JWT入门级,简单易用

作为一个新手,我认为第一步就是去看官方文档 jjwt 别管英语有多差,有道翻译或者网页翻译结果语义不尽相同,也要先看文档,尽管我也看不懂,但是能大概知道这是做什么的,拿来怎么使用,然后再根据博客和一些资料进行整理,我觉得这样能一个比较深刻的印象!

作用

官方文档上说,JWT(JSON Web Token) 是一种可以验证双方之间传递信息的手段,并且以JSON格式呈现,JWT是可签名的,变成JWS,或者加密,成为JWE。
这让使用JWT的用户增加了一层加验证性和安全性,例如,接收器通过验证签名对JWT没有被篡改具有高度的信心。
JWT字符串格式呈现:

eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJudWxsaiJ9.W8hfFfcMVgmlAhTRUl4GHNAq4tq_MWJGB1bv-r9wMCE

分为三部分,(header,payload)用Base64编码,都是以‘ . ’进行分隔开的:

	第一部分:Header:头部,记录了一些元数据,例如采用何种算法,令牌类型等。
	第二部分:Payload:负载,存储我们的关键信息。
	第三部分:签名,前两部分的签名,防止数据篡改。

我们主要关注 Payload,JWT 官方规定了 7 个供选择的字段:

	iss (issuer):签发人
	exp (expiration time):过期时间
	sub (subject):主题
	aud (audience):受众
	nbf (Not Before):生效时间
	iat (Issued At):签发时间
	jti (JWT ID):编号

说白一点,到底是用来干嘛的(个人理解):

一般在用户登陆成功,服务端便会返回一串 字符串(同上),可以用来作为唯一token使用,在某个时间段内失效,验证合法性,也可以使用 jwt 来做 restful api 的身份认证,其实它就是一个标识,是每个用户的身份证,你要做什么,例如:开房,就必须要使用身份证才能进行,而身份证得保证合法,正确,安全。身份证到期就得去再办一次身份证,不让就失效了,就不可以开房了 :)

java实现

第一步,我查看文档,jjwt框架,导入pom.xml

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.10.5</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>0.10.5</version>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId>
    <version>0.10.5</version>
    <scope>runtime</scope>
</dependency>

第二步创建 jwt Token创建,写个工具类,方便以后调用。
生成key在官网上也是有讲的,也给出例子,可以直接使用

  /**
     * 由字符串生成加密key
     *
     * @return
     */
    private static final String KEY1 = "somethinghereshouldbelong";
    public static Key generalKey() {
        try {
            // 一般服务端自定义一个KEY值,转换成byte[] 再转成SecretKey
            String stringKey = "UnWhVr6cKjw5gzwnR6j5FjYpox6kRoyHbvaTwcfexb11QrKrvVeoGGP3YD3cxlKvyJL6lrK0XX0oMGcA5nPIq7ucGeUFFZ7sIuR";
            byte[] encodedKey = Base64.decodeBase64(stringKey);
            SecretKey key = Keys.hmacShaKeyFor(encodedKey);

            //如果嫌麻烦,可以直接使用jjwt 提供key算法
//            SecretKey key = Keys.secretKeyFor(SignatureAlgorithm.HS256); //or HS384 or HS512
            return key;

        }catch (Exception e){
            e.printStackTrace();
        }
      return null;
    }
/**
     * 创建新token
     * @param userId
     * @return
     */
    public static   String createNewToken(String userId){
        //Header:头部,记录了一些元数据,例如采用何种算法,令牌类型等。
        //Payload:负载,存储我们的关键信息。
        //Signature:签名,前两部分的签名,防止数据篡改。

        //Payload 官方提供7个可选字段
        //iss:Issuer  jwt签发者
        //sub:Subject  面向的用户(jwt所面向的用户)
        //aud:Audience  接收jwt的一方
        //exp:Expiration  过期时间戳(jwt的过期时间,这个过期时间必须要大于签发时间)
        //nbf:Not Before 定义在什么时间之前,该jwt都是不可用的.
        //iat:Issued At jwt的签发时间
        //jti:JWT ID jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
        //setClaims:自定义字段信息
            Key secretKey = generalKey();
        //获取当前时间
        Date now = new Date(System.currentTimeMillis());
        Map<String,Object> map=new HashMap<>();
        map.put("name","河神");
        //过期时间
        Date expiration = new Date(now.getTime() + 72000);
            return Jwts
                    .builder()
                    .setClaims(map)
                    .setSubject("User")
                    .setIssuedAt(now)
                    .setAudience(userId)
                    .setIssuer("Login")
                    .setExpiration(expiration)
                    .signWith(secretKey,SignatureAlgorithm.HS512)
                    .compact();
    }

第三步,解密,当用户使用API时,我们需要验证此Token是否签名正确,才能进行服务端下一步

/**
     * 解密jwt
     * @param jwt 密钥
     * @return 主题
     * @throws Exception 如果发生 JwtException,说明该密钥无效
     */
    public static JwtParser parseJWT (String jwt)  {
        Key key = generalKey();
        try {
            JwtParser parser = Jwts.parser();
                    parser
                    .setSigningKey(key)
                    .parseClaimsJws(jwt)
                    .getBody()
                    .getSubject();
                    return parser;
        }catch (SignatureException signatureException){
            throw new BusiHandlerException("签名错误",10001);
        }catch (ExpiredJwtException ex){
            throw new BusiHandlerException("签名过期",10001);
        }catch (JwtException ex){
          throw new BusiHandlerException(ex.getMessage(),ex.getCause());
        }
    }

异常可以自己去定义,这样简单的使用方式就OK了,接下来就是拦截它。

我们或许要达到此类效果:
拦截是否传入token,附带查看是否有注解,是否需要去验证
根据网上的资料和博客,基本清一色的使用拦截器,这里我想试试AOP来达到此效果。
代码如下,不喜勿喷:

@Aspect
@Order(-1)
@Component
public class BusinessAspect {


    /**
     * 切入business
     */
    @Pointcut("execution(public * com.hj.project.controller.*.*(..))")
    public void pointCut() {
    }

    /**
     * around
     *
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("pointCut()")
    public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
        //获得request response
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();

        //获得自定义注解
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        Token anno = method.getAnnotation(Token.class);
         //如果有@Token注解
       if (anno == null)
        {
            return joinPoint.proceed();
//            throw new RuntimeException("method->" + method.getName() + " PathAuth annotation required");
        }else{
           String token = request.getHeader("token");
           if(StringUtils.isBlank(token)){
               throw new BusiHandlerException("签名不能为空",10001);
           }
           TokenUtils.parseJWT(token);
           return joinPoint.proceed();
       }
    }


}

很简单,是给新手的一个入门,有更好的建议,希望不吝赐教

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值