最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

如何利用jwt來保護你的接口服務(wù)

 更新時間:2021年08月12日 11:47:13   作者:Java旅途  
項目軟件要對外提供部分定制接口,為了保證軟件數(shù)據(jù)的安全性,這篇文章主要給大家介紹了關(guān)于如何利用jwt來保護你的接口服務(wù)的相關(guān)資料,需要的朋友可以參考下

前言

以前寫過一篇關(guān)于接口服務(wù)規(guī)范的文章,原文在此,里面關(guān)于安全性問題重點講述了通過appid,appkey,timestamp,nonce以及sign來獲取token,使用token來保障接口服務(wù)的安全。今天我們來講述一種更加便捷的方式,使用jwt來生成token。

一、JWT是什么

JSON Web Token(JWT) 定義了一種緊湊且自包含的方式,用于在各方之間作為 JSON 對象安全地傳輸信息。該信息可以被驗證和信任,因為它是經(jīng)過數(shù)字簽名的。JWT可以設(shè)置有效期。

JWT是一個很長的字符串,包含了Header,Playload和Signature三部分內(nèi)容,中間用.進行分隔。

Headers

Headers部分描述的是JWT的基本信息,一般會包含簽名算法和令牌類型,數(shù)據(jù)如下:

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

Playload

Playload就是存放有效信息的地方,JWT規(guī)定了以下7個字段,建議但不強制使用:

iss: jwt簽發(fā)者
sub: jwt所面向的用戶
aud: 接收jwt的一方
exp: jwt的過期時間,這個過期時間必須要大于簽發(fā)時間
nbf: 定義在什么時間之前,該jwt都是不可用的
iat: jwt的簽發(fā)時間
jti: jwt的唯一身份標識,主要用來作為一次性token

除此之外,我們還可以自定義內(nèi)容

{
    "name":"Java旅途",
    "age":18
}

Signature

Signature是將JWT的前面兩部分進行加密后的字符串,將Headers和Playload進行base64編碼后使用Headers中規(guī)定的加密算法和密鑰進行加密,得到JWT的第三部分。

二、JWT生成和解析token

在應(yīng)用服務(wù)中引入JWT的依賴

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.0</version>
</dependency>

根據(jù)JWT的定義生成一個使用RSA算法加密的,有效期為30分鐘的token

public static String createToken(User user) throws Exception{

    return Jwts.builder()
        .claim("name",user.getName())
        .claim("age",user.getAge())
        // rsa加密
        .signWith(SignatureAlgorithm.RS256, RsaUtil.getPrivateKey(PRIVATE_KEY))
        // 有效期30分鐘
        .setExpiration(DateTime.now().plusSeconds(30 * 60).toDate())
        .compact();
}

登錄接口驗證通過后,調(diào)用JWT生成帶有用戶標識的token響應(yīng)給用戶,在接下來的請求中,頭部攜帶token進行驗簽,驗簽通過后,正常訪問應(yīng)用服務(wù)。

public static Claims parseToken(String token) throws Exception{
    return Jwts
        .parser()
        .setSigningKey(RsaUtil.getPublicKey(PUBLIC_KEY))
        .parseClaimsJws(token)
        .getBody();
}

三、token續(xù)簽問題

上面講述了關(guān)于JWT驗證的過程,現(xiàn)在我們考慮這樣一個問題,客戶端攜帶token訪問下單接口,token驗簽通過,客戶端下單成功,返回下單結(jié)果,然后客戶端帶著token調(diào)用支付接口進行支付,驗簽的時候發(fā)現(xiàn)token失效了,這時候應(yīng)該怎么辦?只能告訴用戶token失效,然后讓用戶重新登錄獲取token?這種體驗是非常不好的,oauth2在這方面做的比較好,除了簽發(fā)token,還會簽發(fā)refresh_token,當token過期后,會去調(diào)用refresh_token重新獲取token,如果refresh_token也過期了,那么再提示用戶去登錄?,F(xiàn)在我們模擬oauth2的實現(xiàn)方式來完成JWT的refresh_token。

