什么是JWT(来自官网)

官网:JSON Web Token Introduction - jwt.io

什么是 JWT

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.

JSON Web 令牌(JWT)是一种开放标准(RFC 7519) ,它定义了一种紧凑和自包含的方式,用于作为 JSON 对象在各方之间安全地传输信息。可以验证和信任此信息,因为它是数字签名的。JWTs 可以使用 secret (使用 HMAC 算法)或使用 RSA 或 ECDSA 的公钥/私钥对进行签名。

Although JWTs can be encrypted to also provide secrecy between parties, we will focus on signed tokens. Signed tokens can verify the integrity of the claims contained within it, while encrypted tokens hide those claims from other parties. When tokens are signed using public/private key pairs, the signature also certifies that only the party holding the private key is the one that signed it.

虽然可以对 JWTs 进行加密,以便在各方之间提供保密性,但是我们将重点讨论已签名的令牌。已签名的令牌可以验证其中包含的声明的完整性,而加密的令牌会向其他方隐藏这些声明。当令牌使用公钥/私钥对进行签名时,签名还证明只有持有私钥的一方才是对其进行签名的一方。

什么时候应该使用 JWT

Here are some scenarios where JSON Web Tokens are useful:

下面是一些 JSON Web 令牌有用的场景:

  • Authorization: This is the most common scenario for using JWT. Once the user is logged in, each subsequent request will include the JWT, allowing the user to access routes, services, and resources that are permitted with that token. Single Sign On is a feature that widely uses JWT nowadays, because of its small overhead and its ability to be easily used across different domains.

    授权: 这是使用 JWT 最常见的场景。一旦用户登录,每个后续请求都将包含 JWT,允许用户访问该令牌所允许的路由、服务和资源。单点登录(Single Sign On)是目前广泛使用 JWT 的一个特性,因为它的开销很小,而且可以轻松地跨不同的域使用。

  • Information Exchange: JSON Web Tokens are a good way of securely transmitting information between parties. Because JWTs can be signed—for example, using public/private key pairs—you can be sure the senders are who they say they are. Additionally, as the signature is calculated using the header and the payload, you can also verify that the content hasn’t been tampered with.

    信息交换: JSON Web 令牌是在各方之间安全地传输信息的好方法。因为可以对 JWTs 进行签名(例如,使用公钥/私钥对) ,所以可以确定发送者就是他们所说的那个人。此外,由于签名是使用标头和有效负载计算的,因此还可以验证内容没有被篡改。

JWT 结构

In its compact form, JSON Web Tokens consist of three parts separated by dots (.), which are:

在其紧凑的形式中,JSON Web token 由三部分组成,由点(.)分隔,它们是:

  • Header 头部
  • Payload 有效载荷
  • Signature 签名

Therefore, a JWT typically looks like the following.

因此,JWT 通常如下所示。

xxxxx.yyyyy.zzzzz

Let’s break down the different parts.

让我们分析一下不同的部分。

Header

The header typically consists of two parts: the type of the token, which is JWT, and the signing algorithm being used, such as HMAC SHA256 or RSA.

标头通常由两部分组成: 令牌的类型(即 JWT)和所使用的签名算法(如 HMAC SHA256或 RSA)。

For example:

例如:

{
  "alg": "HS256",
  "typ": "JWT"
}

Then, this JSON is Base64Url encoded to form the first part of the JWT.

然后,对这个 JSON 进行 Base64Url 编码,以形成 JWT 的第一部分。

Payload

The second part of the token is the payload, which contains the claims. Claims are statements about an entity (typically, the user) and additional data. There are three types of claims: registered, public, and private claims.

令牌的第二部分是有效负载,它包含声明。索赔是关于一个实体(通常是用户)和其他数据的语句。债权有三种类型: 登记债权、公共债权和私人债权。

  • Registered claims: These are a set of predefined claims which are not mandatory but recommended, to provide a set of useful, interoperable claims. Some of them are: iss (issuer), exp (expiration time), sub (subject), aud (audience), and others.

    登记索赔: 这些是一组预先确定的索赔,不是强制性的,但建议提供一组有用的、可互操作的索赔。其中包括: iss (发行者)、 exp (到期时间)、 sub (主题)、 aud (受众)等。

    Notice that the claim names are only three characters long as JWT is meant to be compact.

    注意,只要 JWT 的目的是紧凑,那么声明名称就只有三个字符。

  • Public claims: These can be defined at will by those using JWTs. But to avoid collisions they should be defined in the IANA JSON Web Token Registry or be defined as a URI that contains a collision resistant namespace.

    公共声明: 使用 JWTs 的人可以随意定义这些声明。但是为了避免冲突,它们应该在 IANA JSON Web Token Registry 中定义,或者定义为包含抗冲突名称空间的 URI。

  • Private claims: These are the custom claims created to share information between parties that agree on using them and are neither registered or public claims.

    私人权利主张: 这些权利主张是为了在同意使用它们的各方之间共享信息而创建的,它们既不是注册的也不是公开的权利主张。

An example payload could be:

例如,有效载荷可以是:

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

The payload is then Base64Url encoded to form the second part of the JSON Web Token.

