JWT驗證一般用戶移動端,因為它不像cookie驗證那樣,沒有授權跳轉到登陸頁面
JWT是json web token的簡稱,在 jwt.io 網址可以看到


新建一個API項目,通過postman 可以訪問:

JWT在命名空間:using Microsoft.AspNetCore.Authentication.JwtBearer;
添加JWT實體類
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace Api.Models { public class JwtSettings { /// <summary> /// Token是誰頒發的 /// </summary> public string Issuer { get; set; } /// <summary> /// Token給那些客戶端去使用 /// </summary> public string Audience { get; set; } /// <summary> /// 用於加密的key 必須是16個字符以上,要大於128個字節 /// </summary> public string SecetKey { get; set; } } }
添加配置文件

添加JWT認證
public void ConfigureServices(IServiceCollection services) { services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); services.Configure<JwtSettings>(Configuration); var jwtSettings = new JwtSettings(); Configuration.Bind("JwtSettings", jwtSettings); services.AddAuthentication(option => { option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(option=> { option.TokenValidationParameters = new TokenValidationParameters { ValidIssuer = jwtSettings.Issuer, ValidAudience = jwtSettings.Audience, IssuerSigningKey=new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.SecetKey))
/***********************************TokenValidationParameters的參數默認值***********************************/
// RequireSignedTokens = true,
// SaveSigninToken = false,
// ValidateActor = false,
// 將下面兩個參數設置為false,可以不驗證Issuer和Audience,但是不建議這樣做。
// ValidateAudience = true,
// ValidateIssuer = true,
// ValidateIssuerSigningKey = false,
// 是否要求Token的Claims中必須包含Expires
// RequireExpirationTime = true,
// 允許的服務器時間偏移量
// ClockSkew = TimeSpan.FromSeconds(300),
// 是否驗證Token有效期,使用當前時間與Token的Claims中的NotBefore和Expires對比
// ValidateLifetime = true }; }); }
添加中間件(Middleware)
app.UseAuthentication();
API接口打上標簽:

然后在postman訪問 就是401 未授權

接下來需要給用戶頒發Token
當用戶登陸成功后,頒發token
創建登陸API和實體類
namespace Api.Models { public class LoginViewModel { [Required] public string user { get; set; } [Required] public string pwd { get; set; } } }
using Api.Models; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens; using System; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Text; namespace Api.Controllers { //[Route("api/[controller]")] //[ApiController] public class AuthorizeController : ControllerBase { private JwtSettings _jwtSettings; public AuthorizeController(IOptions<JwtSettings> jwtSetting) { _jwtSettings = jwtSetting.Value; } [HttpPost] public IActionResult Token([FromBody]LoginViewModel login) { if (ModelState.IsValid) { if (!(login.user == "cnglgos" && login.pwd == "123")) { return BadRequest(); } var claim = new Claim[] { new Claim("name","cnbogs"), new Claim("role","admin") }; var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwtSettings.SecretKey)); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); //neget包:Microsoft.AspNetCore.Authentication.JwtBearer //命名空間: System.IdentityModel.Tokens.Jwt; //第一種方式 var token = new JwtSecurityToken( _jwtSettings.Issuer,// Issuer 頒發者,通常為STS服務器地址 _jwtSettings.Audience,// Audience Token的作用對象,也就是被訪問的資源服務器授權標識 claim, DateTime.Now, //Token生效時間,在此之前不可用 DateTime.Now.AddMinutes(30), //Token過期時間,在此之后不可用 creds); //第二種方式 var descriptor = new SecurityTokenDescriptor { Issuer = _jwtSettings.Issuer, Audience = _jwtSettings.Audience,// Audience Token的作用對象,也就是被訪問的資源服務器授權標識 Subject = new ClaimsIdentity(claim), NotBefore = DateTime.Now, //Token生效時間,在此之前不可用 Expires = DateTime.Now.AddMinutes(30), //Token過期時間,在此之后不可用 SigningCredentials = creds, IssuedAt=DateTime.Now //Token頒發時間 }; var handler = new JwtSecurityTokenHandler(); JwtSecurityToken token1 = handler.CreateJwtSecurityToken(descriptor); return Ok(new { token = new JwtSecurityTokenHandler().WriteToken(token), token1 = handler.WriteToken(token1) }); } return BadRequest(); } public IActionResult Index() { return Ok(); } } }
Postman請求

然后上面的Token 請求 https://localhost:5001/api/values

從headers可以看到,前綴必須是Bearer

我們可以自定義Token,必須繼承接口:ISecurityTokenValidator
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.IdentityModel.Tokens; using System.Collections.Generic; using System.Security.Claims; namespace Api.Models { public class TokenValidtor : ISecurityTokenValidator { public bool CanValidateToken => true; public int MaximumTokenSizeInBytes { get; set; } public bool CanReadToken(string securityToken) { return true; } public ClaimsPrincipal ValidateToken(string securityToken, TokenValidationParameters validationParameters, out SecurityToken validatedToken) { validatedToken = null;
var identity = new ClaimsIdentity(JwtBearerDefaults.AuthenticationScheme);
if (securityToken == "cnblgos")
{
var claim = new List<Claim> {
new Claim("name","cnblogs"),
new Claim("role","admin")
};
identity.AddClaims(claim);
}
var principal = new ClaimsPrincipal(identity);
return principal; } } }
然后在StartUp中修改:
public void ConfigureServices(IServiceCollection services) { services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); /* appsettings.json文件中JwtSettings是單獨的一節, 所以要GetSection方法獲取 */ services.Configure<JwtSettings>(Configuration.GetSection("JwtSettings")); //services.Configure<JwtSettings>(Configuration); var jwtSettings = new JwtSettings(); Configuration.Bind("JwtSettings", jwtSettings); services.AddAuthentication(option => { option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(option => { //option.TokenValidationParameters = new TokenValidationParameters { // ValidIssuer = jwtSettings.Issuer, // ValidAudience = jwtSettings.Audience, // IssuerSigningKey=new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.SecretKey)) option.SecurityTokenValidators.Clear(); option.SecurityTokenValidators.Add(new TokenValidtor()); option.Events = new JwtBearerEvents { OnMessageReceived = context => { var token = context.Request.Headers["token"]; context.Token = token.FirstOrDefault(); return Task.CompletedTask; } }; }); }
//添加Policy和Claim授權
services.AddAuthorization(options => {
options.AddPolicy("nsky", policy => policy.RequireClaim("nsky")); });


Token可以去jwt.io 網站驗證
參考大神的文章:https://www.cnblogs.com/RainingNight/p/jwtbearer-authentication-in-asp-net-core.html
