小聲bbb
說到系統的安全識別,記得自己第一個項目,用的就是session,用戶登錄進來以後,給他session標記登錄,記錄id進去,輕輕鬆鬆,設計的操作也很簡單,類似操作HashMap。
這大概也有1年多快兩年了,現在回頭看真的是可怕,幾乎在裸奔
衆所周知,平常使用的Session是存儲在服務器的一種技術,可以理解爲一個會話id,每次使用HTTP請求,都會攜帶一個sessionId,服務器根據這個SessionId去找對應的session
しかし,我預判了你的預判
第三方完全可以隨便輸入一個sessionId,就能破了簡單session記錄登錄的模式了,要想保住自己的大寶貝,必須使用安全加密的功能
關於session安全性文章,搜一下csdn,很多的
Session安全性
除此之外,session因爲是服務器記錄登錄狀態,無疑也給服務器增加了壓力,那麼下面就是JWT(或者叫Token)發光發熱的舞臺了!
只是爲了構建JWT請快步到相應的位置
啥是JWT
JWT的全稱JSON Web Token
這裏我先簡單說一下JWT是個啥東西,然後分析爲什麼好用
JWT可以看做一個身份證,
衆所周知,身份證有這幾個特性:
- 身份證不能僞造(別動歪腦筋)
- 身份證上有個人信息
- 身份證上有簽發機關
- 身份證上有有效期
事實上,這幾乎就是JWT了
JWT的特性完全相同,甚至可以用理解身份證的角度來理解他
- 你的網站簽發一個令牌(跟我念:身份證)
- 客戶端拿着這個令牌找你訪問
- 你用你三歲就發明的識別機對令牌(身份證)識別
- 你已經明白他是自己人了,並邀請他一起進來看電視
- 以下爲收費項目~~
咳咳,不搞hs,回到正軌,通過我們一本正經的分析,
我們不難發現:Token可以做到在你臉前裸奔,但你卻無可奈何
盤點主要特性:
- 存儲簡單的信息,並且大家都能獲取信息
- 無法作假
- 存在過期
其中第一點很重要,token裏面的信息是公開的,所以別放密碼
@某大學某實驗室的某學弟
細說JWT
JWT通常情況下是三段,但是也存在一些喪心病狂的,把token又加密了一遍(內行,我直呼內行)
下面是官方給的一個demo(例子)
這個網站也是可以訪問的,可以自己試着玩,也可以用來測試
https://jwt.io/
其中很明顯爲三個部分:HEADER(頭部)、PAYLOAD(數據)、VERIFY SIGNATURE(簽名)
- 頭部:這個token使用了什麼加密算法
- 數據:自己定的,想塞什麼塞什麼,一般有規定的幾個內容
- 簽名:可以理解爲使用祕鑰加密後得到的一個不可逆加密(存密碼用的很多,原理類似)
其中數據(PAYLOAD)官方定了這幾個部分:
iss (issuer):簽發人
exp (expiration time):過期時間
sub (subject):主題
aud (audience):受衆
nbf (Not Before):生效時間
iat (Issued At):簽發時間
jti (JWT ID):編號
簽名(Signature )部分是對前兩部分的簽名,防止數據篡改。
首先,需要指定一個密鑰(secret)。這個密鑰只有服務器才知道,不能泄露給用戶。然後,使用 Header 裏面指定的簽名算法(默認是 HMAC SHA256),按照下面的公式產生簽名。
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
算出簽名以後,把 Header、Payload、Signature 三個部分拼成一個字符串,每個部分之間用"點"(.)分隔,就可以返回給用戶。
JWT 的幾個特點
上面用比較形象的方式描述了JWT,下面用官方的話來總結特點
- JWT 默認是不加密,但也是可以加密的。生成原始 Token 以後,可以用密鑰再加密一次。
- JWT 不加密的情況下,不能將祕密數據寫入 JWT(個人認爲加密了也最好別加吧,祕密的東西最好保持在用後即毀的狀態)。
- JWT 不僅可以用於認證,也可以用於交換信息。有效使用 JWT,可以降低服務器查詢數據庫的次數。
- JWT 的最大缺點是,由於服務器不保存 session 狀態,因此無法在使用過程中廢止某個 token,或者更改 token的權限。也就是說,一旦 JWT 簽發了,在到期之前就會始終有效,除非服務器部署額外的邏輯(用緩存保存一次簽發出去的JWT)。
- JWT 本身包含了認證信息,一旦泄露,任何人都可以獲得該令牌的所有權限。爲了減少盜用,JWT的有效期應該設置得比較短。對於一些比較重要的權限,使用時應該再次對用戶進行認證。
- 爲了減少盜用,JWT 不應該使用 HTTP 協議明碼傳輸,要使用 HTTPS 協議傳輸。
現在來完成一個JWT的實現
詳細大家都有maven的經驗了
實在不會可以去maven倉庫把jar包下載
你用你三歲時就買來的鍵盤,輕鬆的使用這個jjwt框架,並老老實實的按照我給的流程感♂受
第一步,導入maven
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
第二步,編寫Token的生成邏輯
public static String tokens(Map<String, Object> claims, String secretKey, int millisecond, String jwtIssuer, String jwtAud) {
//獲取當前的時間
Calendar calendar = Calendar.getInstance();
Date date = new Date(System.currentTimeMillis());
calendar.setTime(date);
//向後退後秒數
calendar.add(Calendar.MILLISECOND, millisecond);
Date endTime = calendar.getTime();
JwtBuilder builder = Jwts.builder().setClaims(claims)
.signWith(SignatureAlgorithm.HS256, secretKey)
.setClaims(claims)
.setIssuedAt(new Date())
.setExpiration(endTime)
.setIssuer(jwtIssuer)
.setAudience(jwtAud);
return builder.compact();
}
JwtBuilder 是jjwt提供的工具,可以很輕鬆的構建出一個jwt,利用Builder設計模式,對內容進行定義
其中payload的自定義內容是使用map保存的
編寫解密驗證的邏輯
public static Claims parse(String jwt, String secretKey) throws JwtExpireException, JwtVerifyException , JwtNotExistException{
Claims claims = null;
try {
claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(jwt).getBody();
} catch (ExpiredJwtException expiredJwtException) {
throw new ExpiredJwtException("token過期");
} catch (JwtException jwtException) {
throw new JwtException("JWT驗證錯誤");
} catch (IllegalArgumentException illegalArgumentException) {
throw new IllegalArgumentException("Token爲空");
}
return claims;
}
Claims類就是你的PAYLOAD,可以直接取出信息使用,不拋出異常就視爲成功了
一鍵三連,支持弟弟
寫到這裏,就完成了基礎的內容了,爲了我們用起來更爽,
可以自行進行二次封裝,體驗更棒