1. 程式人生 > 其它 >latex中插入程式碼

latex中插入程式碼

JWT即json web token,大家先看下面這張圖

大家可以觀察到,jwt String就是生成後的jwt字符集,其中有兩個 "."(注意:jwt校驗會對"."個數校驗,多或少都會校驗失敗),被"."分割的就是jwt的三個構成部分,即:header、payload、sign。

接下來,給大家講下jwt的生成規則和校驗規則

JWT生成規則:

1、設定加密方式、claims資訊(即payload)和signingkey

2、設定加密方式為header,並進行base編碼

3、設定claims資訊為payload,並進行base64編碼

4、對header和payload用"."拼接成jwt,,使用signingkey按照加密方式進行加密,生成sign

5、對Jwt和sign用"."生成最終的jwt

JWT校驗規則:

1、設定jwt和signingkey

2、按"."對jwt分成三部分,即:header、payload、sign

3、取第一部分進行base64解碼,獲取加密方式

4、取第二部分進行base64解碼,獲取業務引數,即payload

5、使用加密方式和signingkey建立校驗器,對header+payload進行加密,並與sign(即第三部分)進行對比

6、取出payload的有效期進行校驗,是否過期

7、通過校驗,返回claims資訊

附:

1、進行base64編碼時,會判斷是否為android客戶端,使用base64的庫不一樣,這點可以自行看原始碼。

2、jwt會對生成的base64字符集的特殊符號進行轉換,"-"換為"+",“_”換位"/",去掉尾部"="

3、jwt校驗時,會判斷是否有且只有兩個".",否則校驗失敗

原理總結:

1、三部分裡的header和payload是獨立的,無須signingkey,只需base64解碼即可看到payload的資訊,所以千萬不要在payload裡放敏感資訊

2、如果是使用jwt作為登入態校驗,建議使用對稱加密,因為非對稱解密效率相對較慢,較多請求下會影響效能

3、因jwt是無狀態的,之前見很多同學使用redis進行儲存,我不是很明白,這豈不是違反了jwt當初的設計原則

4、保證金鑰不要洩露,否則jwt可以被偽造

5、必要情況下,建議使用https

另附上個人的程式碼供大家參考

package com.yhc.demo.plugin;

import java.io.UnsupportedEncodingException;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.SignatureException;
import io.jsonwebtoken.UnsupportedJwtException;

/**
 * JwtToken工具類
 */
@Configuration
public class JwtService {

	private static final Logger log = LoggerFactory.getLogger(JwtService.class);

	@Value("${jwt.secret:123456}")
	private String secret;
	@Value("${jwt.expiration:60}")
	private Long expiration;

	/**
	 * 生成token
	 * 
	 * @param username
	 * @return token
	 */
	public String generateToken(String username) {

		Claims claims = Jwts.claims();
		claims.setIssuer(username); // jwt發行人
		claims.setIssuedAt(new Date()); // jwt生成時間
		claims.setExpiration(getExp()); // jwt過期時間
		claims.setSubject("auth"); // jwt主題
		claims.setAudience("yhc"); // jwt接受方
		claims.setId("uuid"); // jwt唯一身份標識
		claims.setNotBefore(new Date()); // jwt在此之前不可用

		return generateToken(claims);
	}

	/**
	 * 重新整理token
	 * 
	 * @param old token
	 * @return new token
	 */
	public String refreshToken(String token) {
		Claims claims = validToken(token);
		if (claims == null) {
			return null;
		}
		claims.setIssuedAt(new Date());
		claims.setExpiration(getExp());
		return generateToken(claims);
	}

	/**
	 * 根據token獲取發行人
	 * 
	 * @param token
	 * @return issuer
	 */
	public String getIssuer(String token) {
		Claims claims = validToken(token);
		return claims.getIssuer();
	}

	/**
	 * 校驗jwtToken,如無效,則返回Null,反之,返回負載物件
	 */
	private Claims validToken(String token) {
		Claims claims = getClaimsFromToken(token);
		if (claims != null) {
			Date exp = claims.getExpiration();
			if (exp.before(new Date())) {
				log.warn("# jwtToken已失效:{}", token);
				throw new RuntimeException("invalid token");
			}
		}
		return claims;
	}

	/**
	 * 從token中獲取JWT中的負載引數
	 */
	private Claims getClaimsFromToken(String token) {
		Claims claims = null;
		try {
			claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
		} catch (Exception e) {
			log.warn("# jwtToken格式驗證失敗:{}", token, e);
			throw new RuntimeException("token verification failed");
		}
		return claims;
	}

	/** 根據負載引數生成token */
	private String generateToken(Claims claims) {
		return Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS512, secret).compact();
	}

	/** 獲取token有效期 */
	private Date getExp() {
		return new Date(System.currentTimeMillis() + expiration * 1000);
	}

	public static void main(String[] args) throws ExpiredJwtException, UnsupportedJwtException, MalformedJwtException,
			SignatureException, IllegalArgumentException, UnsupportedEncodingException {

		String username = "yhc";

		Claims claims = Jwts.claims();
		claims.setIssuer(username); // jwt發行人
		claims.setIssuedAt(new Date()); // jwt生成時間
		claims.setExpiration(new Date(System.currentTimeMillis() + 3600 * 1000)); // jwt過期時間
		claims.setSubject("test"); // jwt主題
		claims.setAudience("yhc"); // jwt接受方
		claims.setId("uuid"); // jwt唯一身份標識
//		claims.setNotBefore(new Date()); // jwt在此之前不可用

		String visitTK = Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS512, "sad12f").compact();
		System.out.println(visitTK);// SystemValue.JWT_HEADER_VALUE_PREFIX +

		Claims claimsDecode = Jwts.parser().setSigningKey("sad12f").parseClaimsJws(visitTK).getBody();
		System.out.println(claimsDecode.getIssuer());

	}
}

  

以上純為個人總結,如有錯誤,還請指出,謝謝。