如何分析并實(shí)踐JSONWEBTOKEN-創(chuàng)新互聯(lián)

這篇文章將為大家詳細(xì)講解有關(guān)如何分析并實(shí)踐JSON WEB TOKEN,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

網(wǎng)站設(shè)計(jì)制作、成都網(wǎng)站建設(shè)的開(kāi)發(fā),更需要了解用戶,從用戶角度來(lái)建設(shè)網(wǎng)站,獲得較好的用戶體驗(yàn)。創(chuàng)新互聯(lián)多年互聯(lián)網(wǎng)經(jīng)驗(yàn),見(jiàn)的多,溝通容易、能幫助客戶提出的運(yùn)營(yíng)建議。作為成都一家網(wǎng)絡(luò)公司,打造的就是網(wǎng)站建設(shè)產(chǎn)品直銷(xiāo)的概念。選擇創(chuàng)新互聯(lián),不只是建站,我們把建站作為產(chǎn)品,不斷的更新、完善,讓每位來(lái)訪用戶感受到浩方產(chǎn)品的價(jià)值服務(wù)。

1. JSON WEB TOKEN

1.1 什么是JWT

JSON Web Token(JWT)是一個(gè)非常輕巧的規(guī)范。

這個(gè)規(guī)范允許我們使用JWT在用戶和服務(wù)器之間傳遞安全可靠的信息。 簡(jiǎn)稱(chēng)JWT,在HTTP通信過(guò)程中,進(jìn)行身份認(rèn)證。

我們知道HTTP通信是無(wú)狀態(tài)的,因此客戶端的請(qǐng)求到了服務(wù)端處理完之后是無(wú)法返回給原來(lái)的客戶端。

因此需要對(duì)訪問(wèn)的客戶端進(jìn)行識(shí)別,常用的做法是通過(guò)session機(jī)制:

客戶端在服務(wù)端登陸成功之后,服務(wù)端會(huì)生成一個(gè)sessionID,返回給客戶端,客戶端將sessionID保存到cookie中,再次發(fā)起請(qǐng)求的時(shí)候,攜帶cookie中的sessionID到服務(wù)端,服務(wù)端會(huì)緩存該session(會(huì)話),當(dāng)客戶端請(qǐng)求到來(lái)的時(shí)候,服務(wù)端就知道是哪個(gè)用戶的請(qǐng)求,并將處理的結(jié)果返回給客戶端,完成通信。

通過(guò)上面的分析,可以知道session存在以下問(wèn)題:

1、session保存在服務(wù)端,當(dāng)客戶訪問(wèn)量增加時(shí),服務(wù)端就需要存儲(chǔ)大量的session會(huì)話,對(duì)服務(wù)器有很大的考驗(yàn);

2、當(dāng)服務(wù)端為集群時(shí),用戶登陸其中一臺(tái)服務(wù)器,會(huì)將session保存到該服務(wù)器的內(nèi)存中,但是當(dāng)用戶的訪問(wèn)到其他服務(wù)器時(shí),會(huì)無(wú)法訪問(wèn),通常采用緩存一致性技術(shù)來(lái)保證可以共享,或者采用第三方緩存來(lái)保存session,不方便。

1.2 Json Web Token是怎么做的?
  • 客戶端通過(guò)用戶名和密碼登錄服務(wù)器;

  • 服務(wù)端對(duì)客戶端身份進(jìn)行驗(yàn)證;

  • 服務(wù)端對(duì)該用戶生成Token,返回給客戶端;

  • 客戶端發(fā)起請(qǐng)求,需要攜帶該Token;

  • 服務(wù)端收到請(qǐng)求后,首先驗(yàn)證Token,之后返回?cái)?shù)據(jù)。

  • 客戶端將Token保存到本地瀏覽器,一般保存到cookie中。

服務(wù)端不需要保存Token,只需要對(duì)Token中攜帶的信息進(jìn)行驗(yàn)證即可;

無(wú)論客戶端訪問(wèn)后臺(tái)的那臺(tái)服務(wù)器,只要可以通過(guò)用戶信息的驗(yàn)證即可。

1.3 JWT 的原理

JWT 的原理是,服務(wù)器認(rèn)證以后,生成一個(gè) JSON 對(duì)象,發(fā)回給用戶,就像下面這樣。

{ "姓名": "張三", "角色": "管理員", "到期時(shí)間": "2018年10月31日0點(diǎn)0分"}

以后,用戶與服務(wù)端通信的時(shí)候,都要發(fā)回這個(gè) JSON 對(duì)象。服務(wù)器完全只靠這個(gè)對(duì)象認(rèn)定用戶身份。為了防止用戶篡改數(shù)據(jù),服務(wù)器在生成這個(gè)對(duì)象的時(shí)候,會(huì)加上簽名(詳見(jiàn)后文)。

