免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
如何用JWT實現(xiàn)無狀態(tài)登錄和鑒權(quán)


作者:賜我白日夢

cnblogs.com/ZhuChangwu/p/11345098.html

無狀態(tài)登錄原理

先提一下啥是有狀態(tài)登錄

單臺tomcat的情況下,編碼的流程如下:

  1. 前端提交表單里用戶的輸入的賬號密碼

  2. 后臺接受,查數(shù)據(jù)庫,

  3. 在數(shù)據(jù)庫中找到用戶的信息后,把用戶的信息存放到session里面,返回給用戶cookie

  4. 以后用戶的請求都會自動攜帶著cookie去訪問后臺,后臺根據(jù)用戶的cookie辨識用戶的身份

但是有缺點

  • 如果有千千萬的用戶都往session里面存放信息,

  • session很難跨服務(wù)器,也就是說,用戶每次請求,都必須訪問同一臺tomcat,新的tomcat不認(rèn)識用戶的cookie

無狀態(tài)登錄

  • 對于服務(wù)端,不再保存任何用戶的信息,對于他們來說,所有的用戶地位平等

  • 對于用戶,他們需要自己攜帶著信息去訪問服務(wù)端,攜帶的信息可以被所有服務(wù)端辨認(rèn),所以,對于用戶,所有的服務(wù)地位平等

具體如何實現(xiàn)呢?

  1. 用戶登錄,服務(wù)端返回給用戶的個人信息+token令牌

  2. 前端為了自己使用方便,將用戶的個人信息緩存進瀏覽器(因為后端只是給了他一個token)

  3. 用戶攜帶自己的token去訪問服務(wù)端

  4. 認(rèn)證通過,把用戶請求的數(shù)據(jù)返回給客戶端

  5. 以后不論用戶請求哪個微服務(wù),都攜帶著token

  6. 微服務(wù)對token進行解密,判斷他是否有效

JWT(Json Web Token)生成規(guī)則

整個登錄.授權(quán).鑒權(quán)的過程token的安全性至關(guān)重要,而JWT就是一門有關(guān)于如何生成一個不可仿造的token的規(guī)范

他是JSON風(fēng)格輕量級的授權(quán)和身份認(rèn)證規(guī)范,可實現(xiàn)無狀態(tài)、分布式的Web應(yīng)用授權(quán),而且它不是技術(shù),和語言無關(guān),java有對這個規(guī)范的實現(xiàn) 叫做 jjwt。

jjwt的github項目
https://github.com/jwtk/jjwt

由JWT算法得到的token格式如上圖,由頭部,載荷,簽名三部分組成

頭部

由兩部分組成,alg表示使用的加密算法 typ表示使用的token的類型

載荷

存放用戶相關(guān)的信息

// 下面是它已經(jīng)定義好的載荷部分key,也允許我們自定義載荷部分key
iss: jwt簽發(fā)者
sub: jwt所面向的用戶
aud: 接收jwt的一方
exp: jwt的過期時間,這個過期時間必須要大于簽發(fā)時間
nbf: 定義在什么時間之前,該jwt都是不可用的.
iat: jwt的簽發(fā)時間
jti: jwt的唯一身份標(biāo)識,主要用來作為一次性token,從而回避重放攻擊。

第三步分的簽名是由 頭+載荷+鹽 三部分加密組成

從圖可以看出,頭部和載荷被串改后,生成的編碼會發(fā)生改變,因此保證了token的安全 ,還有,載荷部分可解密,因此不要往里面放入敏感的信息(比如密碼 )

只要密鑰不泄露,別人就無法偽造任何信息

jwt的交互過程

RSA非對稱加密算算法

由美國麻 省理工 學(xué)院三 位學(xué)者 Riv est、Sh amir 及Adleman 研 究發(fā) 展出 一套 可實 際使用 的公 開金 鑰密 碼系 統(tǒng),那就是 RSA(Rivest-Shamir-Adleman)密碼系統(tǒng)