然后对有效负载进行 Base64Url 编码,形成 JSON Web Token 的第二部分。

Do note that for signed tokens this information, though protected against tampering, is readable by anyone. Do not put secret information in the payload or header elements of a JWT unless it is encrypted.

请注意,对于已签名令牌,这些信息虽然受到保护,不会被篡改,但任何人都可以读取。不要在 JWT 的有效负载或头部元素中放置机密信息,除非该信息是加密的。

Signature

To create the signature part you have to take the encoded header, the encoded payload, a secret, the algorithm specified in the header, and sign that.

要创建签名部分,您必须获取已编码的标题、已编码的有效负载、秘密、标题中指定的算法,并对其进行签名。

For example if you want to use the HMAC SHA256 algorithm, the signature will be created in the following way:

例如,如果您想使用 HMAC SHA256算法,签名将以下列方式创建:

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

The signature is used to verify the message wasn’t changed along the way, and, in the case of tokens signed with a private key, it can also verify that the sender of the JWT is who it says it is.

签名用于验证消息是否在整个过程中被更改,对于使用私钥签名的令牌,它还可以验证 JWT 的发送方是否是它所说的那个发送方。

三部分组合

The output is three Base64-URL strings separated by dots that can be easily passed in HTML and HTTP environments, while being more compact when compared to XML-based standards such as SAML.

输出是三个 Base64-URL 字符串,由点分隔,可以轻松地在 HTML 和 HTTP 环境中传递,同时与基于 xml 的标准(如 SAML)相比更加紧凑。

The following shows a JWT that has the previous header and payload encoded, and it is signed with a secret. Encoded JWT

下面显示了一个 JWT,该 JWT 对前面的头和负载进行了编码,并使用一个 secret 对其进行了签名。

If you want to play with JWT and put these concepts into practice, you can use jwt.io Debugger to decode, verify, and generate JWTs.

如果希望使用 JWT 并将这些概念付诸实践,可以使用 JWT.io Debugger 来解码、验证和生成 JWTs。

JWT.io Debugger

注意:

​ 三部分的编码方式都是 Base64-URL 不是 Base64,所以如果使用Jdk中的类 sun.misc.BASE64Encoder进行编码,还需要后续处理,关于这两种编码方式的区别及转换方法参考这篇文章,这里不做太多介绍。

JWT 如何工作

In authentication, when the user successfully logs in using their credentials, a JSON Web Token will be returned. Since tokens are credentials, great care must be taken to prevent security issues. In general, you should not keep tokens longer than required.

在身份验证中,当用户成功地使用其凭证登录时,将返回一个 JSON Web 令牌。因为令牌是凭证,所以必须非常小心地防止安全问题。一般而言,保存令牌的时间不应超过所需的时间。

You also should not store sensitive session data in browser storage due to lack of security.

由于缺乏安全性,您也不应该在浏览器存储器中存储敏感会话数据。

Whenever the user wants to access a protected route or resource, the user agent should send the JWT, typically in the Authorization header using the Bearer schema. The content of the header should look like the following:

无论何时用户想要访问受保护的路由或资源,用户代理都应该发送 JWT,通常在授权头中使用承载模式。标题的内容应该如下所示:

Authorization: Bearer <token>

This can be, in certain cases, a stateless authorization mechanism. The server’s protected routes will check for a valid JWT in the Authorization header, and if it’s present, the user will be allowed to access protected resources. If the JWT contains the necessary data, the need to query the database for certain operations may be reduced, though this may not always be the case.

在某些情况下,这可以是一种无状态授权机制。服务器的受保护路由将在 Authorization 头中检查有效的 JWT,如果它存在,则允许用户访问受保护的资源。如果 JWT 包含必要的数据,则可能减少为某些操作查询数据库的需要,尽管情况可能并非总是如此。

If the token is sent in the Authorization header, Cross-Origin Resource Sharing (CORS) won’t be an issue as it doesn’t use cookies.

如果令牌是在授权头中发送的,那么由于没有使用 cookie,跨来源资源共享服务器(CORS)就不会成为问题。

The following diagram shows how a JWT is obtained and used to access APIs or resources:

下图显示了 JWT 是如何获得并用于访问 api 或资源的:

How does a JSON Web Token work

  1. The application or client requests authorization to the authorization server. This is performed through one of the different authorization flows. For example, a typical 应用程序或客户机向授权服务器请求授权。这是通过其中一个不同的授权流执行的。例如,一个典型的OpenID Connect 连接 compliant web application will go through the 符合规范的 web 应用程序将通过/oauth/authorize endpoint using the 端点使用authorization code flow 授权码流程.
  2. When the authorization is granted, the authorization server returns an access token to the application. 授予授权后,授权服务器将向应用程序返回一个访问令牌
  3. The application uses the access token to access a protected resource (like an API). 应用程序使用访问令牌来访问受保护的资源(如 API)

Do note that with signed tokens, all the information contained within the token is exposed to users or other parties, even though they are unable to change it. This means you should not put secret information within the token.

请注意,使用带签名的令牌,令牌中包含的所有信息都会公开给用户或其他各方,即使他们无法更改它。这意味着您不应该在令牌中放置秘密信息。

