.NetCore JWT token过期时间设置

本文介绍如何在.NET Core项目中生成JWT并配置身份验证中间件。包括创建token的方法、Startup类中的配置细节及解决token过期后仍被接受的问题。

一、生成token

public string CreateToken(UserDto input)
{
            var tokenHandler = new JwtSecurityTokenHandler();
            var authTime = DateTime.Now;
            var expiresAt = authTime.AddHours(_myOptions.AccessTokenTime);//到期时间
            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(new Claim[]
                {
                    new Claim(JwtClaimTypes.Audience,"api"),
                    new Claim(JwtClaimTypes.Issuer,"KouBei"),
                    new Claim(JwtClaimTypes.Id, input.Id),
                    new Claim(JwtClaimTypes.PhoneNumber, input.Phone),
                    new Claim(JwtClaimTypes.NotBefore, $"{new DateTimeOffset(authTime).ToUnixTimeSeconds()}"),//token生效时间
                    new Claim(JwtClaimTypes.Expiration, $"{new DateTimeOffset(expiresAt).ToUnixTimeSeconds()}")//到期时间,按秒数计算
                }),
                IssuedAt = DateTime.Now,//token生成时间
                Expires = expiresAt,
                NotBefore = authTime,
                SigningCredentials = new SigningCredentials(symmetricKey, SecurityAlgorithms.HmacSha256Signature)//密钥和加密方式
            };
            var token = tokenHandler.CreateToken(tokenDescriptor);
            var tokenString = tokenHandler.WriteToken(token);
            return tokenString;
}

二、Startup 配置

