JWT权限认证是目前系统开发常用的组件,接下来我们就给webAPI项目集成一下JWT,至于JWT实现的原理百度一大堆,自己可以找有针对性的文章,看一下就行了。
创建一个简单的POCO类,用来存储签发或者验证jwt时用到的信息:
public class TokenManagement { /// <summary> /// /// </summary> [JsonProperty("secret")] public string Secret { get; set; } /// <summary> /// /// </summary> [JsonProperty("issuer")] public string Issuer { get; set; } /// <summary> /// /// </summary> [JsonProperty("audience")] public string Audience { get; set; } /// <summary> /// /// </summary> [JsonProperty("accessExpiration")] public int AccessExpiration { get; set; } /// <summary> /// /// </summary> [JsonProperty("refreshExpiration")] public int RefreshExpiration { get; set; } }
然后创建一个接口,用来实现依赖注入:
public interface IAuthenticateService { /// <summary> /// /// </summary> /// <param name="request"></param> /// <param name="token"></param> /// <returns></returns> bool IsAuthenticated(LoginRequest request, out string token); }
创建一个实现类来集成IAuthenticateService:
public class TokenAuthenticationService : IAuthenticateService { private readonly TokenManagement _tokenManagement; /// <summary> /// / /// </summary> /// <param name="tokenManagement"></param> public TokenAuthenticationService(IOptions<TokenManagement> tokenManagement) { _tokenManagement = tokenManagement.Value; } /// <summary> /// /// </summary> /// <param name="request"></param> /// <param name="token"></param> /// <returns></returns> public bool IsAuthenticated(LoginRequest request, out string token) { token = string.Empty; // if (!_userService.IsValid(request)) // return false; var claims = new[] { new Claim(ClaimTypes.Name,request.Username) }; var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_tokenManagement.Secret)); var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var jwtToken = new JwtSecurityToken(_tokenManagement.Issuer, _tokenManagement.Audience, claims, expires: DateTime.Now.AddMinutes(_tokenManagement.AccessExpiration), signingCredentials: credentials); token = new JwtSecurityTokenHandler().WriteToken(jwtToken); return true; } }
然后在startup中ConfigureServices方法中注册:
//JWT注册 services.Configure<TokenManagement>(Configuration.GetSection("tokenManagement")); var token = Configuration.GetSection("tokenManagement").Get<TokenManagement>(); services.AddAuthentication(x => { x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }).AddJwtBearer(x => { x.RequireHttpsMetadata = false; x.SaveToken = true; x.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(token.Secret)), ValidIssuer = token.Issuer, ValidAudience = token.Audience, ValidateIssuer = false, ValidateAudience = false }; }); services.AddScoped<IAuthenticateService, TokenAuthenticationService>(); services.AddHealthChecks(); //添加健康检查,.net core自带的
appsettings.json配置:
"tokenManagement": { "secret": "123456123456123456", "issuer": "webapi.cn", "audience": "WebApi", "accessExpiration": 30, "refreshExpiration": 60 },
用户登录认证模型:
public class LoginRequest { /// <summary> /// / /// </summary> [Required] [JsonProperty("username")] public string Username { get; set; } /// <summary> /// /// </summary> [Required] [JsonProperty("password")] public string Password { get; set; } }
控制器:
using Core.Net.Common.Core.Net.Core.Security; using Core.Net.IServices; using Core.Net.Model.System; using Core.Net.WebApi.Common.JWT; using Core.Net.WebApi.Dtos.Login; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace Core.Net.WebApi.Controllers.Login { /// <summary> /// /// </summary> [Route("api/[controller]/[action]")] [ApiController] public class AuthenticationController : ControllerBase { [JsonIgnore] private readonly IAuthenticateService _authService; [JsonIgnore] private readonly ICoreNetSystemUserServices _coreNetSystemUserServices; /// <summary> /// /// </summary> /// <param name="authService"></param> /// <param name="coreNetSystemUserServices"></param> public AuthenticationController(IAuthenticateService authService, ICoreNetSystemUserServices coreNetSystemUserServices) { _authService = authService; _coreNetSystemUserServices = coreNetSystemUserServices; } /// <summary> /// /// </summary> /// <param name="request"></param> /// <returns></returns> [AllowAnonymous] [HttpPost] public ActionResult RequestToken([FromBody] LoginRequest request) { if (!ModelState.IsValid) { return BadRequest("Invalid Request"); } string token; CoreNetSystemUser user = _coreNetSystemUserServices.GetEntityOne(p => p.UserName == request.Username); string password = Md5.Md5Upper32(request.Password); if (user != null && password == user.Passward && user.IsUse == 1) { if (_authService.IsAuthenticated(request, out token)) { return Ok(token); } } else { return BadRequest("用户名和密码错误!"); } return BadRequest("认证失败"); } } }
using Core.Net.Common.Core.Net.Core; using Core.Net.IServices; using Core.Net.Model.System; using Core.Net.WebApi.Dtos; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace Core.Net.WebApi.Controllers.Login { /// <summary> /// 登录功能 /// </summary> [Route("api/[controller]/[action]")] [ApiController] public class LoginController : Controller { /// <summary> /// 用户 /// </summary> [JsonIgnore] public readonly ICoreNetSystemUserServices _coreNetSystemUserServices; /// <summary> /// 依赖注入对象实例 /// </summary> /// <param name="coreNetSystemUserServices"></param> public LoginController(ICoreNetSystemUserServices coreNetSystemUserServices) { _coreNetSystemUserServices = coreNetSystemUserServices; } /// <summary> /// 登录方法 /// </summary> /// <returns></returns> [HttpGet] public IActionResult Index() { return Ok(_coreNetSystemUserServices.FindList("UserId",false).ToJson()); } /// <summary> /// / /// </summary> /// <param name="entity">用户实体</param> /// <returns></returns> [HttpGet] [Authorize] public WebApiCallBack Index1([FromBody] CoreNetSystemUser entity) { var jm = new WebApiCallBack(); jm.status = true; jm.msg = "请求成功!"; return jm; } } }
如何哪一个api接口需要认证的话,只需要将方法上面加上[Authorize]
运行后效果是: