1.安装jwt nuget包
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.25" /><PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.0.3" />
2.配置jwt信息
builder.Services.AddDistributedMemoryCache();var key = Encoding.ASCII.GetBytes("your_secret_key_hereyour_secret_key_hereyour_secret_key_hereyour_secret_key_hereyour_secret_key_hereyour_secret_key_here");builder.Services.AddAuthentication(options =>{options.DefaultAuthenticateScheme = "JwtBearer";options.DefaultChallengeScheme = "JwtBearer";}).AddJwtBearer("JwtBearer", jwtBearerOptions =>{jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters{ValidateIssuerSigningKey = true,IssuerSigningKey = new SymmetricSecurityKey(key),ValidateIssuer = false,ValidateAudience = false,ValidateLifetime = true,ClockSkew = System.TimeSpan.Zero};});app.UseAuthentication();app.UseAuthorization();
3.登录代码生成token
/// <summary>/// 生成token/// </summary>/// <param name="username"></param>/// <param name="password"></param>/// <returns></returns>[HttpPost]public IActionResult tokensc(string username,string pwd){//...需从数据库获取if(username=!admin&&pwd=="123"){return NotFound("用户名或密码不存在");}var tokenHandler = new JwtSecurityTokenHandler();var key = Encoding.ASCII.GetBytes("your_secret_key_hereyour_secret_key_hereyour_secret_key_hereyour_secret_key_hereyour_secret_key_hereyour_secret_key_here");// 设置过期时间为当前时区的时间加上30分钟var expirationTime = DateTimeOffset.Now.AddMinutes(5);var tokenDescriptor = new SecurityTokenDescriptor{Subject = new ClaimsIdentity(new[]{new Claim(ClaimTypes.Name, username)}),// 其他令牌信息...Expires = expirationTime.UtcDateTime,SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)};var token = tokenHandler.CreateToken(tokenDescriptor);var tokenString = tokenHandler.WriteToken(token);return Ok(new { Token = tokenString });}
4.写一个授权过滤器(解析token)
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Text;namespace webapi
{public class customAuthorizeAttribute : Attribute, IAuthorizationFilter{public void OnAuthorization(AuthorizationFilterContext context){// 获取tokenstring token = context.HttpContext.Request.Headers["token"];// 获取当前用户的角色//var user = context.HttpContext.User;// 获取当前的路由信息var routeData = context.RouteData;// 获取控制器和动作方法名称var controller = routeData.Values["controller"];var action = routeData.Values["action"];//通过角色-控制器-方法,可以开放权限//TODO// 尝试解析tokenif (!TryParseToken(token)){// 如果解析失败,返回 401 Unauthorized 状态码context.Result = new JsonResult("无权限访问"); /*new StatusCodeResult(401)*/;return;}}/// <summary>/// 解析token/// </summary>/// <returns></returns>public bool TryParseToken(string tokens){try{// 这里应该验证用户名和密码var tokenHandler = new JwtSecurityTokenHandler();var key = Encoding.ASCII.GetBytes("your_secret_key_hereyour_secret_key_hereyour_secret_key_hereyour_secret_key_hereyour_secret_key_hereyour_secret_key_here"); // 与创建令牌时使用的密钥相同var tokenValidationParameters = new TokenValidationParameters{ValidateIssuerSigningKey = true,IssuerSigningKey = new SymmetricSecurityKey(key),ValidateIssuer = false,ValidateAudience = false,ValidateLifetime = true};var token = tokens; // 替换为要解析的JWT令牌SecurityToken validatedToken;var principal = tokenHandler.ValidateToken(token, tokenValidationParameters, out validatedToken);var jwtToken = (JwtSecurityToken)validatedToken;// 从令牌中获取声明var username = jwtToken.Claims.First(x => x.Type == "unique_name").Value;var expirationDate = jwtToken.ValidTo;if (expirationDate < DateTime.UtcNow){Console.WriteLine("Token has expired.");}else{Console.WriteLine("Token is still valid.");}return true;}catch (Exception ex){return false;}}}
}
5.在需要的控制器或方法上,使用过滤器(只有token解析成功,没有过期才可以访问接口)
[customAuthorizeAttribute ]
[HttpGet]
public IActionResult Get(){
return ok();
}
6.可以结合IdentityService4身份认证框架使用