本溪做网站的,wordpress带支付主题,wordpress插件vip,网站域名更换简介JWT定义了一种紧凑的、自包含的方式#xff0c;用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任#xff0c;因为它是数字签名的。工作流程1、用户使用账号、密码登录应用#xff0c;登录的请求发送到认证服务器。2、认证服务器进行用户验证#xff… 简介JWT定义了一种紧凑的、自包含的方式用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任因为它是数字签名的。工作流程1、用户使用账号、密码登录应用登录的请求发送到认证服务器。2、认证服务器进行用户验证然后创建JWT字符串返回给客户端。3、客户端请求接口时在请求头带上JWT。应用服务器验证JWT合法性如果合法则继续调用应用接口返回结果。数据结构JWT由3部分组成标头(Header)、有效载荷(Payload)和签名(Signature)。在传输的时候会将JWT的3部分分别进行Base64编码后用.进行连接形成最终传输的字符串JWT由3部分组成标头(Header)、有效载荷(Payload)和签名(Signature)。在传输的时候会将JWT的3部分分别进行Base64编码后用.进行连接形成最终传输的字符串JWT一般是这样一个字符串分为三个部分以.隔开xxxxx.yyyyy.zzzzzJWTStringBase64(Header).Base64(Payload).HMACSHA256(base64UrlEncode(header).base64UrlEncode(payload),secret)token认证的优势相⽐于 Session 认证的⽅式来说使⽤ jwt 进⾏⾝份认证主要有下⾯优势1.⽆状态2.有效避免了CSRF 攻击3.适合移动端应⽤4.单点登录友好NETCore使用JWT添加数据访问模拟apiValuesController其中api/value1是可以直接访问的api/value2添加了权限校验特性标签 [Authorize]using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;namespace Demo.Jwt.Controllers
{[ApiController]public class ValuesController : ControllerBase{[HttpGet][Route(api/value1)]public ActionResultIEnumerablestring Get(){return new string[] { value1, value1 };}[HttpGet][Route(api/value2)][Authorize]public ActionResultIEnumerablestring Get2(){return new string[] { value2, value2 };}}
}添加模拟登陆生成Token的apiAuthController这里模拟一下登陆校验只验证了用户密码不为空即通过校验真实环境完善校验用户和密码的逻辑。using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;namespace Demo.Jwt.Controllers
{[Route(api/[controller])][ApiController]public class AuthController : ControllerBase{[AllowAnonymous][HttpGet]public IActionResult Get(string userName, string pwd){if (!string.IsNullOrEmpty(userName) !string.IsNullOrEmpty(pwd)){var claims new[]{new Claim(JwtRegisteredClaimNames.Nbf,${new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds()}) ,new Claim (JwtRegisteredClaimNames.Exp,${new DateTimeOffset(DateTime.Now.AddMinutes(30)).ToUnixTimeSeconds()}),new Claim(ClaimTypes.Name, userName)};var key new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Const.SecurityKey));var creds new SigningCredentials(key, SecurityAlgorithms.HmacSha256);var token new JwtSecurityToken(issuer: Const.Domain,audience: Const.Domain,claims: claims,expires: DateTime.Now.AddMinutes(30),signingCredentials: creds);return Ok(new{token new JwtSecurityTokenHandler().WriteToken(token)});}else{return BadRequest(new { message username or password is incorrect. });}}}
}Startup添加JWT验证的相关配置using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Tokens;
using System;
using System.Text;namespace Demo.Jwt
{public class Startup{public Startup(IConfiguration configuration){Configuration configuration;}public IConfiguration Configuration { get; }// This method gets called by the runtime. Use this method to add services to the container.public void ConfigureServices(IServiceCollection services){//添加jwt验证services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options {options.TokenValidationParameters new TokenValidationParameters{ValidateIssuer true,//是否验证IssuerValidateAudience true,//是否验证AudienceValidateLifetime true,//是否验证失效时间ClockSkew TimeSpan.FromSeconds(30),ValidateIssuerSigningKey true,//是否验证SecurityKeyValidAudience Const.Domain,//AudienceValidIssuer Const.Domain,//Issuer这两项和前面签发jwt的设置一致IssuerSigningKey new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Const.SecurityKey))//拿到SecurityKey};});services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);}// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.public void Configure(IApplicationBuilder app, IHostingEnvironment env){///添加jwt验证app.UseAuthentication();if (env.IsDevelopment()){app.UseDeveloperExceptionPage();}app.UseMvc(routes {routes.MapRoute(name: default,template: {controllerHome}/{actionIndex}/{id?});});}}
}namespace Demo.Jwt
{public class Const{/// summary/// 这里为了演示写死一个密钥。实际生产环境可以从配置文件读取,这个是用网上工具随便生成的一个密钥/// /summarypublic const string SecurityKey MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDI2a2EJ7m872v0afyoSDJT2o1SitIeJSWtLJU8/Wz2m7gStexajkeDLka6DSTy8gt9UwfgVQo6uKjVLG5Ex7PiGOODVqAEghBuS7JzIYU5RvI543nNDAPfnJsas96mSA7L/mD7RTE2drj6hf3oZjJpMPZUQI/B1Qjb5H3K3PNwIDAQAB;public const string Domain http://localhost:5000;}
}在实际开发中需要用下列手段来增加JWT的安全性1、因为JWT是在请求头中传递的所以为了避免网络劫持推荐使用HTTPS来传输更加安全2、JWT的哈希签名的密钥是存放在服务端的所以只要服务器不被攻破理论上JWT是安全的。因此要保证服务器的安全3、JWT可以使用暴力穷举来破解所以为了应对这种破解方式可以定期更换服务端的哈希签名密钥(相当于盐值)。这样可以保证等破解结果出来了你的密钥也已经换了token 过期后如何自动续期1、方式1将 token 过期时间设置为15分钟前端发起请求后端验证 token 是否过期如果过期前端发起刷新token请求后端为前端返回一个新的token前端用新的token发起请求请求成功如果要实现每隔72小时必须重新登录后端需要记录每次用户的登录时间用户每次请求时检查用户最后一次登录日期如超过72小时则拒绝刷新token的请求请求失败跳转到登录页面。另外后端还可以记录刷新token的次数比如最多刷新50次如果达到50次则不再允许刷新需要用户重新授权。2、方式2登录成功以后后端返回 access_token 和 refresh_token客户端缓存此两种token;使用 access_token 请求接口资源成功则调用成功如果token超时客户端携带 refresh_token 调用token刷新接口获取新的 access_token;后端接受刷新token的请求后检查 refresh_token 是否过期。如果过期拒绝刷新客户端收到该状态后跳转到登录页如果未过期生成新的 access_token 返回给客户端。客户端携带新的 access_token 重新调用上面的资源接口。客户端退出登录或修改密码后注销旧的token使 access_token 和 refresh_token 失效同时清空客户端的 access_token 和 refresh_toke。后端实现token过期还可以利用Redis来存储token设置redis的键值对的过期时间。如果发现redis中不存在token的记录说明token已经过期了。