spring安全验证之jwt(json web token)实践

系统开发来说,安全验证永远是最重要的,从最原始的session、cookie验证方式,到符合restful风格、知足先后端分离需求、启用https请求,各方面都在不断变化中。本文以jwt(json web token)的实践为例,介绍一二。html

首先,来看一下jwt的概念,流程图以下所示:java

流程图

用户发起登陆请求,服务端建立一个加密后的jwt信息,做为token返回值,在后续请求中jwt信息做为请求头,服务端正确解密后可获取到存储的用户信息,表示验证经过;解密失败说明token无效或者已过时。git

加密后jwt信息以下所示,是由.分割的三部分组成,分别为Header、Payload、Signature。github

eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiJqd3QiLCJpYXQiOjE0NzEyNzYyNTEsInN1YiI6IntcInVzZXJJZFwiOjEsXCJyb2xlSWRcIjoxfSIsImV4cCI6MTQ3MTMxOTQ1MX0.vW-pPSl5bU4dmORMa7UzPjBR0F6sqg3n3hQuKY8j35o

Header包含两部分信息,alg指加密类型,可选值为HS25六、RSA等等,typ=JWT为固定值,表示token的类型。web

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

Payload是指签名信息以及内容,通常包括iss (发行者), exp (过时时间), sub(用户信息), aud (接收者),以及其余信息,详细介绍请参考官网。spring

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

Signature则为对Header、Payload的签名。json

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

在jwt官网,能够看到有不一样语言的实现版本,这里使用的是java版的jjwt。话很少说,直接看代码,加解密都很简单:后端

/**
  * 建立 jwt
  * @param id
  * @param subject
  * @param ttlMillis
  * @return
  * @throws Exception
  */
  public String createJWT(String id, String subject, long ttlMillis) throws Exception {
       SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256 ;
       long nowMillis = System. currentTimeMillis();
       Date now = new Date( nowMillis);
       SecretKey key = generalKey();
       JwtBuilder builder = Jwts. builder()
            .setId(id)
            .setIssuedAt(now)
            .setSubject(subject)
           .signWith(signatureAlgorithm, key);
       if (ttlMillis >= 0){
           long expMillis = nowMillis + ttlMillis;
           Date exp = new Date( expMillis);
           builder.setExpiration( exp);
       }
       return builder.compact();
 }

  /**
  * 解密 jwt
  * @param jwt
  * @return
  * @throws Exception
  */
  public Claims parseJWT(String jwt) throws Exception{
       SecretKey key = generalKey();
       Claims claims = Jwts. parser()
          .setSigningKey( key)
          .parseClaimsJws( jwt).getBody();
       return claims;
 }

加解密的key是经过固定字符串转换而生成的;subject为用户信息的json字符串;ttlMillis是指token的有效期,时间较短,须要定时更新。浏览器

这里要介绍的token刷新方式,是在生成token的同时生成一个有效期较长的refreshToken,后续由客户端定时根据 refreshToken来获取最新的token。浏览器与服务端之间创建sse(server send event)请求,来实现刷新。关于sse在前面博文中有介绍过,此处略过不提。安全

本文完整源代码存放于github,地址:https://github.com/ahmu/spring-authorization-demo

参考资料:

(1)http://www.cnblogs.com/xiekeli/p/5607107.html

1.jwt官方网站:https://jwt.io/

2.jjwt项目:https://github.com/jwtk/jjwt

3.Introduction to JSON Web Tokens:https://jwt.io/introduction/

4.How to Create and verify JWTs in Java: https://stormpath.com/blog/jwt-java-create-verify

相关文章
相关标签/搜索