.net core 3.1 使用jwt完成登录验证

nuget安装:Microsoft.AspNetCore.Authentication.JwtBearer  3.1.0 版本

一、添加配置文件

 "Authentication": {
    "JwtBearer": {
      "IsEnabled": "true",
      "SecurityKey": "Demo_C421AAEE0D114E9C1",
      "Issuer": "Demo",
      "Audience": "Demo",
      "Expiration": 60 //token过期时间 (单位:分钟)
    }
  }

二、添加一个扩展类和jwt配置文件类

 public static class AuthConfigure
    {
        public static void ConfigureJwt(this IServiceCollection services, IConfiguration configuration)
        {
            if (bool.Parse(configuration["Authentication:JwtBearer:IsEnabled"]))
            {
                services.AddAuthentication(options =>
                {
                    options.DefaultAuthenticateScheme = "JwtBearer";
                    options.DefaultChallengeScheme = "JwtBearer";
                }).AddJwtBearer("JwtBearer", options =>
                {
                    options.Audience = configuration["Authentication:JwtBearer:Audience"];

                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        // The signing key must match!
                        ValidateIssuerSigningKey = true,
                        IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(configuration["Authentication:JwtBearer:SecurityKey"])),

                        // Validate the JWT Issuer (iss) claim
                        ValidateIssuer = true,
                        ValidIssuer = configuration["Authentication:JwtBearer:Issuer"],

                        // Validate the JWT Audience (aud) claim
                        ValidateAudience = true,
                        ValidAudience = configuration["Authentication:JwtBearer:Audience"],

                        // Validate the token expiry
                        ValidateLifetime = true,

                        // If you want to allow a certain amount of clock drift, set that here
                        ClockSkew = TimeSpan.Zero
                    };
                });
            }
        }
    }
 public class JwtConfig
    {
        /// <summary>
        /// 密钥
        /// </summary>
        public string SecurityKey { get; set; }
        /// <summary>
        /// 所属者
        /// </summary>
        public string Issuer { get; set; }

        public string Audience { get; set; }

        /// <summary>
        /// 过期时间
        /// </summary>
        public int Expiration { get; set; }
    }

三、配置Startup

public void ConfigureServices(IServiceCollection services)
{
    //注入JWT配置文件
    services.Configure<JwtConfig>(Configuration.GetSection("Authentication:JwtBearer"));
    //var provider = context.Services.BuildServiceProvider();
    //var config = provider.GetRequiredService<IOptions<JwtConfig>>().Value;
    //配置jwt,函数里面也可以使用上面两行注释掉的代码的方式获取配置
    services.ConfigureJwt(Configuration);
    services.AddControllers();
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseHttpsRedirection();
    app.UseRouting();
    app.UseAuthentication(); //一定要在这个位置(app.UseAuthorization()上面)
    app.UseAuthorization();
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
    });
}

四、登录接口

