先在 Startup.cs的ConfigureServices方法中添加Jwt配置:
services.AddAuthentication(options => { // 身份认证配置 options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(options => { // Jwt认证配置 options.RequireHttpsMetadata = false; options.SaveToken = true; options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = false, ValidateAudience = false, ValidateLifetime = false, ValidateIssuerSigningKey = true, ValidIssuer = Configuration["JwtToken:Issuer"], // Token发行人,网站或公司名称 ValidAudience = Configuration["JwtToken:Issuer"], // Token接收人,同上 // Token密钥,建议为GUID IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JwtToken:SecretKey"])) }; });
在 Configure方法中开启认证
app.UseAuthorization();
app.UseAuthentication();
生成JwtToken的帮助类:
#region Jwt负载信息 /// <summary> /// Jwt负载信息 /// </summary> public class JwtPayloadInfo { /// <summary> /// 发行人 /// </summary> public string Issuer { get; set; } /// <summary> /// 接收人 /// </summary> public string Audience { get; set; } /// <summary> /// 起始时间 /// </summary> public DateTime? NotBefore { get; set; } /// <summary> /// 超时时间 /// </summary> public DateTime? Expires { get; set; } /// <summary> /// 密钥 /// </summary> public string SecretKey { get; set; } /// <summary> /// 参数 /// </summary> public Dictionary<string, string> Claims { get; set; } /// <summary> /// 初始化 /// </summary> public JwtPayloadInfo() { this.Claims = new Dictionary<string, string>(); } } #endregion /// <summary> /// Jwt帮助类 /// </summary> public class JwtHelper { /// <summary> /// 生成Token /// </summary> /// <param name="payload">Jwt负载信息</param> /// <returns></returns> public static string GetToken(JwtPayloadInfo payload) { var claims = new List<Claim>(); if (payload.Claims != null) { foreach (var item in payload.Claims) { claims.Add(new Claim(item.Key, item.Value)); } } var jwt = new JwtSecurityToken( issuer: payload.Issuer, audience: payload.Audience, claims: claims, notBefore: payload.NotBefore, expires: payload.Expires, signingCredentials: new SigningCredentials( new SymmetricSecurityKey(Encoding.UTF8.GetBytes(payload.SecretKey)), SecurityAlgorithms.HmacSha256) ); var token = new JwtSecurityTokenHandler().WriteToken(jwt); return token; } }
用户登录时生成Token,前端请求Api时在Header中加入Authorization: Bearer [Token],注意Token前需要有Bearer标识符
/// <summary> /// 用户控制器 /// </summary> [ApiController] [ApiExplorerSettings(GroupName = "system")] [Route("[controller]/[action]")] public class UserController : ControllerBase { private readonly IConfiguration _configuration; private readonly IHttpContextAccessor _httpContextAccessor; public UserController( IConfiguration configuration, IHttpContextAccessor httpContextAccessor) { _configuration = configuration; _httpContextAccessor = httpContextAccessor; } /// <summary> /// 用户登录 /// </summary> /// <param name="account">账号</param> /// <param name="password">密码</param> /// <returns></returns> [HttpPost] [AllowAnonymous] public string Login(string account, string password) { var userId = "00000001"; var payload = new JwtPayloadInfo() { Issuer = _configuration["JwtToken:Issuer"], Audience = _configuration["JwtToken:Issuer"], NotBefore = DateTime.Now, Expires = DateTime.Now.AddMinutes(60), SecretKey = _configuration["JwtToken:SecretKey"], Claims = new Dictionary<string, string>() { { "UserId", userId } } }; var token = JwtHelper.GetToken(payload); return token; } /// <summary> /// 获取我的用户信息 /// </summary> /// <returns></returns> [HttpGet] [Authorize] public string GetMyUserInfo() { var claim = _httpContextAccessor.HttpContext.User.FindFirst("UserId"); if (claim == null) { throw new Exception("错误的Token信息"); } var userId = claim.Value; return userId; } }
注意需要注入IHttpContextAccessor 时,要在Startup.cs的ConfigureServices方法中添加:
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
在Controller类中给需要认证的方法添加[Authorize]特性,给不需要认证的方法添加[AllowAnonymous]特性,如果需要对所有方法开启认证可以在Startup.cs的Configure方法中添加如下配置:
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers().RequireAuthorization();
});