目录
JWT封装
-
创建JWTSettings类,配置JWT节点,节点下创建SigningKey、ExpireSeconds两个配置项,分别代表JWT的密钥和过期时间(单位:秒)。再创建配置类JWTOptions,包含SigningKey、ExpireSeconds两个属性。
cs"JWT": { "SecKey": "sdl52%sdf45#$^4sd4f44sdf9*((jksd", "ExpireSeconds": 3600 }
cspublic class JWTSettings { public string SecKey { get; set; } public int ExpireSeconds { get; set; } }
-
Nuget:Microsoft.AspNetCore.Authentication.JwtBearer
-
对JWT进行配置
csusing Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.IdentityModel.Tokens; builder.Services.Configure<JWTSettings>(builder.Configuration.GetSection("JWT")); builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(opt => { var jwtOpt=builder.Configuration.GetSection("JWT").Get<JWTSettings>(); byte[] key = Encoding.UTF8.GetBytes(jwtOpt.SecKey); //设置对称秘钥 var secKey = new SymmetricSecurityKey(key); //设置验证参数 opt.TokenValidationParameters = new () { ValidateIssuer = false,//是否验证颁发者 ValidateAudience = false,//是否验证订阅者 ValidateLifetime = true,//是否验证生命周期 ValidateIssuerSigningKey = true,//是否验证签名 IssuerSigningKey = secKey//签名秘钥 }; });
-
Program.cs的app.UseAuthorization()这行代码之前添加app.UseAuthentication()
-
Controller类中进行登录
cs[Route("api/[controller]/[action]")] [ApiController] public class DemoContrller : ControllerBase { private readonly IOptionsSnapshot<JWTSettings> jwtSettingsOpt; public DemoContrller(IOptionsSnapshot<JWTSettings> jwtSettingsOpt) { this.jwtSettingsOpt = jwtSettingsOpt; } [HttpPost] public ActionResult<string> Login(string username, string password) { if (username == "admin" && password == "123") { List<Claim> claims = new List<Claim> { new Claim(ClaimTypes.NameIdentifier, "1"), new Claim(ClaimTypes.Name, username) }; string key = jwtSettingsOpt.Value.SecKey; DateTime expire = DateTime.Now.AddSeconds(jwtSettingsOpt.Value.ExpireSeconds); byte[] keyBytes = Encoding.UTF8.GetBytes(key); var secKey = new SymmetricSecurityKey(keyBytes); var credentials = new SigningCredentials(secKey, SecurityAlgorithms.HmacSha256Signature); var tokenDescriptor = new JwtSecurityToken( claims: claims,//声明 expires: expire,//过期时间 signingCredentials: credentials//签名凭据 ); string jwt = new JwtSecurityTokenHandler().WriteToken(tokenDescriptor); return jwt; } else { return BadRequest("登录失败"); } } }
-
在需要登录才能访问的控制器类或者Action方法上添加[Authorize]。
-
可以使用this.User.FindFirst(ClaimTypes.Name).Value来访问登录用户的身份信息。
-
登录和访问。用PostMan自定义报文头:Authorization的值为"Bearer JWTToken", Authorization的值中的"Bearer"和JWT令牌之间一定要通过空格分隔。前后不能多出来额外的空格、换行等。
[Authorize]的注意事项
- ASP.NET Core中身份验证和授权验证的功能由Authentication、Authorization中间件提供:app.UseAuthentication()、app.UseAuthorization()。
- 控制器类上标注[Authorize],则所有操作方法都会被进行身份验证和授权验证;对于标注了[Authorize]的控制器中,如果其中某个操作方法不想被验证,可以在操作方法上添加[AllowAnonymous]。如果没有在控制器类上标注[Authorize],那么这个控制器中的所有操作方法都允许被自由地访问;对于没有标注[Authorize]的控制器中,如果其中某个操作方法需要被验证,我们也可以在操作方法上添加[Authorize]。
- ASP.NET Core会按照HTTP协议的规范,从Authorization取出来令牌,并且进行校验、解析,然后把解析结果填充到User属性中,这一切都是ASP.NET Core完成的,不需要开发人员自己编写代码。但是一旦出现401,没有详细的报错信息,很难排查,这是初学者遇到的难题。
- RBAC角色控制:可以设置[Authorize(Roles ="admin,user")]来限制角色登录