思路大概就是用戶登錄成功后,簽發(fā)token的同時,生成一個加密串作為refresh_token,refresh_token存放在redis中,設(shè)置合理的過期時間(一般會將refresh_token的過期時間設(shè)置的比較久一點)。然后將token和refresh_token響應(yīng)給客戶端。偽代碼如下:

@PostMapping("getToken")
public ResultBean getToken(@RequestBody LoingUser user){

    ResultBean resultBean = new ResultBean();
    // 用戶信息校驗失敗,響應(yīng)錯誤
    if(!user){
        resultBean.fillCode(401,"賬戶密碼不正確");
        return resultBean;
    }
    String token = null;
    String refresh_token = null;
    try {
        // jwt 生成的token
        token = JwtUtil.createToken(user);
        // 刷新token
        refresh_token = Md5Utils.hash(System.currentTimeMillis()+"");
        // refresh_token過期時間為24小時
        redisUtils.set("refresh_token:"+refresh_token,token,30*24*60*60);
    } catch (Exception e) {
        e.printStackTrace();
    }

    Map<String,Object> map = new HashMap<>();
    map.put("access_token",token);
    map.put("refresh_token",refresh_token);
    map.put("expires_in",2*60*60);
    resultBean.fillInfo(map);
    return resultBean;
}

客戶端調(diào)用接口時,在請求頭中攜帶token,在攔截器中攔截請求,驗證token的有效性,如果驗證token失敗,則去redis中判斷是否是refresh_token的請求,如果refresh_token驗證也失敗,則給客戶端響應(yīng)鑒權(quán)異常,提示客戶端重新登錄,偽代碼如下:

HttpHeaders headers = request.getHeaders();
// 請求頭中獲取令牌
String token = headers.getFirst("Authorization");
// 判斷請求頭中是否有令牌
if (StringUtils.isEmpty(token)) {
    resultBean.fillCode(401,"鑒權(quán)失敗,請攜帶有效token");
    return resultBean;
}
if(!token.contains("Bearer")){
    resultBean.fillCode(401,"鑒權(quán)失敗,請攜帶有效token");
    return resultBean;
}

token = token.replace("Bearer ","");
// 如果請求頭中有令牌則解析令牌
try {
    Claims claims = TokenUtil.parseToken(token).getBody();
} catch (Exception e) {
    e.printStackTrace();
    String refreshToken = redisUtils.get("refresh_token:" + token)+"";
    if(StringUtils.isBlank(refreshToken) || "null".equals(refreshToken)){
        resultBean.fillCode(403,"refresh_token已過期,請重新獲取token");
        return resultbean;
    }
}

refresh_token來換取token的偽代碼如下:

@PostMapping("refreshToken")
public Result refreshToken(String token){

    ResultBean resultBean = new ResultBean();
    String refreshToken = redisUtils.get(TokenConstants.REFRESHTOKEN + token)+"";
    String access_token = null;
    try {
        Claims claims = JwtUtil.parseToken(refreshToken);
        String username = claims.get("username")+"";
        String password = claims.get("password")+"";
        LoginUser loginUser = new LoginUser();
        loginUser.setUsername(username);
        loginUser.setPassword(password);
        access_token = JwtUtil.createToken(loginUser);
    } catch (Exception e) {
        e.printStackTrace();
    }
    Map<String,Object> map = new HashMap<>();
    map.put("access_token",access_token);
    map.put("refresh_token",token);
    map.put("expires_in",30*60);
    resultBean.fillInfo(map);
    return resultBean;
}

通過上面的分析,我們簡單的實現(xiàn)了token的簽發(fā),驗簽以及續(xù)簽問題,JWT作為一個輕量級的鑒權(quán)框架,使用起來非常方便,但是也會存在一些問題,

  • JWT的Playload部分只是經(jīng)過base64編碼,這樣我們的信息其實就完全暴露了,一般不要將敏感信息存放在JWT中。
  • JWT生成的token比較長,每次在請求頭中攜帶token,導(dǎo)致請求偷會比較大,有一定的性能問題。
  • JWT生成后,服務(wù)端無法廢棄,只能等待JWT主動過期。

下面這段是我網(wǎng)上看到的一段關(guān)于JWT比較適用的場景:

  • 有效期短
  • 只希望被使用一次

