用token实现单点登录

1,依赖架

com.nimbusds
nimbus-jose-jwt
4.31.1


com.auth0
java-jwt
3.1.0

2,工具类
public class TokenJwt {

/**
 * 秘钥
 */
private static final byte[] SECRET="3d990d2276917dfac04467df11fff26d".getBytes();

/**
 * 初始化head部分的数据为
 * {
 * 		"alg":"HS256",
 * 		"type":"JWT"
 * }
 */
private static final JWSHeader header=new JWSHeader(JWSAlgorithm.HS256, JOSEObjectType.JWT, null, null, null, null, null, null, null, null, null, null, null);

/**
 * 生成token,该方法只在用户登录成功后调用
 * 
 * @param payload Map集合,可以存储用户id,token生成时间,token过期时间等自定义字段
 * @return token字符串,若失败则返回null
 * iss: jwt签发者
 * sub: jwt所面向的用户
 * aud: 接收jwt的一方
 * exp: jwt的过期时间,这个过期时间必须要大于签发时间
 * nbf: 定义在什么时间之前,该jwt都是不可用的.
 * iat: jwt的签发时间
 * jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
 */
public static String createToken(Map payload) {
	String tokenString=null;
	// 创建一个 JWS object
	JWSObject jwsObject = new JWSObject(header, new Payload(new JSONObject(payload)));
	try {
		// 将jwsObject 进行HMAC签名
		jwsObject.sign(new MACSigner(SECRET));
		tokenString=jwsObject.serialize();
	} catch (JOSEException e) {
		System.err.println("签名失败:" + e.getMessage());
		e.printStackTrace();
	}
	return tokenString;
}



/**
 * 校验token是否合法,返回Map集合,集合中主要包含    state状态码   data鉴权成功后从token中提取的数据
 * 该方法在过滤器中调用,每次请求API时都校验
 * 如果对token进行验证,那么服务器需要提供保存token的方式,这很麻烦,所以不往token存入信息,只用作登录标识!
 * @param token
 * @return  Map
 */
public static Map validToken(String token) {
	Map resultMap = new HashMap();
	try {
		JWSObject jwsObject = JWSObject.parse(token);
		Payload payload = jwsObject.getPayload();
		JWSVerifier verifier = new MACVerifier(SECRET);

		if (jwsObject.verify(verifier)) {
			//可以为了token专门建立一个类,用来存放token内需要存入的信息
			JSONObject jsonOBj = payload.toJSONObject();
			// token校验成功(此时没有校验是否过期)
			resultMap.put("state", TokenState.VALID.toString());
			// 若payload包含ext字段,则校验是否过期
			if (jsonOBj.containsKey("ext")) {
				long extTime = Long.valueOf(jsonOBj.get("ext").toString());
				Logger.getLogger("查看token的有效期:").info(">>>>>>>>>"+extTime);
				long curTime = DateUtil.strToDate(DateUtil.getTime());
				Logger.getLogger("查看当前时间戳:").info(">>>>>>>>>"+curTime);
				// 过期了
				if (curTime > extTime) {
					resultMap.clear();
					resultMap.put("state", TokenState.EXPIRED.toString());
				}
			}
			//此处为从payload中拿出来的信息
			resultMap.put("data", jsonOBj);

		} else {
			// 校验失败
			resultMap.put("state", TokenState.INVALID.toString());
		}
	} catch (Exception e) {
		//e.printStackTrace();
		// token格式不合法导致的异常
		resultMap.clear();
		resultMap.put("state", TokenState.INVALID.toString());
	}
	return resultMap;
}	


/**
 * 测试
 * @param args
 */
public static void main(String[] args) {
	Map payload =new HashMap();
	payload.put("uuid",Math.random());
	payload.put("rolekey", "1");
	String token=createToken(payload);
	System.out.println(token);
	Map  resultMap=validToken(token);
	Set entries=resultMap.entrySet();
	Iterator iterator = entries.iterator( );
	while(iterator.hasNext())
	{
		Entry entry=(Entry) iterator.next();
		System.out.println(entry.getKey()+">>>>>>>"+entry.getValue()+new Date().getTime());
	}
}

}
3,token的状态枚举
public enum TokenState {
/**
* 过期
/
EXPIRED(“EXPIRED”),
/
*
* 无效(token不合法)
/
INVALID(“INVALID”),
/
*
* 有效的
*/
VALID(“VALID”);

private String state;

private TokenState(String state) {
this.state = state;
}

/**
* 根据状态字符串获取token状态枚举对象
* @param tokenState
* @return
*/
public static TokenState getTokenState(String tokenState){
TokenState[] states=TokenState.values();
TokenState ts=null;
for (TokenState state : states) {
if(state.toString().equals(tokenState)){
ts=state;
break;
}
}
return ts;
}

public String toString() {
return this.state;

}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}

}
4,在登录之后成功了就给他一个token令牌,以后再访问不管是哪个域的时候都要携带上这个token,
用token实现单点登录_第1张图片

你可能感兴趣的:(用token实现单点登录)