java JWT生成和解析token的使用

以前單體應(yīng)用控制登錄session就夠了,后來(lái)對(duì)于多客戶端乘客,可以用cas做統(tǒng)一認(rèn)證狐血,之前也成功配置過(guò)cas5.3.9實(shí)現(xiàn)多客戶端單點(diǎn)登錄單點(diǎn)登出案例,但是也很麻煩易核,最大的缺點(diǎn)是cas還要另起一個(gè)用來(lái)做統(tǒng)一認(rèn)證的服務(wù)匈织,占用一個(gè)端口,而且也很吃內(nèi)存牡直,相似原理的還可以用redis等緩存數(shù)據(jù)庫(kù)弄一個(gè)共享緩存缀匕,也可以實(shí)現(xiàn)多客戶端單點(diǎn)登錄的功能,但是這兩個(gè)的方法都要額外占用端口和服務(wù)碰逸,直到了解到JWT乡小。

JWT是用java寫(xiě)的,可以生成一個(gè)獨(dú)一無(wú)二的token字符串饵史。
包括Header,Claim,ExpiresAt,sign,Header通常由兩部分組成:令牌的類(lèi)型满钟,即JWT。和常用的散列算法约急,如HMAC SHA256或RSA零远。
例如:

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

Header部分的JSON被Base64Url編碼,形成JWT的第一部分厌蔽。
Clainm是要加密的StringId,ExpiresAt可以設(shè)置過(guò)期時(shí)間牵辣,sign可以自己私加密匙,如此:

                 JWT.create()
                    .withHeader(header)
                    .withClaim("userId", userId)
                    .withExpiresAt(date)
                    .sign(algorithm);

便可以創(chuàng)建出一個(gè)加密的token字符串奴饮,通過(guò)把這個(gè)字符串分發(fā)給其他客戶端就可以識(shí)別是不是同一個(gè)用戶纬向,是哪個(gè)用戶,從而很簡(jiǎn)單的實(shí)現(xiàn)單點(diǎn)登錄戴卜。

maven下載jar包(截止發(fā)文最新版是3.10.2):

       <dependency>
           <groupId>com.auth0</groupId>
           <artifactId>java-jwt</artifactId>
           <version>3.10.2</version>
       </dependency>

創(chuàng)建JWTUtil工廠工具類(lèi)

package com.zhaohy.app.utils;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;

public class JWTUtil {//過(guò)期時(shí)間
    private static final long EXPIRE_TIME = 15 * 60 * 1000;//默認(rèn)15分鐘
    //私鑰
    private static final String TOKEN_SECRET = "privateKey";
    
