Java實現基於token認證

一、Token優勢

1.1 與cookie相比較的優勢

1、支持跨域訪問,將token置於請求頭中,而cookie是不支持跨域訪問的;

2、無狀態化,服務端無需存儲token,只需要驗證token信息是否正確即可,而session需要在服務端存儲,一般是通過cookie中的sessionID在服務端查找對應的session;

3、無需綁定到一個特殊的身份驗證方案(傳統的用戶名密碼登陸),只需要生成的token是符合我們預期設定的即可;

4、更適用於移動端(Android,iOS,小程序等等),像這種原生平臺不支持cookie,比如說微信小程序,每一次請求都是一次會話,當然我們可以每次去手動爲他添加cookie,詳情請查看博主另一篇博客;

5、避免CSRF跨站僞造攻擊,還是因爲不依賴cookie;

6、非常適用於RESTful API,這樣可以輕易與各種後端(java,.net,python......)相結合,去耦合

還有一些優勢這裏就不一一列舉了。

1.2 基於JWT的token認證實現

JWT:JSON  Web  Token,其實token就是一段字符串,由三部分組成:Header,Payload,Signature。詳細情況請自行百度,現在,上代碼。

二、加密\解密

2.1 pom.xml

	<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
		<dependency>
			<groupId>com.auth0</groupId>
			<artifactId>java-jwt</artifactId>
			<version>3.8.1</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-core</artifactId>
			<version>2.9.4</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-annotations</artifactId>
			<version>2.9.4</version>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>2.9.4</version>
		</dependency>

2.2 加密

		//加密的數據
		int userId = 51;
		//加密的簽名
		Algorithm algorithm = Algorithm.HMAC256("eyJhbGciO");
		//加密頭
		Map<String, Object> header = new HashMap<String, Object>();
		header.put("typ", "JWT");
		header.put("alg", "HS256");
		try {
			//超時時間
			Date date = new Date(System.currentTimeMillis() + 30  * 1000);
			//令牌token
			String token = JWT.create().withHeader(header).withClaim("userId", userId).withExpiresAt(date)
					.sign(algorithm);
			System.out.println(token);
		} catch (Exception e) {
			// TODO: handle exception
		}
		

2.3 解密

//前端傳過來的令牌
		String token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1Nzg1NTEyOTgsInVzZXJJZCI6ImhlbGxvIn0.mVXwBkBMO-Sr3FJPZSVLezUuxdvMwNsGgRqTCVufH8o";
		//和上面一樣的簽名
		Algorithm algorithm = Algorithm.HMAC256("eyJhbGciO");
		JWTVerifier verifier = JWT.require(algorithm).build();
		//開始解密,失敗的話會出現異常
		DecodedJWT jwt = verifier.verify(token);
		System.out.println(jwt.getClaim("userId").asInt());

三、封裝工具類JWTUtil

public class JWTUtil {
	private static final String TOKEN_SECRET = "eyJhbGciO";
	private static final String CLAIM_NAME = "sign";
	private static final long EXPIRE_TIME = 15 * 60 * 1000;

	public static String sign(String sign) {
		try {
			Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
			Map<String, Object> header = new HashMap<String, Object>();
			header.put("typ", "JWT");
			header.put("alg", "HS256");
			Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
			String token = JWT.create().withHeader(header).withClaim(CLAIM_NAME, sign).withExpiresAt(date)
					.sign(algorithm);
			return token;
		} catch (Exception e) {
			return null;
		}
	}

	public static String verify(String token) {
		try {
			Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
			JWTVerifier verifier = JWT.require(algorithm).build();
			DecodedJWT jwt = verifier.verify(token);
			return jwt.getClaim(CLAIM_NAME).asString();
		} catch (Exception e) {
			return null;
		}
	}

}

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