使用JJWT做token验证

╄→尐↘猪︶ㄣ 提交于 2019-12-10 12:49:21

 

  1. 什么是JJWT?

JJWT是一个提供端到端的JWT创建和验证的Java库。永远免费和开源(Apache License,版本2.0),JJWT很容易使用和理解。它被设计成一个以建筑为中心的流畅界面,隐藏了它的大部分复杂性。

  1. 什么是JSON Web Token(JWT)

JSON Web Token(JWT)是一个非常轻巧的规范。这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息。和 Cookie-Session 的模式不同,JSON Web Token(JWT)使用 Token 替换了 SessionId 的资源访问和状态的保持。

  1. JWT的组成

Jwt由头部、载荷、签名三部分组成,头部包含元数据,通常用来记录JWT所用的算法。

例如:

Header:

{

"typ": "JWT",

"alg": "HS256"

}

将这个头部使用Base64编码过后,就得到的JWT的第一段字符串

载荷:载荷用来承载JWT中的有效信息,通常包括三部分

  1. 公共的声明

可以存放自定义的信息,但是由于载荷仍旧使用的Base64进行编码,所以不建议在载荷中存放敏感信息。

  1. 私密的声明

私密的声明用来存放提供者和消费者共同定义的数据。但是由于载荷仍旧使用的Base64进行编码,所以不建议在载荷中存放敏感信息。

  1. 标准中注册的声明

iss:jwt的签发者

sub:jwt的面向用户

aud: 接收jwt的一方

exp: jwt的过期时间

nbf: 定义在什么时间之前,该jwt都是不可用的.

iat: jwt的签发时间

jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。

将载荷进行base64编码之后,得到第二部分字符串,不建议在载荷中存放过多的数据。

签名:签名用来防止载荷中的数据被篡改,使用头部+载荷中的编码和秘钥一起加密之后生成签名,一旦知道了秘钥,会导致任何人都可以随意的签发token,所以要保护好秘钥。

 

  1. JWT的优势
  1. 支持跨域:由JWT生成的Token可以通过存放在HTTP头中进行传输,而Cookie是不允许跨域传输的。
  2. 无状态:使用token访问时,可以使用token来承载信息,而不需要在服务端生成session来存放生成的信息。
  3. 支持移动应用:由于在移动端是不存在Cookie的,所以使用Token可以解决没有Cookie所带来的的问题。
  4. CSRF:因为不再依赖于Cookie,所以你就不需要考虑对CSRF(跨站请求伪造)的防范。(如果token是用cookie保存,CSRF还是需要考虑,一般建议使用1、在HTTP请求中以参数的形式加入一个服务器端产生的token。或者2.放入http请求头中也就是一次性给所有该类请求加上csrftoken这个HTTP头属性,并把token值放入其中)
  1. JWT的使用方式
  1. 在请求参数中添加token

由于不在Cookie中保存token,可以防止CSRF攻击,防止攻击者伪造用户信息。

  1. 在Http头中添加属性

在Http头中添加属性,可以防止token被记录到浏览器的地址栏,防止token泄露。

  1. JJWT的实现
  1. maven下载jar包

 <dependency>

       <groupId>io.jsonwebtoken</groupId>

       <artifactId>jjwt</artifactId>

       <version>0.9.0</version>

</dependency>

  1. 生成JJWT的token

 public String createToken(Map<String, Object> claims, String subject,HttpServletRequest request) {

        List<Addressable> addressList = tokenService.getAddressable();

        logger.info(addressList.toString());

        String ipAddress = CusAccessObjectUtil.getIpAddress(request);

        logger.info(ipAddress);

        for (Addressable addressable : addressList) {

            if (ipAddress.equals(addressable.getIp())) {

                // 指定签名的时候使用的签名算法,也就是header那部分,jjwt已经将这部分内容封装好了。

                SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

                // 获取系统目前时间

                long nowMillis = System.currentTimeMillis();

                // 转换成Date

                Date now = new Date(nowMillis);

                //获取秘钥

                 SecretKey key = generalKey();

                //设置当前3分钟之后过期

                Calendar nowTime = Calendar.getInstance();

                nowTime.add(Calendar.MINUTE, 3);

                Date expiresDate = nowTime.getTime();

                JwtBuilder jwtBuilder = Jwts.builder() //new一个JWTbuilder,用来设置JWTbody

                        .setClaims(claims)//设置这个自己的私有变量

                        .setExpiration(expiresDate)//设置过期时间

                        .setId(UUID.randomUUID().toString()) //设置唯一ID防止重放攻击

                        .setIssuedAt(now)   //设置当前

                        .setSubject(subject)//可以存放userid等内容,用来表明用户的唯一标识

                        .signWith(signatureAlgorithm, key);

                 return jwtBuilder.compact();

            }

        }

 

        return null;

}

  1. 解析JJWT

 public Claims parseJWT(String jwt) {

              try {

                     SecretKey key = generalKey();  //签名秘钥,和生成的签名的秘钥一模一样

               Claims claims = Jwts.parser()  //得到DefaultJwtParser

                  .setSigningKey(key)         //设置签名的秘钥

                  .parseClaimsJws(jwt).getBody();//设置需要解析的jwt

               return claims;

              }catch (Exception e) {

                     e.printStackTrace();

              }

              return null;

       }

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!