Java安全驗證之jwt(json web token)

http://blog.csdn.net/u012017645/article/details/53585872


jwt token安全驗證流程:用戶發起登錄請求,服務端創建一個加密後的jwt信息,作爲token返回值,在後續請求中jwt信息作爲請求頭,服務端正確解密後可獲取到存儲的用戶信息,表示驗證通過;解密失敗說明token無效或者已過期。

jwt token的組成:header.poyload.sign

  • header:頭部,主要包括參數的類型--JWT,加密算法---RS512,頭部由json字符串用base64編碼生成;
  • poload:載荷,存放需要保存的一些用戶信息,主要包括主題、簽發者、接受者、到期時間等,載荷也由json字符串用base64編碼生成,不能存放敏感數據;
  • sign:簽名,防止惡意篡改數據。

依賴:

		<!-- 使用JWT在用戶和服務器之間傳遞安全可靠的信息 -->
		<dependency>
			<groupId>io.jsonwebtoken</groupId>
			<artifactId>jjwt</artifactId>
			<version>0.6.0</version>
		</dependency>

jwt加解密的工具類:

package cn.lsh.util;

import java.security.Key;
import java.util.Date;

import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import org.apache.commons.lang.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;




import cn.lsh.entity.User;
import cn.lsh.vo.security.Audience;
import cn.lsh.vo.security.LoginParamter;

public class JwtUtils {
	private static final Logger LOGGER=LoggerFactory.getLogger(JwtUtils.class);
	
	private JwtUtils(){
		
	}

	/*
	 * 驗證jwt是否合法,即解密
	 */
	public static Claims parseJWT(String jsonWebToken,String base64Security){
		try {
			return Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary(base64Security))
					.parseClaimsJws(jsonWebToken)
					.getBody();		
		} catch (Exception e) {
			// TODO: handle exception
			LOGGER.error("exception message is: {}", ExceptionUtils.getStackTrace(e));
			return null;
		}
	}
	
	/*
	 * 創建jwt,即加密
	 */
	public static String createJWT(LoginParamter loginParamter,User user,Audience audience){
		long ttlmillis=audience.getExpiresSecond()*1000;
		String base64Security=audience.getBase64Secret();
		Date now=new Date(System.currentTimeMillis());
        
		//生成簽名密鑰
		byte[] apiKeySecretBytes=DatatypeConverter.parseBase64Binary(base64Security);
		Key signingKey=new SecretKeySpec(apiKeySecretBytes, SignatureAlgorithm.HS256.getJcaName());
		
		//添加構成JWT的參數		
		JwtBuilder builder=Jwts.builder().setHeaderParam("typ", "JWT")//typ表示token的類型
				.claim("role", user.getRole())// 自定義屬性
				.claim("unique_name", loginParamter.getUserName())
				.claim("userid", user.getName())
				.setIssuer(audience.getName())// 簽發者
				.setAudience(audience.getClientId())//接受者
				.signWith(SignatureAlgorithm.HS256, signingKey);// 簽名算法以及密匙
		
        //添加Token過期時間
		if(ttlmillis>=0){
			Date exp=new Date(System.currentTimeMillis()+ttlmillis);
			builder.setExpiration(exp)// 過期時間
			.setNotBefore(now);// 失效時間
		}
		
		//生成JWT
		return builder.compact();
	}
	
	public static void main(String[] args) {
		Claims c=parseJWT("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlIjoi566h55CG5ZGYIiwidW5pcXVlX25hbWUiOiJsaXVzaGlodWEiLCJ1c2VyaWQiOiJsaXVzaGlodWEiLCJpc3MiOiJsaXVzaGlodWEiLCJhdWQiOiIwOThmNmJjZDQ2MjFkMzczY2FkZTRlODMyNjI3YjRmNiIsImV4cCI6MTUwMjM1OTQ1NSwibmJmIjoxNTAyMzUyMjU0fQ.OeDN4deNUlDiUmwROjxw5_xrurJt46b1RZ0K5yNKH88", 
				"MDk4ZjZiY2Q0NjIxZDM3M2NhZGU0ZTgzMjYyN2I0ZjY=");
		System.out.println(c);
	}
}

audience包含token的一些信息:

package cn.lsh.vo.security;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import lombok.Data;

@Data
//綁定屬性的配置信息到該bean中,配置信息前綴爲audience
@ConfigurationProperties(prefix="audience")
@Component
@ApiModel(value="JWT")
public class Audience {

	@ApiModelProperty(value="傳入的客戶端id,相當於微信的openID",required=true)
	private String clientId;
	@ApiModelProperty(value="64位公鑰",required=true)
	private String base64Secret;
	@ApiModelProperty(value="令牌發行者姓名",required=true)
	private String name;
	@ApiModelProperty(value="令牌有效時間,單位爲秒",required=true)
	private int expiresSecond;
}

一、在用戶登錄是生成token,返回給客戶端

String accessToken=JwtUtils.createJWT(loginParamter, user, audience);

二、在用戶下次請求是驗證token

	private boolean isValidJwt(HttpServletRequest request){
		LOGGER.info("{} request to {}",request.getMethod(),request.getRequestURL());
		String authorization=request.getHeader("Authorization");
		LOGGER.info("authorization is: {}",authorization);
		//access_token的頭信息,定義爲bearer
		String headString=authorization.substring(0, 6).toLowerCase();
		//compareTo逐個比較兩個字符串中相對字符的ascll值,所有字符都相同返回0,發現小於時返回正整數,大於時返回負整數,即ascll值的差值。
		if(headString.compareTo(Constants.BEARER)==0){
			authorization=authorization.substring(6, authorization.length());
			if(JwtUtils.parseJWT(authorization, audience.getBase64Secret())!=null){
				return true;
			}
		}
		return false;
	}





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章