用到的命名空間
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
生成TOKEN方法
[HttpGet("auth")]
public IActionResult Get(Tmodel mod) { if (mod.user == "AngelaDaddy" && mod.pass == "123456") { // push the user’s name into a claim, so we can identify the user later on. var claims = new[] { new Claim(ClaimTypes.Name, mod.user), new Claim(ClaimTypes.Role, "useradmin"), new Claim(ClaimTypes.SerialNumber, "123123123"), new Claim(ClaimTypes.Role, "useradmin1"), new Claim(ClaimTypes.Role, "useradmin2"), new Claim(ClaimTypes.Role, "useradmin3"), new Claim(ClaimTypes.Name, mod.user + "1"), new Claim(ClaimTypes.Name, mod.user + "2"), new Claim(ClaimTypes.Name, mod.user + "3") }; //sign the token using a secret key.This secret will be shared between your API and anything that needs to check that the token is legit. var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["SecurityKey"])); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); //.NET Core’s JwtSecurityToken class takes on the heavy lifting and actually creates the token. /** * Claims (Payload) Claims 部分包含了一些跟這個 token 有關的重要信息。 JWT 標准規定了一些字段,下面節選一些字段: iss: The issuer of the token,token 是給誰的 發送者 audience: 接收的 sub: The subject of the token,token 主題 exp: Expiration Time。 token 過期時間,Unix 時間戳格式 iat: Issued At。 token 創建時間, Unix 時間戳格式 jti: JWT ID。針對當前 token 的唯一標識 除了規定的字段外,可以包含其他任何 JSON 兼容的字段。 * */ var token = new JwtSecurityToken( issuer: "jwttest", audience: "jwttest", claims: claims, notBefore: DateTime.UtcNow, expires: DateTime.UtcNow.AddSeconds(10), signingCredentials: creds); return Ok(new { token = new JwtSecurityTokenHandler().WriteToken(token) }); } return BadRequest("用戶名密碼錯誤"); }
new Claim時,可以設置失效時間 JwtRegisteredClaimNames.Exp,值為Unix時間戳
認證時需要添加生命周期校驗
LifetimeValidator = (DateTime? notBefore, DateTime? expires, SecurityToken securityToken, TokenValidationParameters validationParameters) => expires > DateTime.UtcNow
var d = securityToken as JwtSecurityToken
var res1 = d.Claims.Where(s => s.Type == ClaimTypes.Role && s.Value == "useradmin2").Count()
生成Token時
var token = new JwtSecurityToken(
issuer: "jwttest",
audience: "jwttest",
claims: claims,
notBefore: DateTime.Now,
expires: DateTime.Now.AddSeconds(30),
signingCredentials: creds);
失效時間可以為本地時間或UTC時間
//添加jwt驗證:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,//是否驗證Issuer
ValidateAudience = true,//是否驗證Audience
ValidateLifetime = false,//是否驗證失效時間
ValidateIssuerSigningKey = true,//是否驗證SecurityKey
ValidAudience = "jwttest",//Audience
ValidIssuer = "jwttest",//Issuer,這兩項和前面簽發jwt的設置一致
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["SecurityKey"])),//拿到SecurityKey
LifetimeValidator = (DateTime? notBefore, DateTime? expires, SecurityToken securityToken, TokenValidationParameters validationParameters) => expires > DateTime.UtcNow
//LifetimeValidator = (DateTime? notBefore, DateTime? expires, SecurityToken securityToken, TokenValidationParameters validationParameters) =>
//{
// var d = securityToken as JwtSecurityToken;
// var res1 = d.Claims.Where(s => s.Type == ClaimTypes.Role && s.Value == "useradmin2").Count();
// var res2 = d.Claims.Where(s => s.Type == ClaimTypes.Role && s.Value == "useradmin3").Count();
// var res3 = d.Claims.Where(s => s.Type == ClaimTypes.Name && s.Value == "useradmin2").Count();
// var res4 = d.Claims.Where(s => s.Type == ClaimTypes.Role && s.Value == "useradmin8").Count();
// return expires > DateTime.UtcNow;
//}
};
});
生成TOKEN

using System; using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Text; using IdentityModel; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.IdentityModel.Tokens; [HttpGet("token")] public ActionResult<string> Token(InputData inputData) { var tokenHandler = new JwtSecurityTokenHandler(); var key = Encoding.UTF8.GetBytes("1111111111"); var authTime = DateTime.UtcNow; var expiresAt = authTime.AddSeconds(3000); //// 第一種 //var token = new JwtSecurityToken( // issuer: "發送者(TokenCreate)", // audience: "接收者(TokenServer)", // claims: new Claim[] // { // new Claim("uname", inputData.Username) // }, // notBefore: authTime, // expires: expiresAt, // signingCredentials: new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha512Signature) // ); // 第二種 var tokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(new Claim[] { new Claim(JwtClaimTypes.Audience,"Client2"), //new Claim(JwtClaimTypes.Issuer,"發送者(TokenCreate)"), //new Claim("uname", inputData.Username) }), Expires = expiresAt, SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature) }; var token = tokenHandler.CreateToken(tokenDescriptor); var tokenString = tokenHandler.WriteToken(token); return Ok(new { access_token = tokenString, token_type = "Bearer", profile = new { uname = inputData.Username, upass = inputData.Password, auth_time = new DateTimeOffset(authTime).ToUnixTimeSeconds(), expires_at = new DateTimeOffset(expiresAt).ToUnixTimeSeconds() } }); }
注冊TOKEN

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using IdentityModel; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.IdentityModel.Tokens; namespace WebApiJwtDemo { public class Startup { public Startup(IConfiguration configuration) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddAuthentication(x => { x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }).AddJwtBearer(o => { o.TokenValidationParameters = new TokenValidationParameters { //NameClaimType = JwtClaimTypes.Name, //RoleClaimType = JwtClaimTypes.Role, ValidIssuer = "發送者(TokenCreate)", ValidAudience = "接收者(TokenServer)", IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("abc123!@#abc123!@#abc123!@#")), RequireExpirationTime = true, ClockSkew = TimeSpan.Zero, ValidateLifetime = true /***********************************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 }; }); services.AddAuthorization(options => { options.AddPolicy("Author", policy => { policy.RequireClaim("uname"); }); }); services.AddControllers(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); } } }