jwt(是一種非對稱加密算法) JWT不一定非要搭配RSA算法,但是擁有RSA算法公鑰私鑰的特性,會使我們的業(yè)務(wù)邏輯變的簡單,做到校驗變少

對稱加密,如AES(Advanced Encryption Standard) 高級加密標(biāo)準(zhǔn)

  • 基本原理:將明文分成N個組,然后使用密鑰對各個組進行加密,形成各自的密文,最后把所有的分組密文進行合并,形成最終的密文。

  • 優(yōu)勢:算法公開、計算量小、加密速度快、加密效率高

  • 缺陷:雙方都使用同樣密鑰,安全性得不到保證

非對稱加密,如RSA

  • 基本原理:同時生成兩把密鑰:私鑰和公鑰,私鑰隱秘保存,公鑰可以下發(fā)給信任客戶端

  • 私鑰加密,持有私鑰或公鑰才可以解密

  • 公鑰加密,持有私鑰才可解密

  • 優(yōu)點:安全,難以破解

  • 缺點:算法比較耗時

不可逆加密,如MD5,SHA

使用JJWT實現(xiàn)JWT

JJWT(java json web token)

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

創(chuàng)建jwt令牌

token最終會頒發(fā)給前端,這時候就得去和前端的哥們商量它想要什么信息

// 生成令牌,主要是用它生成載荷
JwtBuilder builder = Jwts.builder()
        // 設(shè)置頭部,使用hs256加密, + key,也就是鹽
        .signWith(SignatureAlgorithm.HS256,'changwu')
        // 添加載荷
        .setId('666') // 用戶id
        .setSubject('張三') // 用戶名
        .setExpiration(new Date(new Date().getTime()+60*1000)) // 過期時間
        .setIssuedAt(new Date())// 登錄時間
        // 添加自定義的鍵值對
        .claim('role','admin');
System.out.println(builder.compact());

經(jīng)過它處理的token長這個樣子, 三部組成

XXX.YYY.ZZZ

解析token

能成功解析出結(jié)果的前提是兩次的鹽是一樣的才行

Claims map = Jwts.parser().setSigningKey('changwu')
        .parseClaimsJws('eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI2NjYiLCJzdWIiOiLlvKDkuIkiLCJleHAiOjE1NjU2MTg1MjUsImlhdCI6MTU2NTYxODQ2NSwicm9sZSI6ImFkbWluIn0.GDVfLq-ehSnMCRoxVcziXkirjOg34SUUPBK5vAEHu80')
        .getBody();

System.out.println('用戶id' + map.getId());
System.out.println('用戶名' + map.getSubject());
System.out.println('token過期時間' + new SimpleDateFormat('yyyy-MM-dd HH:mm:ss').format(map.getExpiration()));
System.out.println('用戶登錄時間' + new SimpleDateFormat('yyyy-MM-dd HH:mm:ss').format(map.getIssuedAt()));
System.out.println('用戶的角色是:'+map.get('role'));

攔截器

注意哦,使用的是SpringMvc的攔截器,而不是Servlet的過濾器。擴展:SpringBoot實現(xiàn)過濾器、攔截器與切片

攔截器的體系架構(gòu)

在攔截器的體系中,我們常用的是上面的來兩個

HandlerInterceptor是頂級接口如下:

雖然是接口, 但是擁有jdk8的特性,是默認(rèn)的方法,所以允許我們挑選它的部分方法實現(xiàn)而不會報錯

  • prehandler: 請求到達控制器之間被回調(diào),可以在這里進行設(shè)置編碼,安全控制,權(quán)限校驗, 一般全部返回ture,表示放行

  • postHandler: 控制器處理請求之后生成了ModelAndView,但是未進行渲染,提供了修改ModelAndView的機會

  • afterCompletion: 返回給用戶ModelAndView之后執(zhí)行, 用于收尾工作

第二個是HandlerInterceptorAdapter如下圖

