Asp.Net Core WebApi中整合Jwt認證
阿新 • • 發佈:2022-05-09
先在 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金鑰,建議為GUIDIssuerSigningKey = 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();
});