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

詳解SpringCloud服務(wù)認(rèn)證(JWT)

 更新時(shí)間:2018年01月27日 16:58:34   作者:唐亞峰  
本篇文章主要介紹了SpringCloud服務(wù)認(rèn)證(JWT),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

 - JWT

JWT(JSON Web Token), 是為了在網(wǎng)絡(luò)應(yīng)用環(huán)境間傳遞聲明而執(zhí)行的一種基于JSON的開(kāi)放標(biāo)準(zhǔn)((RFC 7519).該token被設(shè)計(jì)為緊湊且安全的,特別適用于分布式站點(diǎn)的單點(diǎn)登錄(SSO)場(chǎng)景。JWT的聲明一般被用來(lái)在身份提供者和服務(wù)提供者間傳遞被認(rèn)證的用戶身份信息,以便于從資源服務(wù)器獲取資源,也可以增加一些額外的其它業(yè)務(wù)邏輯所必須的聲明信息,該token也可直接被用于認(rèn)證,也可被加密。

- JWT與其它的區(qū)別

通常情況下,把API直接暴露出去是風(fēng)險(xiǎn)很大的,不說(shuō)別的,直接被機(jī)器攻擊就喝一壺的。那么一般來(lái)說(shuō),對(duì)API要?jiǎng)澐殖鲆欢ǖ臋?quán)限級(jí)別,然后做一個(gè)用戶的鑒權(quán),依據(jù)鑒權(quán)結(jié)果給予用戶開(kāi)放對(duì)應(yīng)的API。目前,比較主流的方案有幾種:

OAuth

OAuth(開(kāi)放授權(quán))是一個(gè)開(kāi)放的授權(quán)標(biāo)準(zhǔn),允許用戶讓第三方應(yīng)用訪問(wèn)該用戶在某一服務(wù)上存儲(chǔ)的私密的資源(如照片,視頻),而無(wú)需將用戶名和密碼提供給第三方應(yīng)用。

OAuth 允許用戶提供一個(gè)令牌,而不是用戶名和密碼來(lái)訪問(wèn)他們存放在特定服務(wù)提供者的數(shù)據(jù)。每一個(gè)令牌授權(quán)一個(gè)特定的第三方系統(tǒng)(例如,視頻編輯網(wǎng)站)在特定的時(shí)段(例如,接下來(lái)的2小時(shí)內(nèi))內(nèi)訪問(wèn)特定的資源(例如僅僅是某一相冊(cè)中的視頻)。這樣,OAuth讓用戶可以授權(quán)第三方網(wǎng)站訪問(wèn)他們存儲(chǔ)在另外服務(wù)提供者的某些特定信息,而非所有內(nèi)容

Cookie/Session Auth

Cookie認(rèn)證機(jī)制就是為一次請(qǐng)求認(rèn)證在服務(wù)端創(chuàng)建一個(gè)Session對(duì)象,同時(shí)在客戶端的瀏覽器端創(chuàng)建了一個(gè)Cookie對(duì)象;通過(guò)客戶端帶上來(lái)Cookie對(duì)象來(lái)與服務(wù)器端的session對(duì)象匹配來(lái)實(shí)現(xiàn)狀態(tài)管理的。默認(rèn)的,當(dāng)我們關(guān)閉瀏覽器的時(shí)候,cookie會(huì)被刪除。但可以通過(guò)修改cookie 的expire time使cookie在一定時(shí)間內(nèi)有效,基于session方式認(rèn)證勢(shì)必會(huì)對(duì)服務(wù)器造成一定的壓力(內(nèi)存存儲(chǔ)),不易于擴(kuò)展(需要處理分布式session),跨站請(qǐng)求偽造的攻擊(CSRF)

- JWT的優(yōu)點(diǎn)

1.相比于session,它無(wú)需保存在服務(wù)器,不占用服務(wù)器內(nèi)存開(kāi)銷(xiāo)。

2.無(wú)狀態(tài)、可拓展性強(qiáng):比如有3臺(tái)機(jī)器(A、B、C)組成服務(wù)器集群,若session存在機(jī)器A上,session只能保存在其中一臺(tái)服務(wù)器,此時(shí)你便不能訪問(wèn)機(jī)器B、C,因?yàn)锽、C上沒(méi)有存放該Session,而使用token就能夠驗(yàn)證用戶請(qǐng)求合法性,并且我再加幾臺(tái)機(jī)器也沒(méi)事,所以可拓展性好就是這個(gè)意思。

3.前后端分離,支持跨域訪問(wèn)。

- JWT的組成

