dfm*_*tro 6 c# jwt asp.net-core asp.net-core-webapi
我在 ASP.NET Core 2 Web API 项目中使用 JWT 令牌
我的前端 Web 客户端会发送一个 JWT 令牌,它最初是从 Web API 登录 API 中获取的,每个请求都能正常工作。不过,我还有一个离线客户端,它使用相同的 API,最初在线登录,然后离线存储 JWT,仅当用户同步应用程序时(可能是一周后)才发送它。令牌可能已过期或服务器 Web 应用程序在此期间重新启动。
如果 JWT 令牌由于离线客户端过期而失败,我仍然希望调用 Web API 控制器方法并User根据需要的用户名填充 ASP.NET Identity 对象。我将记录此事件,但我还需要过期/无效令牌中的用户名。目前,如果身份验证失败,将不会输入控制器方法,因此我添加一个 [AllowAnonymous] 属性,但这将导致 User.Identity 为空,因为我想要用户名
我的代码:
启动.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication()
.AddJwtBearer(cfg =>
{
cfg.TokenValidationParameters = new TokenValidationParameters()
{
ValidIssuer = _config["Tokens:Issuer"],
ValidAudience = _config["Tokens:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Tokens:Key"]))
};
});
Run Code Online (Sandbox Code Playgroud)
当用户登录时
private IActionResult CreateToken(ApplicationUser user, IList<string> roles)
{
var claims = new List<Claim>
{
new Claim(JwtRegisteredClaimNames.Sub, user.Id.ToString()),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.UniqueName, user.UserName)
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Tokens:Key"]));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
_config["Tokens:Issuer"],
_config["Tokens:Audience"],
claims.ToArray(),
expires: DateTime.Now.AddMinutes(60),
signingCredentials: creds);
var results = new
{
token = new JwtSecurityTokenHandler().WriteToken(token),
expiration = token.ValidTo,
};
return Created("", results);
Run Code Online (Sandbox Code Playgroud)
我确保经过身份验证后,各种 API 调用都会传递 JWT 令牌。
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public class MyController : Controller
{
Run Code Online (Sandbox Code Playgroud)
这允许我使用以下代码捕获登录用户的各种 API 调用
var loggedInUser = User.Identity.Name;
Run Code Online (Sandbox Code Playgroud)
如果 JWT 令牌已过期或无效,如何从该令牌中读取用户名?
如果您希望即使令牌已过期也能通过授权,您只需将其添加到即可禁用生命周期验证TokenValidationParameters
services.AddAuthentication()
.AddJwtBearer(cfg =>
{
cfg.TokenValidationParameters = new TokenValidationParameters()
{
ValidIssuer = _config["Tokens:Issuer"],
ValidAudience = _config["Tokens:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Tokens:Key"]))
//Do not check the expiry of token
ValidateLifetime = false,
};
});
Run Code Online (Sandbox Code Playgroud)
这将确保授权中间件认为令牌有效,并填充User.IdentityMVC 中间件中的对象。
但是,此检查也会禁用您的 Web 客户端的过期检查。您必须确定适当的客户端(不能绝对完成)并检查控制器中的到期时间。
更好的方法是寻找更好的设计来解决您的基本需求。
令牌可能已过期或服务器 Web 应用程序在此期间重新启动
我对这个说法有点困惑。如果服务器 Web 应用程序同时重新启动并且您遇到令牌过期,我假设您正在使用临时签名密钥来签署 JWT 令牌。您应该改用永久签名密钥。
对于离线客户端,您需要长期令牌,请查看刷新令牌。刷新令牌通常具有较长的生命周期,并且可用于将其自身交换为更新的访问令牌。offline_access当指定范围时,标准 oauth2.0 实现会发出刷新令牌。范围名称应指示刷新令牌的常见用例。
您可以在授权服务器上将 Web 客户端和离线客户端配置为两个不同的客户端,从而确保只有离线客户端才会获得刷新令牌。
| 归档时间: |
|
| 查看次数: |
4417 次 |
| 最近记录: |