.net core 2.1 基于Jwt的登录认证
1.新建一个.net core2.1 基于 api 的工程,引用Microsoft.AspNetCore.Authentication.JwtBearer 包
2.新建一个Token的实体类,一个Jwt的基础类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class TokenModel { /// <summary> /// 用户Id /// </summary> public long userId { get; set; } /// <summary> /// 用户名 /// </summary> public string userCode { get; set; } /// <summary> /// 手机 /// </summary> public string phone { get; set; } /// <summary> /// 头像 /// </summary> public string icon { get; set; } /// <summary> /// 昵称 /// </summary> public string userName { get; set; } /// <summary> /// 身份 /// </summary> public string sub { get; set; } /// <summary> /// 角色 /// </summary> public string role { get; set; } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/// <summary> /// 基础配置 /// </summary> public class JwtSettings { //token是谁颁发的 public string Issuer { get; set; } //token可以给哪些客户端使用 public string Audience { get; set; } //加密的key public string SecretKey { get; set; } //过期时间 单位:s public string ExpireTime { get; set; } }
3.在Appsetting.json中添加默认值
"JwtSettings": { "Issuer": "NinaMua", "Audience": "http://localhost:5000", "SecretKey": "NinaMua'sSecretKeyMuaMuaMua",//16位字符以上 "ExpireTime": "3600" //过期时间||单位:s }
4.新建一个类去把在appsetting设定的值变成一个可以全局引用的对象
public class AppSettingsInit { public static JwtSettings JwtSettings; /// <summary> /// 将配置项的值赋值给属性 /// </summary> /// <param name="configuration"></param> public void Initial(IConfiguration configuration) { JwtSettings = new JwtSettings(); JwtSettings.Audience = configuration["JwtSettings:Audience"]; JwtSettings.Issuer = configuration["JwtSettings:Issuer"]; JwtSettings.SecretKey = configuration["JwtSettings:SecretKey"]; JwtSettings.ExpireTime = configuration["JwtSettings:ExpireTime"]; } }
5.去新增一个JwtTokenHelper类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public class JwtTokenHelper { public static JwtSecurityTokenHandler _jwt = new JwtSecurityTokenHandler(); /// <summary> /// 颁发JWT字符串 /// </summary> /// <param name="tokenModel"></param> /// <returns></returns> public static string IssueJwt(TokenModel tokenModel) { var encodedJwt = ""; try { var claims = new Claim[] { new Claim("userId", tokenModel.userId.ToString()), new Claim("userCode", tokenModel.userCode), new Claim("phone", tokenModel.phone), new Claim("userName", tokenModel.userName), new Claim("role", tokenModel.role), new Claim("tokenType", tokenModel.tokenType.ToString()) }; DateTime expTime = DateTime.Now.AddSeconds(Convert.ToDouble(AppSettingsInit.JwtSettings.ExpireTime)); //秘钥 var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(AppSettingsInit.JwtSettings.SecretKey)); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var jwt = new JwtSecurityToken( issuer: AppSettingsInit.JwtSettings.Issuer, audience: AppSettingsInit.JwtSettings.Audience, claims: claims, expires: expTime,//过期时间 signingCredentials: creds); encodedJwt = _jwt.WriteToken(jwt); } catch (Exception ex) { } if (encodedJwt != "") encodedJwt = $"{JwtBearerDefaults.AuthenticationScheme} {encodedJwt}"; return encodedJwt; } /// <summary> /// 解析jwt字符串 /// </summary> /// <param name="jwtStr"></param> /// <returns></returns> public static TokenModel SerializeJWT(string jwtStr) { var tm = new TokenModel(); JwtSecurityToken jwtToken = _jwt.ReadJwtToken(jwtStr); try { var JwtList = jwtToken.Payload; tm.userCode = JwtList["userCode"]?.ToString(); tm.userId = Convert.ToInt64(JwtList["userId"]); tm.userCode = JwtList["userCode"]?.ToString(); tm.phone = JwtList["phone"]?.ToString(); tm.userName = JwtList["userName"]?.ToString(); tm.role = JwtList["role"]?.ToString(); } catch (Exception e) { // ignored } return tm; } }
6.在startup.cs中的ConfigureServices注入依赖
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
public void ConfigureServices(IServiceCollection services) { #region 配置登录授权 services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }).AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, (jwtBearerOptions) => { jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters { //需要跟生成Token的信息保持一致 ValidateIssuerSigningKey = true,//验证全局秘匙||默认True IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.UTF8.GetBytes(AppSettingsInit.JwtSettings.SecretKey)), ValidateIssuer = true,//验证发布者||默认True ValidIssuer = AppSettingsInit.JwtSettings.Issuer, ValidateAudience = true,//验证访问者||默认True ValidAudience = AppSettingsInit.JwtSettings.Audience, ValidateLifetime = true,//验证生命周期||默认True ClockSkew = TimeSpan.Zero }; }); #endregion services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); #region 配置Swagger services.AddSwaggerGen(c => { #region 顶部基础信息 c.SwaggerDoc("v1", new Info { Version = "v1.1.0", Title = "WebAPI", Description = "API帮助文档", TermsOfService = "None", Contact = new Swashbuckle.AspNetCore.Swagger.Contact { Name = "NinaMua", Email = "791016081@qq.com", Url = "http://www.cnblogs.com/NinaMua" } }); #endregion #region 权限验证信息 //添加一个必须的全局安全信息,和AddSecurityDefinition方法指定的方案名称要一致 var security = new Dictionary<string, IEnumerable<string>> { { "Bearer", new string[] { } } }; c.AddSecurityRequirement(security); c.AddSecurityDefinition("Bearer", new ApiKeyScheme { Description = "格式|Bearer {token}", Name = "Authorization",//jwt默认的参数名称 In = "header",//jwt默认在请求头中存放Authorization信息 Type = "apiKey" }); #endregion #region 添加读取注释服务 //添加对控制器的标签(描述)通过对SwaggerDocTag添加备注 //c.DocumentFilter<SwaggerDocTag>(); var basePath = AppDomain.CurrentDomain.BaseDirectory; var apiXmlPath = Path.Combine(basePath, "TestApi.xml"); if (System.IO.File.Exists(apiXmlPath)) c.IncludeXmlComments(apiXmlPath, true);//控制器层注释(true表示显示控制器注释) var entityXmlPath = Path.Combine(basePath, "TestEntity.xml"); if (System.IO.File.Exists(entityXmlPath)) c.IncludeXmlComments(entityXmlPath);//实体类注释 #endregion }); #endregion }
7.在startup.cs中的Configure注入中间件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseHsts(); } app.UseHttpsRedirection(); app.UseAuthentication();//配置授权 loggerFactory.AddNLog();//添加NLog env.ConfigureNLog("nlog.config");//读取Nlog配置文件 #region Swagger app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "ApiHelp V1"); }); #endregion app.UseMvc(); }
8.在api接口上加上权限认证[Authorize]
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
[Route("api/")] public class LoginController : BaseApiController { public ILogger<LoginController> logger; /// <param name="_logger">日志</param> public LoginController(ILogger<LoginController> _logger) { logger = _logger; } /// <summary> /// 登录 /// </summary> /// <returns></returns> [Route("Login")] [HttpGet] public ResponseMessage Login() { ///用户是否存在/// TokenModel temp = new TokenModel(); temp.userName = "系统管理员"; temp.userCode = "system"; temp.role = "Admin"; temp.phone = ""; temp.icon = ""; var result = JwtTokenHelper.IssueJwt(temp); if (result != "") return Success(result); else return CustomizeResponse(100, "登录失败"); } /// <summary> /// 退出 /// </summary> /// <returns></returns> [HttpGet] [Route("SignOut")] [Authorize] public string Exit() { return "1111"; } }
9.测试
在没有token的请求中~请求接口401
拿到token后放在全局之中