在 .net core web api 中存储 JWT 令牌的位置?

Tej*_*jas 5 authentication api jwt

我正在使用 web api 来访问数据,我想对 web api 进行身份验证和授权。为此,我正在使用 JWT 令牌身份验证。但我不知道应该在哪里存储访问令牌?

我想做的事?

1)登录后存储令牌

2)如果用户想访问任何web api方法,请检查该用户的令牌是否有效,如果有效则授予访问权限。

我知道两种方式

1)使用cookies

2)sql server 数据库

哪一种是从上面存储令牌的更好方法?

Mph*_*nge 5

或者,如果您只想使用 JWT 进行身份验证,则实现会略有不同

services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
    options.Events = new JwtBearerEvents
    {
        OnTokenValidated = context =>
        {
            var user = context.Principal.Identity.Name;
            //Grab the http context user and validate the things you need to
            //if you are not satisfied with the validation fail the request using the below commented code
            //context.Fail("Unauthorized");
            
            //otherwise succeed the request
            return Task.CompletedTask;
        }
    };
    options.RequireHttpsMetadata = false;
    options.SaveToken = true;
    options.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey("MyVeryStrongKeyHiddenFromAnyone"),
        ValidateIssuer = false,
        ValidateAudience = false

    };
});
Run Code Online (Sandbox Code Playgroud)

在使用 MVC 之前仍然应用使用身份验证。

[请注意,这些是非常简单的示例,您可能需要进一步加强安全性并实施最佳实践,例如使用强密钥、可能从环境加载配置等]

那么实际的身份验证操作,比如说在 AuthenticationController 中可能会是这样的

[Route("api/[controller]")]
[Authorize]
public class AuthenticationController : Controller
{
    [HttpPost("authenticate")]
    [AllowAnonymous]
    public async Task<IActionResult> AuthenticateAsync([FromBody]LoginRequest loginRequest)
    {
        //LoginRequest may have any number of fields expected .i.e. username and password

        //validate user credentials and if they fail return
        //return Unauthorized();

        var claimsIdentity = new ClaimsIdentity(new Claim[]
           {
            //add relevant user claims if any
           }, "Cookies");

        var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
        await Request.HttpContext.SignInAsync("Cookies", claimsPrincipal);
        return Ok();
    }
}
Run Code Online (Sandbox Code Playgroud)

在本例中,我使用 cookie,因此我使用 Set Cookie 返回 HTTP 结果。如果我使用 JWT,我会返回类似的内容

[HttpPost("authenticate")]
public IActionResult Authenticate([FromBody]LoginRequest loginRequest)
{
    //validate user credentials and if they validation failed return a similar response to below
    //return NotFound();

    var tokenHandler = new JwtSecurityTokenHandler();
    var key = Encoding.ASCII.GetBytes("MySecurelyInjectedAsymKey");
    var tokenDescriptor = new SecurityTokenDescriptor
    {
        Subject = new ClaimsIdentity(new Claim[]
        {
            //add my users claims etc
        }),
        Expires = DateTime.UtcNow.AddDays(1),//configure your token lifespan and needed
        SigningCredentials = new SigningCredentials(new SymmetricSecurityKey("MyVerySecureSecreteKey"), SecurityAlgorithms.HmacSha256Signature),
        Issuer = "YourOrganizationOrUniqueKey",
        IssuedAt = DateTime.UtcNow
    };

    var token = tokenHandler.CreateToken(tokenDescriptor);
    var tokenString = tokenHandler.WriteToken(token);
    var cookieOptions = new CookieOptions();
    cookieOptions.Expires = DateTimeOffset.UtcNow.AddHours(4);//you can set this to a suitable timeframe for your situation 
    cookieOptions.Domain = Request.Host.Value;
    cookieOptions.Path = "/";
    Response.Cookies.Append("jwt", tokenString, cookieOptions);
    return Ok();
}
Run Code Online (Sandbox Code Playgroud)


Mph*_*nge 0

我不熟悉在后端应用程序上存储用户令牌,我将快速检查它是如何工作的,但是如果您使用 dotnet core 通过 cookie 或 jwt 进行身份验证,根据我的理解和经验,您不需要存储任何在你这边的事情。

如果您使用 cookie,那么您只需要配置中间件来验证 cookie 的有效性(如果它出现在用户/消费者的标头中),并且如果不可用、已过期或无法解析它,您只需拒绝该请求并用户甚至不会点击任何受保护的控制器和操作。这是一种非常简化的 cookie 方法。(我仍处于开发阶段,尚未在生产中进行测试,但目前使用 JS 客户端和 Postman 在本地运行得非常好)

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
       .AddCookie(options =>
       {
           options.Cookie.Name = "yourCookieName";
           options.Cookie.SameSite = SameSiteMode.None;//its recommended but you can set it to any of the other 3 depending on your reqirements
           options.Events = new Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationEvents
           {
               OnRedirectToLogin = redirectContext =>//this will be called if an unauthorized connection comes and you can do something similar to this or more
               {
                   redirectContext.HttpContext.Response.StatusCode = 401;
                   return Task.CompletedTask;
               },
               OnValidatePrincipal = context => //if a call comes with a valid cookie, you can use this to do validations. in there you have access to the request and http context so you should have enough to work with
               {
                   var userPrincipal = context.Principal;//I'm not doing anything with this right now but I could for instance validate if the user has the right privileges like claims etc
                   return Task.CompletedTask;
               }
           };
       });
Run Code Online (Sandbox Code Playgroud)

显然,这将在启动的ConfigureServices方法中放置或调用以注册身份验证

然后在启动的配置方法中,您将连接身份验证,例如

app.UseAuthentication();
Run Code Online (Sandbox Code Playgroud)

app.UseMvc()
Run Code Online (Sandbox Code Playgroud)