且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

使用JWT在Asp.net Web API上实现身份验证

更新时间:2022-12-06 16:47:31

您对JWT的理解很好.但是,这里有一些更正和一些建议.

Your understanding of JWTs is good. But here are a couple corrections and some recommendations.

  • JWT与身份验证无关.仅当您在创建JWT时进行身份验证时,才会击中数据库密码和哈希密码.这与JWT正交,您可以按照自己喜欢的任何方式进行操作.我个人喜欢会员重新启动,这也是使用JWT的一个很好的例子.
  • 理论上,您可以让用户每年输入一次密码,并使JWT在整个一年中都有效.如果JWT在任何时候被盗,那么用户资源将受到损害,这极有可能不是***解决方案.
  • JWTs have nothing to do with authentication. Hitting your DB and hashing passwords only happens when you authenticate on creation of the JWT. This is orthogonal to JWTs and you can do that in any way you like. I personally like Membership Reboot, which also has a good example of using JWTs.
  • Theoretically, you could have the user enter a password once a year and have the JWT be valid that entire year. This most likely not the best solution, if the JWT gets stolen at any point the users resources would be compromised.
  • 令牌可以但不必加密.对令牌进行加密将增加系统的复杂性,并增加服务器读取JWT所需的计算量.如果您要求在静止时没有人能够读取令牌,这可能很重要.
  • 令牌始终由发行者加密签名以确保其完整性.意味着它们不能被用户或第三方篡改.

您的JWT可以包含您想要的任何信息.用户名,生日,电子邮件等.您可以使用基于声明的授权来执行此操作.然后,您只需告诉您的提供者使用索赔原则"中的这些索赔创建JWT.以下代码来自该Membership Reboot示例,它向您展示了如何完成此操作.

Your JWTs can contain any information you want. The users name, birthdate, email, etc. You do this with claims based authorization. You then just tell your provider to make a JWT with these claims from the Claims Principle. The following code is from that Membership Reboot example and it shows you how this is done.

public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
    var svc = context.OwinContext.Environment.GetUserAccountService<UserAccount>();
    UserAccount user;
    if (svc.Authenticate("users", context.UserName, context.Password, out user))
    {
        var claims = user.GetAllClaims();

        var id = new System.Security.Claims.ClaimsIdentity(claims, "MembershipReboot");
        context.Validated(id);
    }

    return base.GrantResourceOwnerCredentials(context);
}

这使您可以精确地控制谁在访问资源,而无需访问处理器密集型身份验证服务.

This allows you to control with precision whom is accessing your resources, all without hitting your processor intensive authentication service.

实现令牌提供程序的一种非常简单的方法是使用

A very easy way to implement a Token provider is to use Microsoft's OAuth Authorization Server in your WebAPI project. It give you the bare bones of what you need to make a OAuth server for your API.

您还可以查看Thinktecture的身份服务器,它可以为您提供很多帮助更容易控制用户.例如,您可以轻松地使用身份服务器实现刷新令牌,在该服务器中,对用户进行一次身份验证,然后在一定时间(可能一个月)内,他们可以继续从身份服务器获取短暂的JWT.刷新令牌是好的,因为它们可以被吊销,而JWT则不能.该解决方案的缺点是您需要设置另一台或两台服务器来承载身份服务.

You could also look into Thinktecture's Identity Server which would give you much easier control over users. For instance, you can easily implement refresh tokens with identity server where the user is authenticated once and then for a certain amount of time (maybe a month) they can continue getting short lived JWTs from the Identity Server. The refresh tokens are good because they can be revoked, whereas JWTs cannot. The downside of this solution is that you need to set up another server or two to host the Identity service.

要处理您的最后一点,即入侵者不能复制上一个请求以获取对资源的访问权限,您必须至少使用SSL.这将保护令牌在运输中.

To deal with your last point, that an intruder should not be able to copy the last request to get access to a resource, you must use SSL at a bare minimum. This will protect the token in transport.

如果您要保护非常敏感的东西,则应将令牌生存期保持在很短的时间范围内.如果您保护的东西不那么敏感,则可以延长使用寿命.如果令牌有效,则令牌越长,如果攻击者的计算机受到威胁,攻击者将不得不冒充经过身份验证的用户的时间窗口越大.

If you are protecting something extremely sensitive, you should keep the token lifetime to a very short window of time. If you are protecting something less sensitive, you could make the lifetime longer. The longer the token if valid, the larger the window of time a attacker will have to impersonate the authenticated user if the user's machine is compromised.