    /**
     * 生成簽名逾条,15分鐘過(guò)期
     * @param **username**
    * @param **password**
    * @return
     */
    public static String createToken(String userId) {
        try {
            // 設(shè)置過(guò)期時(shí)間
            Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
            // 私鑰和加密算法
            Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
            // 設(shè)置頭部信息
            Map<String, Object> header = new HashMap<>(2);
            header.put("Type", "Jwt");
            header.put("alg", "HS256");
            // 返回token字符串
            return JWT.create()
                    .withHeader(header)
                    .withClaim("userId", userId)
                    .withExpiresAt(date)
                    .sign(algorithm);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    
    /**
     * 生成token,自定義過(guò)期時(shí)間 毫秒
     * @param **username**
    * @param **password**
    * @return
     */
    public static String createToken(String userId,long expireDate) {
        try {
            // 設(shè)置過(guò)期時(shí)間
            Date date = new Date(System.currentTimeMillis() + expireDate);
            // 私鑰和加密算法
            Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
            // 設(shè)置頭部信息
            Map<String, Object> header = new HashMap<>(2);
            header.put("Type", "Jwt");
            header.put("alg", "HS256");
            // 返回token字符串
            return JWT.create()
                    .withHeader(header)
                    .withClaim("userId", userId)
                    .withExpiresAt(date)
                    .sign(algorithm);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
    /**
     * 檢驗(yàn)token是否正確
     * @param **token**
    * @return
     */
    public static String verifyToken(String token){
        try {
            Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
            JWTVerifier verifier = JWT.require(algorithm).build();
            DecodedJWT jwt = verifier.verify(token);
            String userId = jwt.getClaim("userId").asString();
            return userId;
        } catch (Exception e){
            return null;
        }
    }
    public static void main(String[] args) {
        String token = JWTUtil.createToken("zhaohy", 3000);
        System.out.println("token == " + token);
        String userId = JWTUtil.verifyToken(token);
        System.out.println("userId == " + userId);
        
        //新建定時(shí)任務(wù)
        Runnable runnable = new Runnable() {
            //run方法中是定時(shí)執(zhí)行的操作
            public void run() {
                System.out.println(new Date());
                String userId = JWTUtil.verifyToken(token);
                System.out.println("userId == " + userId);
            }
        };
        ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
        /*
         * 參數(shù)一:command:執(zhí)行線程
         * 參數(shù)二:initialDelay:初始化延時(shí)
         * 參數(shù)三:period:兩次開(kāi)始執(zhí)行最小間隔時(shí)間
         * 參數(shù)四:unit:計(jì)時(shí)單位
         */
        service.scheduleAtFixedRate(runnable, 0, 4, TimeUnit.SECONDS);
    }
}

運(yùn)行里面的main方法:


jwt-main方法輸出結(jié)果截圖

通過(guò)截圖中控制臺(tái)打印出的效果表明投剥,token可以被創(chuàng)建师脂,也可以被解析,過(guò)期時(shí)間之后就不見(jiàn)了江锨,過(guò)期時(shí)間是生效的吃警,至此,就可以在項(xiàng)目中愉快的使用啦啄育!

參考:https://www.cnblogs.com/ljl-blog/p/11164991.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末酌心,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子挑豌,更是在濱河造成了極大的恐慌安券,老刑警劉巖墩崩,帶你破解...
    沈念sama閱讀 211,376評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異侯勉,居然都是意外死亡鹦筹,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門(mén)址貌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)盛龄,“玉大人,你說(shuō)我怎么就攤上這事芳誓。” “怎么了啊鸭?”我有些...
    開(kāi)封第一講書(shū)人閱讀 156,966評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵锹淌,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我赠制,道長(zhǎng)赂摆,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,432評(píng)論 1 283
  • 正文 為了忘掉前任钟些,我火速辦了婚禮烟号,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘政恍。我一直安慰自己汪拥,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,519評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布篙耗。 她就那樣靜靜地躺著迫筑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪宗弯。 梳的紋絲不亂的頭發(fā)上脯燃,一...
    開(kāi)封第一講書(shū)人閱讀 49,792評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音蒙保,去河邊找鬼辕棚。 笑死,一個(gè)胖子當(dāng)著我的面吹牛邓厕,可吹牛的內(nèi)容都是我干的逝嚎。 我是一名探鬼主播,決...
    沈念sama閱讀 38,933評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼邑狸,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼懈糯!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起单雾,我...
    開(kāi)封第一講書(shū)人閱讀 37,701評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤赚哗,失蹤者是張志新(化名)和其女友劉穎她紫,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體屿储,經(jīng)...
    沈念sama閱讀 44,143評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡贿讹,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,488評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了够掠。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片民褂。...
    茶點(diǎn)故事閱讀 38,626評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖疯潭,靈堂內(nèi)的尸體忽然破棺而出赊堪,到底是詐尸還是另有隱情,我是刑警寧澤竖哩,帶...
    沈念sama閱讀 34,292評(píng)論 4 329
  • 正文 年R本政府宣布哭廉,位于F島的核電站,受9級(jí)特大地震影響相叁,放射性物質(zhì)發(fā)生泄漏遵绰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,896評(píng)論 3 313
  • 文/蒙蒙 一增淹、第九天 我趴在偏房一處隱蔽的房頂上張望椿访。 院中可真熱鬧,春花似錦虑润、人聲如沸成玫。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,742評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)梁剔。三九已至,卻和暖如春舞蔽,著一層夾襖步出監(jiān)牢的瞬間荣病,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工渗柿, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留个盆,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓朵栖,卻偏偏與公主長(zhǎng)得像颊亮,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子陨溅,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,494評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容