1. <ul id="0c1fb"></ul>

      <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
      <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区

      RELATEED CONSULTING
      相關(guān)咨詢(xún)
      選擇下列產(chǎn)品馬上在線溝通
      服務(wù)時(shí)間:8:30-17:00
      你可能遇到了下面的問(wèn)題
      關(guān)閉右側(cè)工具欄

      新聞中心

      這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
      SpringBoot中如何實(shí)現(xiàn)HTTP認(rèn)證

      這篇文章將為大家詳細(xì)講解有關(guān)Spring Boot中如何實(shí)現(xiàn)HTTP認(rèn)證,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

      呼圖壁ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場(chǎng)景,ssl證書(shū)未來(lái)市場(chǎng)廣闊!成為創(chuàng)新互聯(lián)的ssl證書(shū)銷(xiāo)售渠道,可以享受市場(chǎng)價(jià)格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:13518219792(備注:SSL證書(shū)合作)期待與您的合作!

      HttpBasic 認(rèn)證有一定的局限性與安全隱患,因此在實(shí)際項(xiàng)目中使用并不多,但是,有的時(shí)候?yàn)榱藴y(cè)試方便,開(kāi)啟 HttpBasic 認(rèn)證能方便很多。

      今天還是來(lái)和大家簡(jiǎn)單聊一聊 Spring Security 中的 HttpBasic 認(rèn)證。

      1.什么是 HttpBasic

      Http Basic 認(rèn)證是 Web 服務(wù)器和客戶(hù)端之間進(jìn)行認(rèn)證的一種方式,最初是在 HTTP1.0 規(guī)范(RFC 1945)中定義,后續(xù)的有關(guān)安全的信息可以在 HTTP 1.1 規(guī)范(RFC 2616)和 HTTP 認(rèn)證規(guī)范(RFC 2617)中找到。

      HttpBasic 最大的優(yōu)勢(shì)在于使用非常簡(jiǎn)單,沒(méi)有復(fù)雜的頁(yè)面交互,只需要在請(qǐng)求頭中攜帶相應(yīng)的信息就可以認(rèn)證成功,而且它是一種無(wú)狀態(tài)登錄,也就是 session 中并不會(huì)記錄用戶(hù)的登錄信息。

      HttpBasic 最大的問(wèn)題在于安全性,因?yàn)橛脩?hù)名/密碼只是簡(jiǎn)單的通過(guò) Base64 編碼之后就開(kāi)始傳送了,很容易被工具嗅探到,進(jìn)而暴露用戶(hù)信息。

      Spring Security 中既支持基本的 HttpBasic 認(rèn)證,也支持 Http 摘要認(rèn)證,Http 摘要認(rèn)證是在 HttpBasic 認(rèn)證的基礎(chǔ)上,提高了信息安全管理,但是代碼復(fù)雜度也提高了不少,所以 Http 摘要認(rèn)證使用并不多。

      這里,和大家分享 Spring Security 中的這兩種認(rèn)證方式。

      2.HttpBasic 認(rèn)證

      我們先來(lái)看實(shí)現(xiàn),再來(lái)分析它的認(rèn)證流程。

      首先創(chuàng)建一個(gè) Spring Boot 項(xiàng)目,引入 Web 和 Spring Security 依賴(lài),如下:

      Spring Boot中如何實(shí)現(xiàn)HTTP認(rèn)證

      接下來(lái)創(chuàng)建一個(gè)測(cè)試接口:

      @RestController
      public class HelloController {
         @GetMapping("/hello")
         public String hello() {
             return "hello";
         }
      }

      再開(kāi)啟 HttpBasic 認(rèn)證:

      @Configuration
      public class SecurityConfig extends WebSecurityConfigurerAdapter {
         @Override
         protected void configure(HttpSecurity http) throws Exception {
             http.authorizeRequests()
                     .anyRequest().authenticated()
                     .and()
                     .httpBasic();
         }
      }

      最后再在 application.properties 中配置基本的用戶(hù)信息,如下:

      spring.security.user.password=123
      spring.security.user.name=javaboy

      配置完成后,啟動(dòng)項(xiàng)目,訪問(wèn) /hello 接口,此時(shí)瀏覽器中會(huì)有彈出框,讓我們輸入用戶(hù)名/密碼信息:

      Spring Boot中如何實(shí)現(xiàn)HTTP認(rèn)證

      此時(shí)我們查看請(qǐng)求響應(yīng)頭,如下:

      Spring Boot中如何實(shí)現(xiàn)HTTP認(rèn)證

      可以看到,瀏覽器響應(yīng)了 401,同時(shí)還攜帶了一個(gè) WWW-Authenticate 響應(yīng)頭,這個(gè)是用來(lái)描述認(rèn)證形式的,如果我們使用的是 HttpBasic 認(rèn)證,默認(rèn)響應(yīng)頭格式如圖所示。

      接下來(lái)我們輸入用戶(hù)名密碼,點(diǎn)擊 Sign In 進(jìn)行登錄,登錄成功后,就可以成功訪問(wèn)到 /hello 接口了。

      我們查看第二次的請(qǐng)求,如下:

      Spring Boot中如何實(shí)現(xiàn)HTTP認(rèn)證

      大家可以看到,在請(qǐng)求頭中,多了一個(gè) Authorization 字段,該字段的值為 Basic amF2YWJveToxMjM=,

      amF2YWJveToxMjM= 是一個(gè)經(jīng)過(guò) Base64 編碼之后的字符串,我們將該字符串解碼之后發(fā)現(xiàn),結(jié)果如下:

      String x = 
      new String(Base64.getDecoder().decode("amF2YWJveToxMjM="), 
      "UTF-8");

      解碼結(jié)果如下:

      Spring Boot中如何實(shí)現(xiàn)HTTP認(rèn)證

      可以看到,這就是我們的用戶(hù)名密碼信息。用戶(hù)名/密碼只是經(jīng)過(guò)簡(jiǎn)單的 Base64 編碼之后就開(kāi)始傳遞了,所以說(shuō),這種認(rèn)證方式比較危險(xiǎn)。

      我們?cè)賮?lái)稍微總結(jié)一下 HttpBasic 認(rèn)證的流程:

      1. 瀏覽器發(fā)出請(qǐng)求,說(shuō)要訪問(wèn) /hello 接口。

      2. 服務(wù)端返回 401,表示未認(rèn)證。同時(shí)在響應(yīng)頭中攜帶 WWW-Authenticate 字段來(lái)描述認(rèn)證形式。

      3. 瀏覽器收到 401 響應(yīng)之后,彈出對(duì)話框,要求用戶(hù)輸入用戶(hù)名/密碼,用戶(hù)輸入完用戶(hù)名/密碼之后,瀏覽器會(huì)將之進(jìn)行 Base64 編碼,編碼完成后,發(fā)送到服務(wù)端。

      4. 服務(wù)端對(duì)瀏覽器傳來(lái)的信息進(jìn)行解碼,并校驗(yàn),當(dāng)沒(méi)問(wèn)題的時(shí)候,給客戶(hù)端作出響應(yīng)。

      大致的流程就是這樣。

      3.Http 摘要認(rèn)證

      Http 摘要認(rèn)證與 HttpBasic 認(rèn)證基本兼容,但是要復(fù)雜很多,這個(gè)復(fù)雜不僅體現(xiàn)在代碼上,也體現(xiàn)在請(qǐng)求過(guò)程中。

      Http 摘要認(rèn)證最重要的改進(jìn)是他不會(huì)在網(wǎng)絡(luò)上發(fā)送明文密碼。它的整個(gè)認(rèn)證流程是這樣的:

      1. 瀏覽器發(fā)出請(qǐng)求,說(shuō)要訪問(wèn) /hello 接口。

      2. 服務(wù)端返回 401,表示未認(rèn)證,同時(shí)在響應(yīng)頭中攜帶 WWW-Authenticate 字段來(lái)描述認(rèn)證形式。不同的是,這次服務(wù)端會(huì)計(jì)算出一個(gè)隨機(jī)字符串,一同返回前端,這樣可以防止重放攻擊(所謂重放攻擊就是別人嗅探到你的摘要信息,把摘要當(dāng)成密碼一次次發(fā)送服務(wù)端,加一個(gè)會(huì)變化的隨機(jī)字符串,生成的摘要信息就會(huì)變化,就可以防止重放攻擊),如下:

      Spring Boot中如何實(shí)現(xiàn)HTTP認(rèn)證

      同時(shí),服務(wù)端返回的字段還有一個(gè) qop,表示保護(hù)級(jí)別,auth 表示只進(jìn)行身份驗(yàn)證;auth-int 表示還要校驗(yàn)內(nèi)容。

      nonce 是服務(wù)端生成的隨機(jī)字符串,這是一個(gè)經(jīng)過(guò) Base64 編碼的字符串,經(jīng)過(guò)解碼我們發(fā)現(xiàn),它是由過(guò)期時(shí)間和密鑰組成的。在以后的請(qǐng)求中 nonce 會(huì)原封不動(dòng)的再發(fā)回給服務(wù)端。

      1. 客戶(hù)端選擇一個(gè)算法,根據(jù)該算法計(jì)算出密碼以及其他數(shù)據(jù)的摘要,如下:

      Spring Boot中如何實(shí)現(xiàn)HTTP認(rèn)證

      可以看到,客戶(hù)端發(fā)送到服務(wù)端的數(shù)據(jù)比較多。

      • nonce 就是服務(wù)端發(fā)來(lái)的隨機(jī)字符串。

      • response 是生成的摘要信息。

      • nc 表示請(qǐng)求此時(shí),可以防止重放攻擊。

      • cnonce 表示客戶(hù)端發(fā)送給服務(wù)端的隨機(jī)字符串。

      1. 服務(wù)端根據(jù)客戶(hù)端發(fā)送來(lái)的用戶(hù)名,可以查詢(xún)出用戶(hù)密碼,再根據(jù)用戶(hù)密碼可以計(jì)算出摘要信息,再將摘要信息和客戶(hù)端發(fā)送來(lái)的摘要信息進(jìn)行對(duì)比,就能確認(rèn)用戶(hù)身份。

      這就是整個(gè)流程。

      一言以蔽之,原本的用戶(hù)密碼被摘要信息代替了,為了安全,摘要信息會(huì)根據(jù)服務(wù)端返回的隨機(jī)字符串而發(fā)生變化,服務(wù)端根據(jù)用戶(hù)密碼,同樣算出密碼的摘要信息,再和客戶(hù)端傳來(lái)的摘要信息進(jìn)行對(duì)比,沒(méi)問(wèn)題的話,用戶(hù)就算認(rèn)證成功了。當(dāng)然,在此基礎(chǔ)上還加了一些過(guò)期限制、重放攻擊防范機(jī)制等。

      好了,那這個(gè)在 Spring Security 代碼中該怎么實(shí)現(xiàn)呢?

      @Configuration
      public class SecurityConfig extends WebSecurityConfigurerAdapter {
         @Override
         protected void configure(HttpSecurity http) throws Exception {
             http.authorizeRequests()
                     .anyRequest().authenticated()
                     .and()
                     .csrf()
                     .disable()
                     .exceptionHandling()
                     .authenticationEntryPoint(digestAuthenticationEntryPoint())
                     .and()
                     .addFilter(digestAuthenticationFilter());
         }

         @Bean
         DigestAuthenticationEntryPoint digestAuthenticationEntryPoint() {
             DigestAuthenticationEntryPoint entryPoint = new DigestAuthenticationEntryPoint();
             entryPoint.setKey("javaboy");
             entryPoint.setRealmName("myrealm");
             entryPoint.setNonceValiditySeconds(1000);
             return entryPoint;
         }
         @Bean
         DigestAuthenticationFilter digestAuthenticationFilter() {
             DigestAuthenticationFilter filter = new DigestAuthenticationFilter();
             filter.setAuthenticationEntryPoint(digestAuthenticationEntryPoint());
             filter.setUserDetailsService(userDetailsService());
             return filter;
         }

         @Override
         @Bean
         protected UserDetailsService userDetailsService() {
             InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
             manager.createUser(User.withUsername("javaboy").password("123").roles("admin").build());
             return manager;
         }

         @Bean
         PasswordEncoder passwordEncoder() {
             return NoOpPasswordEncoder.getInstance();
         }

      }

      配置無(wú)非就是兩方面,一方面是服務(wù)端隨機(jī)字符串的生成,另一方面就是客戶(hù)端摘要信息的校驗(yàn)。

      1. 首先提供 DigestAuthenticationEntryPoint 的實(shí)例,配置服務(wù)端隨機(jī)數(shù)生成的一些參數(shù),例如 nonce 有效期(多長(zhǎng)時(shí)間會(huì)變),realm 的名字,以及生成 nonce 時(shí)所需要的 key。nonce 的具體生成邏輯在 DigestAuthenticationEntryPoint#commence 方法中:

      public void commence(HttpServletRequest request, HttpServletResponse response,
      AuthenticationException authException) throws IOException {
      HttpServletResponse httpResponse = response;
      long expiryTime = System.currentTimeMillis() + (nonceValiditySeconds * 1000);
      String signatureValue = DigestAuthUtils.md5Hex(expiryTime + ":" + key);
      String nonceValue = expiryTime + ":" + signatureValue;
      String nonceValueBase64 = new String(Base64.getEncoder().encode(nonceValue.getBytes()));
      String authenticateHeader = "Digest realm=\"" + realmName + "\", "
      + "qop=\"auth\", nonce=\"" + nonceValueBase64 + "\"";
      if (authException instanceof NonceExpiredException) {
      authenticateHeader = authenticateHeader + ", stale=\"true\"";
      }
      if (logger.isDebugEnabled()) {
      logger.debug("WWW-Authenticate header sent to user agent: "
      + authenticateHeader);
      }
      httpResponse.addHeader("WWW-Authenticate", authenticateHeader);
      httpResponse.sendError(HttpStatus.UNAUTHORIZED.value(),
      HttpStatus.UNAUTHORIZED.getReasonPhrase());
      }

      在這段代碼中,首先獲取到過(guò)期時(shí)間,然后給過(guò)期時(shí)間和 key 一起計(jì)算出消息摘要,再將 nonce 和消息摘要共同作為 value,計(jì)算出一個(gè) Base64 編碼字符,再將該編碼字符寫(xiě)回到前端。

      1. 配置 DigestAuthenticationFilter 過(guò)濾器,主要用來(lái)處理前端請(qǐng)求。過(guò)濾器的源碼比較長(zhǎng),我這里就不貼出來(lái)了,一個(gè)核心的思路就是從前端拿到用戶(hù)請(qǐng)求的摘要信息,服務(wù)端也根據(jù)一直的信息算出來(lái)一個(gè)摘要,再根據(jù)傳過(guò)來(lái)的摘要信息進(jìn)行比對(duì),進(jìn)而確認(rèn)用戶(hù)身份。

      配置完成后,重啟服務(wù)端進(jìn)行測(cè)試。

      測(cè)試效果其實(shí)和 HttpBasic 認(rèn)證是一樣的,所有的變化,只是背后的實(shí)現(xiàn)有所變化而已,用戶(hù)體驗(yàn)是一樣的。

      4.小結(jié)

      Http 摘要認(rèn)證的效果雖然比 HttpBasic 安全,但是其實(shí)大家看到,整個(gè)流程下來(lái)解決的安全問(wèn)題其實(shí)還是非常有限。而且代碼也麻煩了很多,因此這種認(rèn)證方式并未廣泛流行開(kāi)來(lái)。

      Http 認(rèn)證小伙伴們作為一個(gè)了解即可,里邊的有一些思想還是挺有意思的,可以激發(fā)我們解決其他問(wèn)題的思路,例如對(duì)于重放攻擊的的解決辦法,我們?nèi)绻胱约悍烙胤殴?,就可以參考這里的實(shí)現(xiàn)思路。

      關(guān)于Spring Boot中如何實(shí)現(xiàn)HTTP認(rèn)證就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到。


      網(wǎng)站名稱(chēng):SpringBoot中如何實(shí)現(xiàn)HTTP認(rèn)證
      網(wǎng)站鏈接:http://ef60e0e.cn/article/jdojoo.html
      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区
      1. <ul id="0c1fb"></ul>

        <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
        <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

        清远市| 肇东市| 衡山县| 松桃| 铁岭县| 凤山县| 双峰县| 三原县| 喀喇沁旗| 海淀区| 大邑县| 长岭县| 都昌县| 北辰区| 武鸣县| 泰安市| 饶阳县| 资兴市| 营山县| 垣曲县| 弋阳县| 明溪县| 江口县| 韶山市| 沭阳县| 吉林省| 饶河县| 内黄县| 海原县| 长岛县| 水城县| 济源市| 霞浦县| 乐亭县| 鄂伦春自治旗| 策勒县| 太康县| 闽侯县| 凤台县| 海南省| 江北区|