{ "iss": "JWT Builder", 
 "iat": 1416797419, 
 "exp": 1448333419, 
 "aud": "www.battcn.com", 
 "sub": "1837307557@qq.com", 
 "GivenName": "Levin", 
 "Surname": "Levin", 
 "Email": "1837307557@qq.com", 
 "Role": [ "ADMIN", "MEMBER" ] 
}
  1.  iss: 該JWT的簽發(fā)者,是否使用是可選的;
  2. sub: 該JWT所面向的用戶,是否使用是可選的;
  3. aud: 接收該JWT的一方,是否使用是可選的;
  4. exp(expires): 什么時(shí)候過(guò)期,這里是一個(gè)Unix時(shí)間戳,是否使用是可選的;
  5. iat(issued at): 在什么時(shí)候簽發(fā)的(UNIX時(shí)間),是否使用是可選的;
  6. nbf (Not Before):如果當(dāng)前時(shí)間在nbf里的時(shí)間之前,則Token不被接受;一般都會(huì)留一些余地,比如幾分鐘;,是否使用是可選的;

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

JWT Token生成器:https://jwt.io/

- 認(rèn)證

- 登陸認(rèn)證

  1. 客戶端發(fā)送 POST 請(qǐng)求到服務(wù)器,提交登錄處理的Controller層
  2. 調(diào)用認(rèn)證服務(wù)進(jìn)行用戶名密碼認(rèn)證,如果認(rèn)證通過(guò),返回完整的用戶信息及對(duì)應(yīng)權(quán)限信息
  3. 利用 JJWT 對(duì)用戶、權(quán)限信息、秘鑰構(gòu)建Token
  4. 返回構(gòu)建好的Token

- 請(qǐng)求認(rèn)證

  1. 客戶端向服務(wù)器請(qǐng)求,服務(wù)端讀取請(qǐng)求頭信息(request.header)獲取Token
  2. 如果找到Token信息,則根據(jù)配置文件中的簽名加密秘鑰,調(diào)用JJWT Lib對(duì)Token信息進(jìn)行解密和解碼;
  3. 完成解碼并驗(yàn)證簽名通過(guò)后,對(duì)Token中的exp、nbf、aud等信息進(jìn)行驗(yàn)證;
  4. 全部通過(guò)后,根據(jù)獲取的用戶的角色權(quán)限信息,進(jìn)行對(duì)請(qǐng)求的資源的權(quán)限邏輯判斷;
  5. 如果權(quán)限邏輯判斷通過(guò)則通過(guò)Response對(duì)象返回;否則則返回HTTP 401;

無(wú)效Token

有效Token

- JWT的缺點(diǎn)

有優(yōu)點(diǎn)就會(huì)有缺點(diǎn),是否適用應(yīng)該考慮清楚,而不是技術(shù)跟風(fēng)

  1. token過(guò)大容易占用更多的空間
  2. token中不應(yīng)該存儲(chǔ)敏感信息
  3. JWT不是 session ,勿將token當(dāng)session
  4. 無(wú)法作廢已頒布的令牌,因?yàn)樗械恼J(rèn)證信息都在JWT中,由于在服務(wù)端沒(méi)有狀態(tài),即使你知道了某個(gè)JWT被盜取了,你也沒(méi)有辦法將其作廢。在JWT過(guò)期之前(你絕對(duì)應(yīng)該設(shè)置過(guò)期時(shí)間),你無(wú)能為力。
  5. 類(lèi)似緩存,由于無(wú)法作廢已頒布的令牌,在其過(guò)期前,你只能忍受”過(guò)期”的數(shù)據(jù)(自己放出去的token,含著淚也要用到底)。

- 代碼(片段)

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

@Configuration
@ConfigurationProperties(prefix = "battcn.security.token")
public class TokenProperties {
 /**
 * {@link com.battcn.security.model.token.Token} token的過(guò)期時(shí)間
 */
 private Integer expirationTime;

 /**
 * 發(fā)行人
 */
 private String issuer;

 /**
 * 使用的簽名KEY {@link com.battcn.security.model.token.Token}.
 */
 private String signingKey;

 /**
 * {@link com.battcn.security.model.token.Token} 刷新過(guò)期時(shí)間
 */
 private Integer refreshExpTime;

 // get set ...
}

Token生成的類(lèi)

@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過(guò)期時(shí)間,秘鑰,可自行擴(kuò)展

battcn:
 security:
 token:
 expiration-time: 10 # 分鐘 1440
 refresh-exp-time: 30 # 分鐘 2880
 issuer: http://blog.battcn.com
 signing-key: battcn

WebSecurityConfig 是 Spring Security 關(guān)鍵配置,在Securrty中基本上可以通過(guò)定義過(guò)濾器去實(shí)現(xiàn)我們想要的功能.

