JWT简介

作者: 明翼 | 来源:发表于2020-02-23 21:04 被阅读0次

一 JWT是什么

JWT是JSON Web Token的简称,是目前流行的跨域的认证解决方案,作为JSON对象在各方传递信息的凭证,它是由服务器端签发的,而且是带签名的,在不知道服务器端私钥的情况下,无法伪造的。服务器端通过数字签名来保证数据的完整性和有效性。

1.1 为什么需要

为什么需要这种token认证那,从http这个无状态的协议说起。早期http是短连接的,也就是一个报文一个tcp请求,得到返回的内容后就关闭了。(现在就算支持keep-alive的情况,如果用一个tcp代表一个用户的情况下,如果用户稍有断网,要重新登陆体验笔记差)这就造成一个问题,如果在网站上,比如购物网站上跟踪每个用户信息,就需要区分不同用户的请求内容,早期用session来实现,交互过程如下:

  1. 用户在浏览器登陆,发送username和password给服务器。
  2. 服务器收到后进行验证,验证成功后,将用户信息,比如用户对象保存到session中,且发送一个叫JSESSIONID的cookie给用户浏览器。
  3. 用户下次请求会带上这个JSESSIONID,服务器以此来识别不同的用户。

这种session认证缺点:

  • session 存在服务器上,意味着用户下次请求还必须请求在这台服务器上,才能拿到授权的资源,限制了负载均衡能力。如果多个系统认证无法实现单点登陆功能。

  • session 保存在服务器上,用户越来越多后,在服务器占的内存也会越来越多,甚至有内存溢出的风险。

1.2 JWT

JWT是一个字符串,用于鉴权和认证。包含头信息,有效荷载,签名三部分组成,中间用.号分隔,如下格式:

header.payload.signature
  • header
header = Base64URL({"alg":"HS256","typ":"JWT"))

说明:

声明类型alg:表示令牌的类型,JWT令牌统一写JWT。
签名密玥算法alg:HMAC256,RSA等。
Base64URL:header头需要进行Base64URL处理,Base64URL使用"-"和"_"替换:"+"和"/",不使用"=" ,使用这个原因是因为URL中含有这些字符。

  • payload
    载荷信息,就是json格式封装的一些key和value,标准定义七个:
{
    "iss": "John Wu JWT",
    "iat": 1441593502,
    "exp": 1441594722,
    "aud": "www.example.com",
    "sub": "jrocket@example.com",
    "from_user": "B",
    "target_user": "A"
}

iss:JWT签发者
exp:到期时间UNIX时间戳
sub:JWT对应的用户
aud:用户
nbf:在此之前不可用
iat:发布时间
jti:JWT ID用于标识该JWT,防止回放攻击。

payload中一般保存非敏感信息,同样用Base64URL处理,如果需要保存敏感信息,需要对整个token进行加密。

  • signature
    签名,是通过上面选择的算法对上述两部分进行签名:
HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret
)

secret 为密钥,签名这里面并不是为了保密,而是为了验证此token是本服务器签发的,而且还可以防止篡改,保证数据的完整性。
官网示意图如下:


encode和decode示意图

二 如何使用JWT

2.1 JWT的处理流程:

  1. 初次登陆,输入用户和密码请求发到服务器。
  2. 服务器取出数据库中的用户名和密码进行验证。
  3. 验证通过后,生成token,返回给客户端。
  4. 以后客户端所有请求都会在请求头中:
    Authentication字段都要有值,为JWT。
  5. 服务器验证此token是否合法。
  6. 将用户访问的信息返回给客户端


    JWT请求流程

注意,如果使用token,涉及到跨域的话,需要设置:

Access-Control-Allow-Origin: *

所谓的跨域,即一个请求访问不是同一个域名或端口,这些就属于跨域,为安全期间,一般默认不准许跨域的。
java使用JWT例子:
pom文件引入相关包:

   <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.2.0</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.7.0</version>
        </dependency>

例子:

public class JWTUtil {

    private static final long EXPIRE_TIME = SpringContextUtil.getBean(FebsProperties.class).getShiro().getJwtTimeOut() * 1000;

    /**
     * 校验 token是否正确
     *
     * @param token  密钥
     * @param secret 用户的密码
     * @return 是否正确
     */
    public static boolean verify(String token, String username, String secret) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(secret);
            JWTVerifier verifier = JWT.require(algorithm)
                    .withClaim("username", username)
                    .build();
            verifier.verify(token);
            return true;
        } catch (Exception e) {
            log.info("token is invalid{}", e.getMessage());
            return false;
        }
    }

    /**
     * 从 token中获取用户名
     *
     * @return token中包含的用户名
     */
    public static String getUsername(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim("username").asString();
        } catch (JWTDecodeException e) {
            log.error("error:{}", e.getMessage());
            return null;
        }
    }

    /**
     * 生成 token
     *
     * @param username 用户名
     * @param secret   用户的密码
     * @return token
     */
    public static String sign(String username, String secret) {
        try {
            username = StringUtils.lowerCase(username);
            Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
            Algorithm algorithm = Algorithm.HMAC256(secret);
            return JWT.create()
                    .withClaim("username", username)
                    .withExpiresAt(date)
                    .sign(algorithm);
        } catch (Exception e) {
            log.error("error:{}", e);
            return null;
        }
    }
}

三 JWT有什么缺点

  1. 默认不加密,如果传私密信息不够安全。
  2. 如果采用cookie保存仍然可以被伪造,建议放在localstorage中。
  3. 如果token信息过长,会影响性能,因为每个请求都需要带token信息。
  4. token颁发后,不能通过服务器端让令牌失效,只能等过期,当然这个可以通过保存在redis中,超时日期设置过token过期时间,验证时候先从redis中获取,如果没有直接判断非法,不通过普通的token验证流程验证。

相关文章

  • JsonWebToken

    JWT (JsonWebToken) JWT官网['https://jwt.io/'] JWT简介 1.JWT(J...

  • FusionAuth JWT

    本文介绍基于 FusionAuth JWT 的 JWT 实现方法。 目录 FusionAuth JWT 简介 代码...

  • JWT简介

    在介绍JWT之前先看一下传统校验令牌的方法,如下图: 1.令牌结构 通过学习JWT令牌结构为自定义jwt令牌打好基...

  • JWT简介

    前言 JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案。微服务常见的认证方案 一、跨域认证...

  • JWT简介

    一 JWT是什么 JWT是JSON Web Token的简称,是目前流行的跨域的认证解决方案,作为JSON对象在...

  • JWT简介

    JSON Web Token (JWT) 参考资料:Introduction to JSON Web Tokens...

  • jwt

    jwt简介 JSON Web Token(JWT)是非常流行的跨域身份验证解决方案。 jwt构成 HEADER: ...

  • JWT

    JWT | 简介 全称:JSON Web Token; JWT 主要用于身份认证和信息加密; JWT 是一个简单而...

  • Spring Boot 集成 JWT 实现用户登录认证

    JWT 简介 什么是 JWT JWT 是 JSON Web Token 的缩写,是为了在网络应用环境间传递声明而执...

  • 全栈之初识JWT -- Web安全的守护神

    一、JWT 简介 JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案。JWT 是一个非常轻巧...

网友评论

      本文标题:JWT简介

      本文链接:https://www.haomeiwen.com/subject/mwijqhtx.html