ConfigureServices方法中:

  services.AddAuthentication(x =>
            {
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(o =>
            {
                o.Events = new JwtBearerEvents()
                {
                    OnMessageReceived = context =>
                    {
                        context.Token = context.Request.Query["AccessToken"];
                        return Task.CompletedTask;
                    }
                };
                o.SaveToken = true;
                o.TokenValidationParameters = new TokenValidationParameters
                {
                    NameClaimType = JwtClaimTypes.Name,
                    RoleClaimType = JwtClaimTypes.Role,

                    ValidIssuer = "KouBei",
                    ValidAudience = "api",
                    IssuerSigningKey = symmetricKey,
                    // 是否验证Token有效期,使用当前时间与Token的Claims中的NotBefore和Expires对比
                    ValidateLifetime = true,
                    //注意这是缓冲过期时间,总的有效时间等于这个时间加上jwt的过期时间,如果不配置,默认是5分钟
                    ClockSkew = TimeSpan.FromSeconds(4)

                };
});

c# - .NetCore JwtBearerAuthentication 不拒绝过期的 token

我正在生成 JWT 以用于我的 WebApi 项目。我将 token 设置为在一分钟内过期,以便我可以测试它在过期日期之后提交时是否拒绝 token

CreateToken Controller

public async Task<IActionResult> CreateToken([FromBody] CredentialModel model)
{
    var user = await _unitOfWork.UserManager.FindByNameAsync(model.UserName);

    if (user == null) return BadRequest();
    if (Hasher.VerifyHashedPassword(user, user.PasswordHash, model.Password) != PasswordVerificationResult.Success) return BadRequest();

    var userClaims = await UserManager.GetClaimsAsync(user);

    var claims = new[]
    {
        new Claim(JwtRegisteredClaimNames.Sub, user.UserName),
        new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
        new Claim(JwtRegisteredClaimNames.Iat, DateTime.UtcNow.ToString()),
        new Claim(JwtRegisteredClaimNames.GivenName, user.FirstName), 
        new Claim(JwtRegisteredClaimNames.FamilyName, user.LastName),
        new Claim(JwtRegisteredClaimNames.Email, user.Email)
    }
    .Union(userClaims);

    var cert = new Certificate(Configuration["Tokens:Certificate"]);
    var token = new JwtSecurityToken(
        issuer: Configuration["Tokens:Issuer"],
        audience: Configuration["Tokens:Audience"],
        claims: claims,
        expires: DateTime.UtcNow.AddMinutes(1),
        signingCredentials: cert.Signature
    );

    return Ok(new
    {
        token = new JwtSecurityTokenHandler().WriteToken(token),
        expiration = token.ValidTo
    });
}

token 认证-启动类

app.UseJwtBearerAuthentication(new JwtBearerOptions()
{
    AutomaticAuthenticate = true,
    AutomaticChallenge = true,
    TokenValidationParameters = new TokenValidationParameters()
    {
        ValidIssuer = Configuration["Tokens:Issuer"],
        ValidAudience = Configuration["Tokens:Audience"],
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new Certificate(Configuration["Tokens:Certificate"]).SecurityKey,
        ValidateLifetime = true
    },
});

尽管我设置了 validateLifetime = true ,但两分钟后 token 不会被拒绝。它将继续接受 token 。是否有我不知道的最短到期时间或我的设置错误?

ClockSkew 的默认值为 5 分钟。

app.UseJwtBearerAuthentication(new JwtBearerOptions()
{
    AutomaticAuthenticate = true,
    AutomaticChallenge = true,
    TokenValidationParameters = new TokenValidationParameters()
    {
        ValidIssuer = Configuration["Tokens:Issuer"],
        ValidAudience = Configuration["Tokens:Audience"],
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new Certificate(certPath: Configuration["Tokens:Certificate"], isValid: false).SecurityKey,
        ValidateLifetime = true,
        ValidateIssuer = true,
        ValidateAudience = true,
        ClockSkew = TimeSpan.Zero
    },
});
### JWT Token 过期时间设置 - **在 Payload 中设置**:JWT 的 Payload 里面可以设置一个过期时间,在用户每次访问的时候更新这个过期时间。由于 JWT 的 secret 加密机制,只要 `exp` 变了,整个 Token 就变了,相当于每次重新颁发了一个新的 Token [^1]。 - **.NetCore设置**:在 .NetCore 里,可通过代码设置过期时间。示例代码如下: ```csharp public string CreateToken(UserDto input) { var tokenHandler = new JwtSecurityTokenHandler(); var authTime = DateTime.Now; var expiresAt = authTime.AddHours(_myOptions.AccessTokenTime); // 到期时间 var tokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(new Claim[] { new Claim(JwtClaimTypes.Audience, "api"), new Claim(JwtClaimTypes.Issuer, "KouBei"), new Claim(JwtClaimTypes.Id, input.Id), new Claim(JwtClaimTypes.PhoneNumber, input.Phone), new Claim(JwtClaimTypes.NotBefore, $"{new DateTimeOffset(authTime).ToUnixTimeSeconds()}"), // token 生效时间 new Claim(JwtClaimTypes.Expiration, $"{new DateTimeOffset(expiresAt).ToUnixTimeSeconds()}") // 到期时间,按秒数计算 }) }; // 后续代码省略 } ``` [^2] - **PHP Laravel 中设置**:在 Laravel 里,默认在 `config/jwt.php` 中通过 `ttl` 设置令牌的到期时间,单位为分钟,默认是 1 小时。若要动态更改,可将 `exp` 添加为自定义声明。示例代码如下: ```php $token = JWTAuth::attempt($credentials, ['exp' => Carbon\Carbon::now()->addDays(7)->timestamp]); ``` 上述代码创建了一个在 7 天后到期的令牌,这里只需要一个 Unix 时间戳 [^3]。 ### JWT Token 过期时间的管理 - **定期刷新**:在用户持续使用系统时,可以定期刷新 Token过期时间,以保持用户的登录状态。比如,在用户每次进行重要操作时,重新生成一个新的 Token 并返回给客户端。 - **过期处理**:当客户端携带过期的 Token 进行请求时,服务器需要进行相应的处理。可以返回特定的错误码给客户端,客户端根据错误码提示用户重新登录。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值