服務(wù)器就不保存任何 session 數(shù)據(jù)了,也就是說(shuō),服務(wù)器變成無(wú)狀態(tài)了,從而比較容易實(shí)現(xiàn)擴(kuò)展。

1.4 JWT 的數(shù)據(jù)結(jié)構(gòu)

實(shí)際的 JWT 大概就像下面這樣。

它是一個(gè)很長(zhǎng)的字符串,中間用點(diǎn)(.)分隔成三個(gè)部分。注意,JWT 內(nèi)部是沒(méi)有換行的,這里只是為了便于展示,將它寫(xiě)成了幾行。

JWT 的三個(gè)部分依次如下。

  • Header(頭部)

  • Payload(負(fù)載)

  • Signature(簽名)

寫(xiě)成一行,就是下面的樣子。

如何分析并實(shí)踐JSON WEB TOKEN

1.4.1 Header

Header 部分是一個(gè) JSON 對(duì)象,描述 JWT 的元數(shù)據(jù),通常是下面的樣子。

{ "alg": "HS256", "typ": "JWT"}

上面代碼中,alg屬性表示簽名的算法(algorithm),默認(rèn)是 HMAC SHA256(寫(xiě)成 HS256);typ屬性表示這個(gè)令牌(token)的類(lèi)型(type),JWT 令牌固定寫(xiě)為JWT。

最后,將上面的 JSON 對(duì)象使用 Base64URL 算法(詳見(jiàn)后文)轉(zhuǎn)成字符串。

1.4.2 Payload

Payload 部分也是一個(gè) JSON 對(duì)象,用來(lái)存放實(shí)際需要傳遞的數(shù)據(jù)。JWT 規(guī)定了7個(gè)官方字段,供選用。

  • iss (issuer):簽發(fā)人

  • exp (expiration time):過(guò)期時(shí)間

  • sub (subject):主題

  • aud (audience):受眾

  • nbf (Not Before):生效時(shí)間

  • iat (Issued At):簽發(fā)時(shí)間

  • jti (JWT ID):編號(hào)

除了官方字段,你還可以在這個(gè)部分定義私有字段,下面就是一個(gè)例子。

{ "sub": "1234567890", "name": "John Doe", "admin": true}

注意,JWT 默認(rèn)是不加密的,任何人都可以讀到,所以不要把秘密信息放在這個(gè)部分。

這個(gè) JSON 對(duì)象也要使用 Base64URL 算法轉(zhuǎn)成字符串。

1.4.3 Signature

Signature 部分是對(duì)前兩部分的簽名,防止數(shù)據(jù)篡改。

首先,需要指定一個(gè)密鑰(secret)。這個(gè)密鑰只有服務(wù)器才知道,不能泄露給用戶。然后,使用 Header 里面指定的簽名算法(默認(rèn)是 HMAC SHA256),按照下面的公式產(chǎn)生簽名。

HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)

算出簽名以后,把 Header、Payload、Signature 三個(gè)部分拼成一個(gè)字符串,每個(gè)部分之間用"點(diǎn)"(.)分隔,就可以返回給用戶。

1.4.4 Base64URL

前面提到,Header 和 Payload 串型化的算法是 Base64URL。這個(gè)算法跟 Base64 算法基本類(lèi)似,但有一些小的不同。

JWT 作為一個(gè)令牌(token),有些場(chǎng)合可能會(huì)放到 URL(比如 api.example.com/?token=xxx)。

Base64 有三個(gè)字符+、/=,在 URL 里面有特殊含義,所以要被替換掉:=被省略、+替換成-,/替換成_。這就是 Base64URL 算法。

1.5 JWT 的使用方式

客戶端收到服務(wù)器返回的 JWT,可以儲(chǔ)存在 Cookie 里面,也可以儲(chǔ)存在 localStorage。

此后,客戶端每次與服務(wù)器通信,都要帶上這個(gè) JWT。你可以把它放在 Cookie 里面自動(dòng)發(fā)送,但是這樣不能跨域,所以更好的做法是放在 HTTP 請(qǐng)求的頭信息Authorization字段里面。

Authorization: Bearer <token>

另一種做法是,跨域的時(shí)候,JWT 就放在 POST 請(qǐng)求的數(shù)據(jù)體里面。

1.6 JWT 的幾個(gè)特點(diǎn)

