一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|JavaScript|易語言|

服務器之家 - 編程語言 - JAVA教程 - 詳解SpringCloud服務認證(JWT)

詳解SpringCloud服務認證(JWT)

2021-03-27 14:16唐亞峰 JAVA教程

本篇文章主要介紹了SpringCloud服務認證(JWT),小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

 - jwt

 

jwt(json web token), 是為了在網絡應用環境間傳遞聲明而執行的一種基于json的開放標準((rfc 7519).該token被設計為緊湊且安全的,特別適用于分布式站點的單點登錄(sso)場景。jwt的聲明一般被用來在身份提供者和服務提供者間傳遞被認證的用戶身份信息,以便于從資源服務器獲取資源,也可以增加一些額外的其它業務邏輯所必須的聲明信息,該token也可直接被用于認證,也可被加密。

- jwt與其它的區別

 

通常情況下,把api直接暴露出去是風險很大的,不說別的,直接被機器攻擊就喝一壺的。那么一般來說,對api要劃分出一定的權限級別,然后做一個用戶的鑒權,依據鑒權結果給予用戶開放對應的api。目前,比較主流的方案有幾種:

oauth

oauth(開放授權)是一個開放的授權標準,允許用戶讓第三方應用訪問該用戶在某一服務上存儲的私密的資源(如照片,視頻),而無需將用戶名和密碼提供給第三方應用。

oauth 允許用戶提供一個令牌,而不是用戶名和密碼來訪問他們存放在特定服務提供者的數據。每一個令牌授權一個特定的第三方系統(例如,視頻編輯網站)在特定的時段(例如,接下來的2小時內)內訪問特定的資源(例如僅僅是某一相冊中的視頻)。這樣,oauth讓用戶可以授權第三方網站訪問他們存儲在另外服務提供者的某些特定信息,而非所有內容

cookie/session auth

cookie認證機制就是為一次請求認證在服務端創建一個session對象,同時在客戶端的瀏覽器端創建了一個cookie對象;通過客戶端帶上來cookie對象來與服務器端的session對象匹配來實現狀態管理的。默認的,當我們關閉瀏覽器的時候,cookie會被刪除。但可以通過修改cookie 的expire time使cookie在一定時間內有效,基于session方式認證勢必會對服務器造成一定的壓力(內存存儲),不易于擴展(需要處理分布式session),跨站請求偽造的攻擊(csrf)

- jwt的優點

 

1.相比于session,它無需保存在服務器,不占用服務器內存開銷。

2.無狀態、可拓展性強:比如有3臺機器(a、b、c)組成服務器集群,若session存在機器a上,session只能保存在其中一臺服務器,此時你便不能訪問機器b、c,因為b、c上沒有存放該session,而使用token就能夠驗證用戶請求合法性,并且我再加幾臺機器也沒事,所以可拓展性好就是這個意思。

3.前后端分離,支持跨域訪問。

- jwt的組成

?
1
2
3
4
5
6
7
8
9
10
{ "iss": "jwt builder",
 "iat": 1416797419,
 "exp": 1448333419,
 "aud": "www.battcn.com",
 "sub": "[email protected]",
 "givenname": "levin",
 "surname": "levin",
 "email": "[email protected]",
 "role": [ "admin", "member" ]
}
  1.  iss: 該jwt的簽發者,是否使用是可選的;
  2. sub: 該jwt所面向的用戶,是否使用是可選的;
  3. aud: 接收該jwt的一方,是否使用是可選的;
  4. exp(expires): 什么時候過期,這里是一個unix時間戳,是否使用是可選的;
  5. iat(issued at): 在什么時候簽發的(unix時間),是否使用是可選的;
  6. nbf (not before):如果當前時間在nbf里的時間之前,則token不被接受;一般都會留一些余地,比如幾分鐘;,是否使用是可選的;

詳解SpringCloud服務認證(JWT)

一個jwt實際上就是一個字符串,它由三部分組成,頭部、載荷、簽名(上圖依次排序)

jwt token生成器:

- 認證

 

詳解SpringCloud服務認證(JWT)

- 登陸認證

  1. 客戶端發送 post 請求到服務器,提交登錄處理的controller層
  2. 調用認證服務進行用戶名密碼認證,如果認證通過,返回完整的用戶信息及對應權限信息
  3. 利用 jjwt 對用戶、權限信息、秘鑰構建token
  4. 返回構建好的token

詳解SpringCloud服務認證(JWT)

- 請求認證

  1. 客戶端向服務器請求,服務端讀取請求頭信息(request.header)獲取token
  2. 如果找到token信息,則根據配置文件中的簽名加密秘鑰,調用jjwt lib對token信息進行解密和解碼;
  3. 完成解碼并驗證簽名通過后,對token中的exp、nbf、aud等信息進行驗證;
  4. 全部通過后,根據獲取的用戶的角色權限信息,進行對請求的資源的權限邏輯判斷;
  5. 如果權限邏輯判斷通過則通過response對象返回;否則則返回http 401;

無效token

詳解SpringCloud服務認證(JWT)

有效token

詳解SpringCloud服務認證(JWT)

- jwt的缺點

 

有優點就會有缺點,是否適用應該考慮清楚,而不是技術跟風

  1. token過大容易占用更多的空間
  2. token中不應該存儲敏感信息
  3. jwt不是 session ,勿將token當session
  4. 無法作廢已頒布的令牌,因為所有的認證信息都在jwt中,由于在服務端沒有狀態,即使你知道了某個jwt被盜取了,你也沒有辦法將其作廢。在jwt過期之前(你絕對應該設置過期時間),你無能為力。
  5. 類似緩存,由于無法作廢已頒布的令牌,在其過期前,你只能忍受”過期”的數據(自己放出去的token,含著淚也要用到底)。

- 代碼(片段)

 

tokenproperties 與 application.yml資源的key映射,方便使用

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@configuration
@configurationproperties(prefix = "battcn.security.token")
public class tokenproperties {
 /**
 * {@link com.battcn.security.model.token.token} token的過期時間
 */
 private integer expirationtime;
 
 /**
 * 發行人
 */
 private string issuer;
 
 /**
 * 使用的簽名key {@link com.battcn.security.model.token.token}.
 */
 private string signingkey;
 
 /**
 * {@link com.battcn.security.model.token.token} 刷新過期時間
 */
 private integer refreshexptime;
 
 // get set ...
}

token生成的類

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
@component
public class tokenfactory {
 
 private final tokenproperties properties;
 
 @autowired
 public tokenfactory(tokenproperties properties) {
 this.properties = properties;
 }
 
 /**
 * 利用jjwt 生成 token
 * @param context
 * @return
 */
 public accesstoken createaccesstoken(usercontext context) {
 optional.ofnullable(context.getusername()).orelsethrow(()-> new illegalargumentexception("cannot create token without username"));
 optional.ofnullable(context.getauthorities()).orelsethrow(()-> new illegalargumentexception("user doesn't have any privileges"));
 claims claims = jwts.claims().setsubject(context.getusername());
 claims.put("scopes", context.getauthorities().stream().map(object::tostring).collect(tolist()));
 localdatetime currenttime = localdatetime.now();
 string token = jwts.builder()
  .setclaims(claims)
  .setissuer(properties.getissuer())
  .setissuedat(date.from(currenttime.atzone(zoneid.systemdefault()).toinstant()))
  .setexpiration(date.from(currenttime
  .plusminutes(properties.getexpirationtime())
  .atzone(zoneid.systemdefault()).toinstant()))
  .signwith(signaturealgorithm.hs512, properties.getsigningkey())
 .compact();
 return new accesstoken(token, claims);
 }
 
 /**
 * 生成 刷新 refreshtoken
 * @param usercontext
 * @return
 */
 public token createrefreshtoken(usercontext usercontext) {
 if (stringutils.isblank(usercontext.getusername())) {
  throw new illegalargumentexception("cannot create token without username");
 }
 localdatetime currenttime = localdatetime.now();
 claims claims = jwts.claims().setsubject(usercontext.getusername());
 claims.put("scopes", arrays.aslist(scopes.refresh_token.authority()));
 string token = jwts.builder()
  .setclaims(claims)
  .setissuer(properties.getissuer())
  .setid(uuid.randomuuid().tostring())
  .setissuedat(date.from(currenttime.atzone(zoneid.systemdefault()).toinstant()))
  .setexpiration(date.from(currenttime
  .plusminutes(properties.getrefreshexptime())
  .atzone(zoneid.systemdefault()).toinstant()))
  .signwith(signaturealgorithm.hs512, properties.getsigningkey())
 .compact();
 
 return new accesstoken(token, claims);
 }
}

配置文件,含token過期時間,秘鑰,可自行擴展

?
1
2
3
4
5
6
7
battcn:
 security:
 token:
 expiration-time: 10 # 分鐘 1440
 refresh-exp-time: 30 # 分鐘 2880
 issuer: http://blog.battcn.com
 signing-key: battcn

websecurityconfig 是 spring security 關鍵配置,在securrty中基本上可以通過定義過濾器去實現我們想要的功能.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
@configuration
@enablewebsecurity
public class websecurityconfig extends websecurityconfigureradapter {
 
 public static final string token_header_param = "x-authorization";
 public static final string form_based_login_entry_point = "/api/auth/login";
 public static final string token_based_auth_entry_point = "/api/**";
 public static final string manage_token_based_auth_entry_point = "/manage/**";
 public static final string token_refresh_entry_point = "/api/auth/token";
 
 @autowired private restauthenticationentrypoint authenticationentrypoint;
 @autowired private authenticationsuccesshandler successhandler;
 @autowired private authenticationfailurehandler failurehandler;
 @autowired private loginauthenticationprovider loginauthenticationprovider;
 @autowired private tokenauthenticationprovider tokenauthenticationprovider;
 
 @autowired private tokenextractor tokenextractor;
 
 @autowired private authenticationmanager authenticationmanager;
 
 protected loginprocessingfilter buildloginprocessingfilter() throws exception {
 loginprocessingfilter filter = new loginprocessingfilter(form_based_login_entry_point, successhandler, failurehandler);
 filter.setauthenticationmanager(this.authenticationmanager);
 return filter;
 }
 
 protected tokenauthenticationprocessingfilter buildtokenauthenticationprocessingfilter() throws exception {
 list<string> list = lists.newarraylist(token_based_auth_entry_point,manage_token_based_auth_entry_point);
 skippathrequestmatcher matcher = new skippathrequestmatcher(list);
 tokenauthenticationprocessingfilter filter = new tokenauthenticationprocessingfilter(failurehandler, tokenextractor, matcher);
 filter.setauthenticationmanager(this.authenticationmanager);
 return filter;
 }
 
 @bean
 @override
 public authenticationmanager authenticationmanagerbean() throws exception {
 return super.authenticationmanagerbean();
 }
 
 @override
 protected void configure(authenticationmanagerbuilder auth) {
 auth.authenticationprovider(loginauthenticationprovider);
 auth.authenticationprovider(tokenauthenticationprovider);
 }
 
 @override
 protected void configure(httpsecurity http) throws exception {
 http
 .csrf().disable() // 因為使用的是jwt,因此這里可以關閉csrf了
 .exceptionhandling()
 .authenticationentrypoint(this.authenticationentrypoint)
 .and()
  .sessionmanagement()
  .sessioncreationpolicy(sessioncreationpolicy.stateless)
 .and()
  .authorizerequests()
  .antmatchers(form_based_login_entry_point).permitall() // login end-point
  .antmatchers(token_refresh_entry_point).permitall() // token refresh end-point
 .and()
  .authorizerequests()
  .antmatchers(token_based_auth_entry_point).authenticated() // protected api end-points
  .antmatchers(manage_token_based_auth_entry_point).hasanyrole(roleenum.admin.name())
 .and()
  .addfilterbefore(buildloginprocessingfilter(), usernamepasswordauthenticationfilter.class)
  .addfilterbefore(buildtokenauthenticationprocessingfilter(), usernamepasswordauthenticationfilter.class);
 }
}

- 說點什么

 

由于jwt代碼做了簡單封裝,包含內容較多,所以文章里只貼主要片段,需要完整代碼可以直接從下面git獲取

本章代碼(battcn-jwt-service):battcn-cloud.rar

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:http://blog.csdn.net/memmsc/article/details/78122931

延伸 · 閱讀

精彩推薦
  • JAVA教程基于spring boot 的配置參考大全(推薦)

    基于spring boot 的配置參考大全(推薦)

    下面小編就為大家帶來一篇基于spring boot 的配置參考大全(推薦)。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧...

    Think-0079892020-12-26
  • JAVA教程log4j2日志異步打印(實例講解)

    log4j2日志異步打印(實例講解)

    下面小編就為大家帶來一篇log4j2日志異步打印(實例講解)。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧...

    wunan23的日志5232021-01-23
  • JAVA教程淺談Java三大框架與應用

    淺談Java三大框架與應用

    這篇文章主要介紹了淺談Java三大框架與應用,需要的朋友可以參考下 ...

    mdxy-dxy3722019-12-17
  • JAVA教程java web個人通訊錄系統設計

    java web個人通訊錄系統設計

    這篇文章主要為大家詳細介紹了java web個人通訊錄系統設計,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下 ...

    kang_ya_ping3092020-07-30
  • JAVA教程JDBC用法小結

    JDBC用法小結

    這篇文章主要介紹了JDBC用法,較為詳細的分析了基于JDBC進行數據庫操作的技巧,具有一定參考借鑒價值,需要的朋友可以參考下 ...

    shichen20143532019-12-07
  • JAVA教程java 二分法算法的實例

    java 二分法算法的實例

    這篇文章主要介紹了java 二分法算法的實例的相關資料,希望通過本文大家能夠掌握二分法,需要的朋友可以參考下...

    wely1962020-12-24
  • JAVA教程Java上傳視頻實例代碼

    Java上傳視頻實例代碼

    本文通過實例代碼給大家講解了java上傳視頻功能,代碼分為頁面前臺和后臺,工具類,具體實例代碼大家通過本文學習吧...

    smart_hwt9142021-03-17
  • JAVA教程詳解Java中ByteArray字節數組的輸入輸出流的用法

    詳解Java中ByteArray字節數組的輸入輸出流的用法

    ByteArrayInputStream和ByteArrayOutputStream分別集成自InputStream和OutputStream這兩個輸入和輸出流,這里我們就來詳解Java中ByteArray字節數組的輸入輸出流的用法,需要的朋...

    skywang4582020-05-18
主站蜘蛛池模板: 久久综合久综合久久鬼色 | 青青操在线 | 日本不卡高清免费v日本 | 羞羞漫画免费漫画页面在线看漫画秋蝉 | 亚洲欧美久久久久久久久久爽网站 | 秋霞在线一级 | 成人在线免费播放 | 美女和男人差差 | a黄毛片| 国产一区二区在线免费观看 | 久久精品热在线观看30 | 国产chinese男男gaygay | 亚洲精品免费在线观看 | 日本中文字幕一区二区有码在线 | 狠狠操社区 | 亚洲国产99在线精品一区二区 | 日本xxxx在线视频免费 | 成人在线一区二区 | 楚乔传第二部免费观看全集完整版 | 久草热8精品视频在线观看 久草草在线视视频 | 狠狠插综合网 | 亚洲高清视频在线 | 色yeye在线观视频 | 国语自产自拍秒拍在线视频 | 201天天爱天天做 | 国产精品 视频一区 二区三区 | 午夜性色一区二区三区不卡视频 | 青草久久伊人 | 欧美视频在线一区二区三区 | 私人家庭影院5577 | 亚洲成综合 | 午夜久久免影院欧洲 | 精品一区二区视频 | 欧美色图日韩色图 | 高人先生免费观看全集 | 国产三级跑| 色综合天天综合网国产人 | 亚洲国产精品久久网午夜小说 | 帅老头恋帅老头同性tv | 亚洲精品高清中文字幕完整版 | 日本亚欧乱色视频在线观看 |