這個適配器方法全是空實現(xiàn),同樣可以滿足我們的需求,但是它同時實現(xiàn)了AsyncHandlerInterceptor,擁有了一個新的方法,afterConcrruentHandingStarted(request,response,handler)

這個方法會在Controller方法異步執(zhí)行時開始執(zhí)行, 而Interceptor的postHandle方法則是需要等到Controller的異步執(zhí)行完才能執(zhí)行

編碼實現(xiàn)

其實到這里改如何做已經(jīng)清晰明了

用戶登錄,授權(quán)

授權(quán)的很簡單

  1. 用戶發(fā)送登錄請求提交form表單

  2. 后端根據(jù)用戶名密碼查詢用戶的信息

  3. 把用戶的信息封裝進jwt的載荷部分

  4. 返回給前端token

用戶再次請求,鑒權(quán)

后臺會有很多方法需要指定權(quán)限的人才能訪問, 所謂鑒定權(quán)限,其實就是把前端放在請求頭中的token信息解析出來,如果解析成功了,說明用戶的合法的,否則就提示前端用戶沒有權(quán)限。擴展閱讀:前后端分離模式下的權(quán)限設(shè)計方案

把token從請求頭中解析出來的過程,其實是在大量的重復(fù)性工作,所以我們放在攔截器中實現(xiàn)

使用攔截器兩步走

第一步,繼承HandlerInterAdapter,選擇重寫它的方法

  • 設(shè)計的邏輯,這個方法肯定要返回true, 因為后臺的方法中肯定存在大量的不需要任何權(quán)限就能訪問的方法

  • 所以這個方法的作用就是,解析出請求頭中的用戶的權(quán)限信息,重新放回到request中,

  • 這樣每個需要進行權(quán)限驗證的請求,就不需要再進行解析請求頭,而是直接使用當(dāng)前回調(diào)方法的處理結(jié)果

@Component
public class RequestInterceptor extends HandlerInterceptorAdapter {

@Autowired
JwtUtil jwtUtil;

// 在請求進入處理器之前回調(diào)這個方法
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    // 獲取請求頭
String header = request.getHeader('Authorization');
// 請求頭不為空進行解析
if (StringUtils.isNotBlank(header)) {
    // 按照我們和前端約定的格式進行處理
    if (header.startsWith('Bearer ')){
        // 得到令牌
        String token = header.substring(7);
        // 驗證令牌
        try{ // 令牌的解析這里一定的try起來,因為它解析錯誤的令牌時,會報錯
            // 當(dāng)然你也可以在自定義的jwtUtil中把異常 try起來,這里就不用寫了
            Claims claims = jwtUtil.parseJWT(token);
            String roles =(String) claims.get('roles');
            System.err.println('roles=='+roles);
            if (roles!=null&&'admin'.equals(roles)){
                request.setAttribute('role_admin',token);
            }
            if (roles!=null&&'user'.equals(roles)){
                request.setAttribute('role_user',token);
            }
        }catch (Exception e){
            throw new RuntimeException('令牌不存在');
        }
    }
}
    return true;
}
}

這樣 控制器中的方法需要進行權(quán)限驗證時,就免去了解析的麻煩,直接從request中獲取即可

第二步,將攔截器注冊進容器

@Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport {

@Autowired
RequestInterceptor requestInterceptor;

// 注冊攔截器
protected void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(requestInterceptor)
            .addPathPatterns('/**')
            .excludePathPatterns('/user/login/**');
}
}

END

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
使用JWT生成token
微服務(wù)網(wǎng)關(guān)鑒權(quán):gateway使用、網(wǎng)關(guān)限流使用、用戶密碼加密、JWT鑒權(quán)
基于jwt和session用戶認(rèn)證的區(qū)別和優(yōu)缺點
一步步帶你了解前后端分離利器之JWT
Cookie和Token
Restful安全認(rèn)證及權(quán)限的解決方案
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服