在需要验证的接口上加特性:[Authorize]

        private readonly JwtConfig jwtModel = null;
        public JwtLoginController(IOptions<JwtConfig> _jwtModel)//注入jwt配置参数
        {
            jwtModel = _jwtModel.Value;
        }       

         /// <summary>
        /// 登录
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public async Task<string> Login(LoginDto dto)
        {
            //一波验证逻辑。。。。。。
            
            //下面代码自行封装
            var claims = new List<Claim>();
            claims.AddRange(new[]
            {
                new Claim("UserName", dto.UserName),
                new Claim(JwtRegisteredClaimNames.Sub, dto.UserName),
                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
                new Claim(JwtRegisteredClaimNames.Iat, DateTimeOffset.Now.ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64)
            });

            DateTime now = DateTime.UtcNow;
            var jwtSecurityToken = new JwtSecurityToken(
                issuer: jwtModel.Issuer,
                audience: jwtModel.Audience,
                claims: claims,
                notBefore: now,
                expires: now.Add(TimeSpan.FromMinutes(jwtModel.Expiration)),
                signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.ASCII.GetBytes(jwtModel.SecurityKey)), SecurityAlgorithms.HmacSha256)
            );
            
            string token = new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken);

            return token;
        }

        public class LoginDto
        {
            public string UserName { get; set; }
            public string Password { get; set; }
        }

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
使用 JWT 进行身份验证时,通常会设置一个过期时间,以确保用户在一段时间内保持登录状态。当 JWT 过期时,用户需要重新登录并获取新的 JWT 令牌。为了避免用户频繁重新登录,我们可以使用刷新令牌的方式来延长用户的登录状态。 在 .NET Core 3.1 中,我们可以使用 JwtSecurityTokenHandler 类来生成和验证 JWT 令牌。下面是一个简单的 JwtHelper 类的实现,它支持生成、刷新和验证 JWT 令牌: ```csharp using Microsoft.IdentityModel.Tokens; using System; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Text; public class JwtHelper { private static readonly string secret = "your_secret_key_here"; private static readonly string issuer = "your_issuer_here"; private static readonly int expireMinutes = 30; private static readonly int refreshExpireMinutes = 60; public static string GenerateToken(string userId) { var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret)); var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256); var claims = new[] { new Claim(ClaimTypes.NameIdentifier, userId) }; var tokenDescriptor = new SecurityTokenDescriptor { Issuer = issuer, Audience = issuer, Subject = new ClaimsIdentity(claims), Expires = DateTime.UtcNow.AddMinutes(expireMinutes), SigningCredentials = credentials }; var tokenHandler = new JwtSecurityTokenHandler(); var token = tokenHandler.CreateToken(tokenDescriptor); return tokenHandler.WriteToken(token); } public static string RefreshToken(string token) { var tokenHandler = new JwtSecurityTokenHandler(); var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret)); try { var claimsPrincipal = tokenHandler.ValidateToken(token, new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidIssuer = issuer, ValidAudience = issuer, IssuerSigningKey = securityKey, ValidateLifetime = false }, out SecurityToken validatedToken); var jwtToken = validatedToken as JwtSecurityToken; if (jwtToken == null || !jwtToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCultureIgnoreCase)) { throw new SecurityTokenException("Invalid token"); } var userId = claimsPrincipal.FindFirst(ClaimTypes.NameIdentifier).Value; return GenerateToken(userId); } catch(Exception ex) { throw new SecurityTokenException("Invalid token", ex); } } public static bool ValidateToken(string token) { var tokenHandler = new JwtSecurityTokenHandler(); var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secret)); try { var claimsPrincipal = tokenHandler.ValidateToken(token, new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidIssuer = issuer, ValidAudience = issuer, IssuerSigningKey = securityKey, ValidateLifetime = true, ClockSkew = TimeSpan.Zero }, out SecurityToken validatedToken); var jwtToken = validatedToken as JwtSecurityToken; if (jwtToken == null || !jwtToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha256, StringComparison.InvariantCultureIgnoreCase)) { throw new SecurityTokenException("Invalid token"); } return true; } catch(Exception) { return false; } } } ``` 在上面的代码中,我们定义了一个静态的 secret 字符串来存储 JWT 的密钥,一个 issuer 字符串来存储 JWT 的发行者,以及一个 expireMinutes 和 refreshExpireMinutes 来分别设置 JWT 令牌和刷新令牌的过期时间。在 GenerateToken 方法中,我们使用 JwtSecurityTokenHandler 类来创建一个 JWT 令牌,并设置其过期时间和签名凭证。在 RefreshToken 方法中,我们首先验证传入的 JWT 令牌是否有效,并提取其中的用户 ID。然后,我们使用 GenerateToken 方法来生成一个新的 JWT 令牌。在 ValidateToken 方法中,我们验证传入的 JWT 令牌是否有效,并返回一个布尔值表示验证结果。 使用 JwtHelper 类非常简单,只需要调用其中的 GenerateToken、RefreshToken 和 ValidateToken 方法即可。下面是一个示例: ```csharp var token = JwtHelper.GenerateToken("user_id"); var isValid = JwtHelper.ValidateToken(token); var refreshedToken = JwtHelper.RefreshToken(token); ``` 需要注意的是,由于 JWT 令牌是无状态的,因此在刷新令牌时,我们需要使用一些外部存储机制(如数据库或缓存)来存储每个用户的刷新令牌。当用户请求刷新令牌时,我们可以从外部存储中检索出用户的刷新令牌,并验证其有效性后生成新的 JWT 令牌。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值