jwt

项目中使用到了jwt,用来在分布式项目中替代session;

jwt使用起来很简单,以下为我写的一个简单demo:

package rayeye.zq.com.tools;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Calendar;
import java.util.Date;
import java.util.Map;

/**
 * Created by zq on 2017/3/18.
 */
public class JWT {
    private static Logger logger = LoggerFactory.getLogger(JWT.class);
    public static final String JWT_ISSUER_ALIAS = "TEST-TEST-Security";
    public static final String JWT_SUBJECT = "user";
    public static final String JWT_USER_ALIAS = "user";
    public static final String JWT_VERSION = "3.0";
    public static final String JWT_SECRET = "5EEDAAF1C9B4B5301B8537AB29C84308";

    public JWT() {
    }


//    获取加密后 的jwt字符串
    public static String getJWTString(String sub, Date expires, Map<String, Object> claims) {
        JSONArray audience = new JSONArray();
        if(claims == null) {
            throw new NullPointerException("NULL sub is claims");
        } else {
            if(sub == null || "".equals(sub)) {
                sub = "user";
            }

            if(expires == null) {
                throw new NullPointerException("NULL expires is illegal");
            } else {
                if(claims.containsKey("roles")) {
                    audience.add(claims.get("roles"));
                }

                SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
                claims.put("exp", Long.valueOf(expires.getTime()));
                String jwtString = Jwts.builder().setIssuer("TEST-TEST-Security").setSubject(sub).setAudience(audience.toJSONString()).setClaims(claims).setExpiration(expires).setIssuedAt(new Date()).setId("3.0").signWith(signatureAlgorithm, "5EEDAAF1C9B4B5301B8537AB29C84308").compact();
                return jwtString;
            }
        }
    }

//    判断jwt是否有效
    public static boolean isValid(String token) {
        try {
            Jwts.parser().setSigningKey("5EEDAAF1C9B4B5301B8537AB29C84308").parseClaimsJws(token.trim());
            return true;
        } catch (Exception var2) {
            logger.error("Token check failure!
Error:" + var2.getMessage());
            return false;
        }
    }


//    解析jwt
    public static String parseJWT(String jwsToken) {
        if(isValid(jwsToken)) {
            Claims claims = (Claims)Jwts.parser().setSigningKey("5EEDAAF1C9B4B5301B8537AB29C84308").parseClaimsJws(jwsToken).getBody();
            return JSONObject.toJSONString(claims);
        } else {
            return null;
        }
    }

//    设置jwt有效期
    public static Date getExpiryDate(int minutes) {
        // 根据当前日期,来得到到期日期
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.add(Calendar.MINUTE, minutes);
        return calendar.getTime();
    }



    public static void main(String [] args){
        Date expiry = getExpiryDate(7 * 24 * 60);
        JSONObject object = new JSONObject();
        object.put("test1","test1");
        object.put("test2","test2");
        object.put("test2/","test2/");
        String jwt = getJWTString("user",expiry,object);
        System.out.println(jwt);
        System.out.println("-------------------------------------------------------");
        System.out.println(isValid(jwt));
        System.out.println("-------------------------------------------------------");
        System.out.print(parseJWT("eyJhbGciOiJIUzI1NiJ9.eyJ0ZXN0MiI6InRlc3QyIiwidGVzdDIvIjoidGVzdDIvIiwiZXhwIjoxNDkwNTMyNzc3LCJ0ZXN0MSI6InRlc3QxIiwiaWF0IjoxNDg5OTI3OTc3LCJqdGkiOiIzLjAifQ.NpMlrAaqi1MiWVVwHtIX2HihjE8HdBVgsWqaqev5YFk"));
    }


}

 相关maven:

<!-- jjwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.6.0</version>
</dependency>

//我暂时只是知道如何使用它,至于其底层原理则还没研究。后面会继续研究.

jwt的简单实现原理介绍:

jwt分为三部分:

1.header(头部)

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

头部通常包含两部分,type:代表token的类型,这里使用的事JWT类型。alg:使用的Hash算法,例如HMAC SHA256或者RSA。

2.payload(负载)

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}
负载包含了一些声明Claim。声明分三类:
1.)Reserved Claim,这是一套预定义的声明,并不是必须要是用的,例如:iss(issuer)、exp(expiration time)、sub(subject)、aud(audience)等
2.)public Claim,
3.)private Claim,交换信息的自定义声明.
 
3.signature 使用header中指定的算法讲编码后的header,编码后的payload,一个sercret进行加密,如下:
例如使用的是HMAC SHA256算法,大致流程类似于: HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
这个signature是用来验证信息是否被修改.

如此,可以保证jwt字符串可以用来实现信息认证的功能,

比如当遇到单点登录需求的时候,就可以考虑使用jwt来代替session,当然,也可以考虑redis代替session,这又是另一个话题,此处不谈.

原文地址:https://www.cnblogs.com/zqsky/p/6582587.html