參照:https://www.cnblogs.com/sunnytrudeau/p/9693512.html
MVC部分的登錄不贅述,主要是JwtBearer混合部分的問題。
- 創建JwtSettings類:
/// <summary> /// JWT授權的配置項 /// </summary> public class JwtSettings { public JwtSettings() { //CreateKey(); } /// <summary> /// 誰頒發的 /// </summary> public string Issuer { get; set; } /// <summary> /// 頒發給誰 /// </summary> public string Audience { get; set; } /// <summary> /// 令牌密碼 /// </summary> public string SecurityKey { get; set; } public int ExpiresMinute { get; set; } = 1440; //默認一天 ///對稱秘鑰 public SymmetricSecurityKey Key { get { return new SymmetricSecurityKey(Encoding.UTF8.GetBytes(SecurityKey)); } } ///數字簽名 public SigningCredentials Credentials { get { return new SigningCredentials(Key, SecurityAlgorithms.HmacSha256); } } ///修改密碼,重新創建數字簽名 public void SetSecurityKey(string value) { SecurityKey = value; //CreateKey(); } //private void CreateKey() //{ // Key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(SecurityKey)); // Credentials = new SigningCredentials(Key, SecurityAlgorithms.HmacSha256); //} } }
- appsettings.json中加入配置信息
"JwtSettings": {
"Issuer": "server",
"Audience": "client",
"ExpiresMinute": 10080, //超時分鍾數,7天
"SecurityKey": "69f48e18-3409-40ce-b7a7-8c0362245cf8" //不少於16位長度
},
- 修改Startup.cs中認證內容
#region Authentication var jwtSettings = Configuration.GetSection("JwtSettings").Get<JwtSettings>(); services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, opts => { opts.AccessDeniedPath = "/Account/Login"; opts.Cookie.HttpOnly = true; opts.LoginPath = "/Account/Login"; opts.Cookie.Name = MyConsts.AuthCookieName; }) .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, opts => { opts.RequireHttpsMetadata = false; //無需https //x.SaveToken = true; opts.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = jwtSettings.Key, ValidateIssuer = true, ValidIssuer = jwtSettings.Issuer, ValidateAudience = true, ValidAudience = jwtSettings.Audience, ValidateLifetime = true, ClockSkew = TimeSpan.FromMinutes(5) }; }); #endregion
- APIController中增加一個Login方法的Controller,用於登錄並返回token
[Route("api/[controller]")] [ApiController] public class AccountController : ControllerBase { .... /// <summary> /// 登錄方法,默認7天超時 /// </summary> /// <param name="UserName">用戶名</param> /// <param name="Password">密碼</param> /// <returns></returns> [HttpGet,HttpPost] [Route("Login")] public async Task<IActionResult> LoginAsync(string UserName, string Password) { ..... var claims = new Claim[] { new Claim(ClaimTypes.Sid, UserName), new Claim(ClaimTypes.Name, UserName), new Claim(ClaimTypes.Role, "user"), new Claim("guid",user.Id.ToString()), new Claim("avatar",""), //new Claim("displayName",user.NameDisplay), //new Claim("loginName",user.Account), //new Claim("emailAddress",""), //new Claim("userType",IsAdmin ? "1": "0") }; var token = JwtBearerAuthenticationExtension.GetJwtAccessToken(claims); rp.SetData(token); return Ok(rp); } }
- 加入api的路由
#region 路由 app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}") .RequireAuthorization(); endpoints.MapControllerRoute( name: "apiDefault", pattern: "api/{controller=Home}/{action=Index}/{id?}"); }); #endregion
- 為ValuesController加入登錄驗證,並使用HttpContext獲取當前登錄用戶
[Route("api/[controller]")] [ApiController] [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] public class ValuesController : ControllerBase { /// <summary> /// 獲取所有values,GET api/values /// </summary> /// <returns></returns> [HttpGet] public ActionResult<IEnumerable<string>> Get() { var current = MyHttpContext.Current; return new string[] { current.User.Identity.Name, current.User.Claims.Count().ToString() }; } }
驗證,以下是Swagger的截圖,Postman等也一樣:
- 未登錄時:
- 登錄獲取Token
- 將該Token前面加Bearer作為傳入Header中的Authorization中,
- 再次執行Values
調用成功。
總結:MVC的Controller使用
.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie
塊的邏輯,ApiController使用AddJwtBearer部分邏輯,具體可以在Controller的Attribute
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
上切換。