为什么使用 JWT

Let’s talk about the benefits of JSON Web Tokens (JWT) when compared to Simple Web Tokens (SWT) and Security Assertion Markup Language Tokens (SAML).

让我们讨论一下与简单 Web 令牌(SWT)和安全断言标记语言令牌(SAML)相比,JSON Web 令牌(JWT)的优点。

As JSON is less verbose than XML, when it is encoded its size is also smaller, making JWT more compact than SAML. This makes JWT a good choice to be passed in HTML and HTTP environments.

由于 JSON 没有 XML 那么冗长,因此在对其进行编码时,它的大小也更小,使得 JWT 比 SAML 更加紧凑。这使得 JWT 成为在 HTML 和 HTTP 环境中传递的一个很好的选择。

Security-wise, SWT can only be symmetrically signed by a shared secret using the HMAC algorithm. However, JWT and SAML tokens can use a public/private key pair in the form of a X.509 certificate for signing. Signing XML with XML Digital Signature without introducing obscure security holes is very difficult when compared to the simplicity of signing JSON.

在安全方面,SWT 只能通过使用 HMAC 算法的共享密钥对称地签名。但是,JWT 和 SAML 令牌可以使用 x. 509证书形式的公钥/私钥对进行签名。与简单的 JSON 签名相比,使用 XML 数字签名对 XML 进行签名而不引入模糊的安全漏洞是非常困难的。

JSON parsers are common in most programming languages because they map directly to objects. Conversely, XML doesn’t have a natural document-to-object mapping. This makes it easier to work with JWT than SAML assertions.

JSON 解析器在大多数编程语言中都很常见,因为它们直接映射到对象。相反,XML 没有自然的文档到对象的映射。这使得使用 JWT 比使用 SAML 断言更容易。

Regarding usage, JWT is used at Internet scale. This highlights the ease of client-side processing of the JSON Web token on multiple platforms, especially mobile.

考虑到使用情况,JWT 被用于 Internet 规模。这突出显示了在多个平台(尤其是移动平台)上对 JSON Web 令牌进行客户端处理的便利性。

Comparing the length of an encoded JWT and an encoded SAML Comparison of the length of an encoded JWT and an encoded SAML

编码的 JWT 和编码的 SAML 长度的比较

If you want to read more about JSON Web Tokens and even start using them to perform authentication in your own applications, browse to the JSON Web Token landing page at Auth0.

如果您想了解更多关于 JSON Web 令牌的信息,甚至开始使用它们在您自己的应用程序中执行身份验证,请浏览 Auth0的 JSON Web 令牌登陆页面。

如何使用

参考 Github 官方教程

自己封装的简单工具类

maven依赖

<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.18.1</version>
</dependency>

工具类

@Slf4j
public class JwtUtils {

    // 秘钥
    public static final String SECRET_KEY = "f3g7h2dn@w2esdRhf9wj#$";
    // 令牌颁发者
    public static final String ISSUER = "VUE_SHOP";
    // 用户信息key
    public static final String CLAIM_USER_KEY = "user";
    // 有效时间,30min,为方便,设置为10h
    public static final int TIMEOUT = 30 * 60 * 1000 * 20;
    // 加密算法
    public static final Algorithm SIGN_ALGORITHM = Algorithm.HMAC256(SECRET_KEY);

    /**
     * 创建token
     * @param user
     * @return
     */
    public static String createToken(Object user) {
        try {
            return JWT.create()
                    .withIssuer(ISSUER)
                    .withExpiresAt(new Date(System.currentTimeMillis() + TIMEOUT))
                    .withClaim(CLAIM_USER_KEY, JSON.toJSONString(user))
                    .sign(SIGN_ALGORITHM);
        } catch (Exception e) {
            log.error("创建jwt token失败: {}", e);
            throw new BizException(BizCodeEnum.INTERNAL_SERVER_ERROR);
        }
    }

    /**
     * 校验令牌
     * @param token
     * @return
     */
    public static DecodedJWT verifyToken(String token) {

        try {
            JWTVerifier verifier = JWT.require(SIGN_ALGORITHM)
                    .withIssuer(ISSUER)
                    .build(); //Reusable verifier instance
            DecodedJWT jwt = verifier.verify(token);
            return jwt;
        } catch (TokenExpiredException e) {
            throw new BizException(BizCodeEnum.BAD_REQUEST, "令牌已过期");
        } catch (SignatureVerificationException e) {
            throw new BizException(BizCodeEnum.BAD_REQUEST, "无效令牌");
        }
    }

    // public static void main(String[] args) {
    //     OrderEntity or = new OrderEntity();
    //     or.setOrderId(10001);
    //     or.setTradeNo("0000000888888");
    //     String token = createToken(or);
    //     System.out.println("token: " + token);
    //     DecodedJWT decodedJWT = verifyToken(token);
    //     String s = decodedJWT.getClaim(CLAIM_USER_KEY).asString();
    //     OrderEntity orderEntity = JSON.parseObject(s, OrderEntity.class);
    //     System.out.println(orderEntity);
    // }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值