比如,用戶注冊后發(fā)一封郵件讓其激活賬戶,通常郵件中需要有一個鏈接,這個鏈接需要具備以下的特性:能夠標識用戶,該鏈接具有時效性(通常只允許幾小時之內(nèi)激活),不能被篡改以激活其他可能的賬戶,一次性的。這種場景就適合使用JWT。

總結(jié)

到此這篇關(guān)于如何利用jwt來保護你的接口服務(wù)的文章就介紹到這了,更多相關(guān)jwt保護接口服務(wù)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • idea中@Autowired注解下變量報紅的解決

    idea中@Autowired注解下變量報紅的解決

    這篇文章主要介紹了idea中@Autowired注解下變量報紅的解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Java獲取Process子進程進程ID方法詳解

    Java獲取Process子進程進程ID方法詳解

    這篇文章主要介紹了Java獲取Process子進程進程ID方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2022-12-12
  • 劍指Offer之Java算法習(xí)題精講數(shù)組與字符串

    劍指Offer之Java算法習(xí)題精講數(shù)組與字符串

    跟著思路走,之后從簡單題入手,反復(fù)去看,做過之后可能會忘記,之后再做一次,記不住就反復(fù)做,反復(fù)尋求思路和規(guī)律,慢慢積累就會發(fā)現(xiàn)質(zhì)的變化
    2022-03-03
  • Java仿12306圖片驗證碼

    Java仿12306圖片驗證碼

    這篇文章主要為大家詳細介紹了Java仿12306的圖片驗證碼的相關(guān)資料,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-04-04
  • mybatis update更新字段的使用操作

    mybatis update更新字段的使用操作

    這篇文章主要介紹了mybatis update更新字段的使用操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • Spring boot 默認靜態(tài)資源路徑與手動配置訪問路徑的方法

    Spring boot 默認靜態(tài)資源路徑與手動配置訪問路徑的方法

    這篇文章主要介紹了Spring boot 默認靜態(tài)資源路徑與手動配置訪問路徑的方法,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2017-05-05
  • 解析ConcurrentHashMap: transfer方法源碼分析(難點)

    解析ConcurrentHashMap: transfer方法源碼分析(難點)

    ConcurrentHashMap是由Segment數(shù)組結(jié)構(gòu)和HashEntry數(shù)組結(jié)構(gòu)組成。Segment的結(jié)構(gòu)和HashMap類似,是一種數(shù)組和鏈表結(jié)構(gòu),今天給大家普及java面試常見問題---ConcurrentHashMap知識,一起看看吧
    2021-06-06
  • 詳解Java中KMP算法的圖解與實現(xiàn)

    詳解Java中KMP算法的圖解與實現(xiàn)

    KMP算法是一種神奇的字符串匹配算法,在對超長字符串進行模板匹配的時候比暴力匹配法的效率會高不少。本文將利用圖解為大家詳細講解KMP算法的實現(xiàn),需要的可以參考一下
    2022-05-05
  • Java設(shè)計模式中的原型模式講解

    Java設(shè)計模式中的原型模式講解

    原型模式是用于創(chuàng)建重復(fù)的對象,同時又能保證性能。這種類型的設(shè)計模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對象的最佳方式,今天通過本文給大家介紹下Java?原型設(shè)計模式,感興趣的朋友一起看看吧
    2023-04-04
  • 解決idea更新maven倉庫的圖文教程

    解決idea更新maven倉庫的圖文教程

    這篇文章主要介紹了解決idea更新maven倉庫的圖文教程,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01

最新評論

五家渠市| 元朗区| 古交市| 临邑县| 高台县| 昌平区| 巩留县| 游戏| 仲巴县| 澎湖县| 饶阳县| 阳高县| 芒康县| 垣曲县| 班戈县| 许昌市| 和林格尔县| 乌拉特后旗| 额敏县| 东平县| 湘西| 班戈县| 虹口区| 彩票| 衡山县| 静海县| 宣威市| 孙吴县| 绵阳市| 手机| 伊川县| 高邑县| 宜春市| 资中县| 木兰县| 华容县| 木里| 南昌县| 白水县| 宁海县| 上思县|