在.net核心web api中的何处存储JWT令牌?

在.net核心web api中的何处存储JWT令牌?,api,authentication,jwt,Api,Authentication,Jwt,我使用web api访问数据,我想对web api进行身份验证和授权。为此,我使用JWT令牌身份验证。但我不知道应该在哪里存储访问令牌 我想做什么 1) 登录后存储令牌 2) 如果用户希望访问web api的任何方法,请检查令牌对此用户是否有效,如果有效,则授予访问权限 我知道两种方法 1) 使用cookies 2) sql server数据库 哪一种是存储上述代币的更好方法?我不熟悉将用户代币存储在后端应用程序上,我将快速检查这是如何工作的。但是,如果您使用dotnet core通过Cooki

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

我想做什么

1) 登录后存储令牌

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

我知道两种方法

1) 使用cookies

2) sql server数据库


哪一种是存储上述代币的更好方法?

我不熟悉将用户代币存储在后端应用程序上,我将快速检查这是如何工作的。但是,如果您使用dotnet core通过Cookie或jwt进行身份验证,根据我的理解和经验,您无需存储任何东西

如果您正在使用cookie,那么您只需要配置中间件来验证cookie的有效性,如果cookie出现在用户/消费者的标题中,并且如果cookie不可用、已过期或无法解决,您只需拒绝请求,用户甚至不会点击任何受保护的控制器和操作。这里有一个非常简单的cookie方法(我还在开发中,还没有在生产中测试过,但现在使用JS客户端和Postman,它在本地运行得非常好)

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

然后在启动时的配置方法中,连接身份验证

app.UseAuthentication();
以前

app.UseMvc()

或者,如果您只是想使用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

            };
        });
在使用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();
        }
    }
}
[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();

    }

我希望这些有帮助

您能进一步解释一下您的用例吗。是否要在webapi上强制身份验证,以便调用者在调用控制器和操作之前需要进行身份验证,还是webapi正在调用另一个需要对您的调用进行身份验证的系统?如果您试图实现之前的选项,那么您不必担心,如果您已经完成了中间件的定制,除非您正在考虑剥离应用程序的多个实例,并且您需要在多个应用程序之间共享会话(但不确定为什么要使用会话)但是,如果您询问如何在成功身份验证后将令牌传递回调用方,则有两种选择。使用标准owin中间件来处理使用Bear的身份验证,然后您可以在响应中返回jwt(风险在于您的终端客户端保护令牌)或者将中间件配置为使用cookie身份验证,只返回带有标题集cookie的cookie,这样您的客户端就可以保存cookie,而不必担心任何其他应用程序能够访问其信息。为什么您认为您需要将jwt存储在任何位置?用于通过比较令牌验证用户是否有效这是一个解决方案,但这里的IUserDomain是什么…?没问题,不用担心,这些基本上只是服务编排,有助于执行某些操作,如到数据库验证用户凭据或调用内部身份验证系统。但您是否得到了一个基本信息,即您实际上不需要使用数据库来存储令牌
[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();

    }