JWT 默認(rèn)是不加密,但也是可以加密的。生成原始 Token 以后,可以用密鑰再加密一次。

  • JWT 不加密的情況下,不能將秘密數(shù)據(jù)寫(xiě)入 JWT。

  • JWT 不僅可以用于認(rèn)證,也可以用于交換信息。有效使用 JWT,可以降低服務(wù)器查詢數(shù)據(jù)庫(kù)的次數(shù)。

  • JWT 的大缺點(diǎn)是,由于服務(wù)器不保存 session 狀態(tài),因此無(wú)法在使用過(guò)程中廢止某個(gè) token,或者更改 token 的權(quán)限。也就是說(shuō),一旦 JWT 簽發(fā)了,在到期之前就會(huì)始終有效,除非服務(wù)器部署額外的邏輯。

  • JWT 本身包含了認(rèn)證信息,一旦泄露,任何人都可以獲得該令牌的所有權(quán)限。為了減少盜用,JWT 的有效期應(yīng)該設(shè)置得比較短。對(duì)于一些比較重要的權(quán)限,使用時(shí)應(yīng)該再次對(duì)用戶進(jìn)行認(rèn)證。

  • 為了減少盜用,JWT 不應(yīng)該使用 HTTP 協(xié)議明碼傳輸,要使用 HTTPS 協(xié)議傳輸。

2.手撕一個(gè)Demo

創(chuàng)建一個(gè)maven項(xiàng)目,加入pom依賴(lài):

<!--JWT--><dependencies><!--JWT-->    <dependency>        <groupId>io.jsonwebtoken</groupId>        <artifactId>jjwt</artifactId>        <version>0.9.0</version>    </dependency>    <dependency>        <groupId>junit</groupId>        <artifactId>junit</artifactId>        <version>RELEASE</version>        <scope>compile</scope>    </dependency></dependencies><build>    <plugins>        <plugin>            <groupId>org.apache.maven.plugins</groupId>            <artifactId>maven-compiler-plugin</artifactId>            <version>3.5</version>            <configuration>                <source>1.8</source>                <target>1.8</target>            </configuration>        </plugin>    </plugins></build>

創(chuàng)建類(lèi)JWTDemo:

public class JWTDemo {    //加密的    private static final String SECRET_KEY = "123456789";    @Test    public void jwtTest() throws InterruptedException {        // 設(shè)置3秒后過(guò)期        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");        long time = System.currentTimeMillis() + 30*60*1000;        String jwt = this.buildJwt(new Date(time));        System.out.println("jwt = " + jwt);        // 驗(yàn)證token是否可用        boolean isOk = this.isJwtValid(jwt);        System.out.println(isOk);    }    public String buildJwt(Date exp) {        String jwt = Jwts.builder()                .signWith(SignatureAlgorithm.HS256, SECRET_KEY)    //SECRET_KEY是加密算法對(duì)應(yīng)的密鑰,這里使用額是HS256加密算法                .setExpiration(exp)     //expTime是過(guò)期時(shí)間                .claim("name","wangtingjun")                .claim("age","18")                .claim("key", "vaule")      //該方法是在JWT中加入值為vaule的key字段                .compact();        return jwt;    }    public boolean isJwtValid(String jwt) {        try {            //解析JWT字符串中的數(shù)據(jù),并進(jìn)行最基礎(chǔ)的驗(yàn)證            Claims claims = Jwts.parser()                    .setSigningKey(SECRET_KEY)  //SECRET_KEY是加密算法對(duì)應(yīng)的密鑰,jjwt可以自動(dòng)判斷機(jī)密算法                    .parseClaimsJws(jwt)    //jwt是JWT字符串                    .getBody();            System.out.println(claims);            String vaule = claims.get("key", String.class);     //獲取自定義字段key            //判斷自定義字段是否正確            if ("vaule".equals(vaule)) {                return true;            } else {                return false;            }        }        //在解析JWT字符串時(shí),如果密鑰不正確,將會(huì)解析失敗,拋出SignatureException異常,說(shuō)明該JWT字符串是偽造的        //在解析JWT字符串時(shí),如果‘過(guò)期時(shí)間字段’已經(jīng)早于當(dāng)前時(shí)間,將會(huì)拋出ExpiredJwtException異常,說(shuō)明本次請(qǐng)求已經(jīng)失效        catch (SignatureException | ExpiredJwtException e) {            return false;        }    }}

最后可以在控制臺(tái)看到打印出來(lái)的信息

jwt = eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1NDA5NzgxMzAsIm5hbWUiOiJ3YW5ndGluZ2p1biIsImFnZSI6IjE4Iiwia2V5IjoidmF1bGUifQ.XEDlK0UNTV3aKANQe9QCE2Y7JiP7D7ebrDVOs2JxRCQ{exp=1540978130, name=wangtingjun, age=18, key=vaule}true

關(guān)于如何分析并實(shí)踐JSON WEB TOKEN就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。

當(dāng)前題目:如何分析并實(shí)踐JSONWEBTOKEN-創(chuàng)新互聯(lián)
標(biāo)題路徑:http://muchs.cn/article22/djeejc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站營(yíng)銷(xiāo)、自適應(yīng)網(wǎng)站App設(shè)計(jì)、用戶體驗(yàn)、標(biāo)簽優(yōu)化全網(wǎng)營(yíng)銷(xiāo)推廣

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

微信小程序開(kāi)發(fā)