@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() // 因?yàn)槭褂玫氖荍WT,因此這里可以關(guān)閉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);
 }
}

- 說(shuō)點(diǎn)什么

由于JWT代碼做了簡(jiǎn)單封裝,包含內(nèi)容較多,所以文章里只貼主要片段,需要完整代碼可以直接從下面GIT獲取

本章代碼(battcn-jwt-service):http://xiazai.jb51.net/201801/yuanma/battcn-cloud_jb51.rar

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 聊聊java多線程創(chuàng)建方式及線程安全問(wèn)題

    聊聊java多線程創(chuàng)建方式及線程安全問(wèn)題

    線程被稱(chēng)為輕量級(jí)進(jìn)程,是程序執(zhí)行的最小單位,它是指在程序執(zhí)行過(guò)程中,能夠執(zhí)行代碼的一個(gè)執(zhí)行單位。接下來(lái)通過(guò)本文給大家介紹java多線程創(chuàng)建方式及線程安全問(wèn)題,感興趣的朋友一起看看吧
    2022-01-01
  • idea實(shí)現(xiàn)類(lèi)快捷生成接口方法示例

    idea實(shí)現(xiàn)類(lèi)快捷生成接口方法示例

    這篇文章主要介紹了idea實(shí)現(xiàn)類(lèi)快捷生成接口方法示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • IDEA設(shè)置Tab選項(xiàng)卡快速的操作

    IDEA設(shè)置Tab選項(xiàng)卡快速的操作

    這篇文章主要介紹了IDEA設(shè)置Tab選項(xiàng)卡快速的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-02-02
  • MyBatis分頁(yè)的四種方式

    MyBatis分頁(yè)的四種方式

    分頁(yè)查詢(xún)是非常常見(jiàn)的需求,本文主要介紹了MyBatis分頁(yè)的四種方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-08-08
  • jdk21下載、安裝詳細(xì)教程(Windows、Linux、macOS)

    jdk21下載、安裝詳細(xì)教程(Windows、Linux、macOS)

    本文介紹了OpenJDK 21的下載地址和安裝步驟,包括Windows、Linux和macOS平臺(tái),下載后解壓并設(shè)置環(huán)境變量,最后驗(yàn)證安裝,感興趣的朋友一起看看吧
    2025-03-03
  • Java Web基于Session的登錄實(shí)現(xiàn)方法

    Java Web基于Session的登錄實(shí)現(xiàn)方法

    這篇文章主要介紹了Java Web基于Session的登錄實(shí)現(xiàn)方法,涉及Java針對(duì)session的操作及表單提交與驗(yàn)證技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-10-10
  • maven搭建spring項(xiàng)目(圖文教程)

    maven搭建spring項(xiàng)目(圖文教程)

    下面小編就為大家?guī)?lái)一篇maven搭建spring項(xiàng)目(圖文教程)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-06-06
  • Java 多線程使用要點(diǎn)分析

    Java 多線程使用要點(diǎn)分析

    這篇文章主要介紹了Java 多線程使用要點(diǎn)分析的相關(guān)資料,Java 多線程開(kāi)發(fā)需要主要的細(xì)節(jié)問(wèn)題很多,這里就說(shuō)下,需要的朋友可以參考下
    2016-12-12
  • springboot實(shí)現(xiàn)發(fā)送短信驗(yàn)證碼的示例代碼

    springboot實(shí)現(xiàn)發(fā)送短信驗(yàn)證碼的示例代碼

    項(xiàng)目里面有用到用戶手機(jī)號(hào)注冊(cè)發(fā)短信功能,本文主要介紹了springboot實(shí)現(xiàn)發(fā)送短信驗(yàn)證碼的示例代碼,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-09-09
  • SpringCloud開(kāi)啟session共享并存儲(chǔ)到Redis的實(shí)現(xiàn)

    SpringCloud開(kāi)啟session共享并存儲(chǔ)到Redis的實(shí)現(xiàn)

    這篇文章主要介紹了SpringCloud開(kāi)啟session共享并存儲(chǔ)到Redis的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02

最新評(píng)論

斗六市| 乐山市| 琼结县| 蛟河市| 商洛市| 安丘市| 定日县| 昭平县| 肇州县| 康乐县| 舞钢市| 扬州市| 那坡县| 芷江| 湟中县| 仙居县| 东兴市| 武安市| 莲花县| 宜良县| 屏山县| 台南市| 鄂尔多斯市| 福海县| 宁晋县| 若羌县| 綦江县| 韶山市| 江津市| 搜索| 河北区| 乳山市| 江都市| 安宁市| 房产| 扎囊县| 神木县| 宿州市| 吐鲁番市| 舒兰市| 莲花县|