日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

base64编码 springboot_Spring Boot 中如何实现 HTTP 认证?

發(fā)布時間:2025/3/19 javascript 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 base64编码 springboot_Spring Boot 中如何实现 HTTP 认证? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

松哥給最近連載的 Spring Security 系列也錄制了視頻教程,感興趣的小伙伴請戳這里->Spring Boot+Vue+微人事視頻教程(Spring Boot 第十章就是 Spring Security)。

HttpBasic 認證有一定的局限性與安全隱患,因此在實際項目中使用并不多,但是,有的時候為了測試方便,開啟 HttpBasic 認證能方便很多。

因此松哥今天還是來和大家簡單聊一聊 Spring Security 中的 HttpBasic 認證。

本文是 Spring Security 系列第 29 篇,閱讀前面文章有助于更好理解本文:

  • 挖一個大坑,Spring Security 開搞!
  • 松哥手把手帶你入門 Spring Security,別再問密碼怎么解密了
  • 手把手教你定制 Spring Security 中的表單登錄
  • Spring Security 做前后端分離,咱就別做頁面跳轉(zhuǎn)了!統(tǒng)統(tǒng) JSON 交互
  • Spring Security 中的授權操作原來這么簡單
  • Spring Security 如何將用戶數(shù)據(jù)存入數(shù)據(jù)庫?
  • Spring Security+Spring Data Jpa 強強聯(lián)手,安全管理只有更簡單!
  • Spring Boot + Spring Security 實現(xiàn)自動登錄功能
  • Spring Boot 自動登錄,安全風險要怎么控制?
  • 在微服務項目中,Spring Security 比 Shiro 強在哪?
  • SpringSecurity 自定義認證邏輯的兩種方式(高級玩法)
  • Spring Security 中如何快速查看登錄用戶 IP 地址等信息?
  • Spring Security 自動踢掉前一個登錄用戶,一個配置搞定!
  • Spring Boot + Vue 前后端分離項目,如何踢掉已登錄用戶?
  • Spring Security 自帶防火墻!你都不知道自己的系統(tǒng)有多安全!
  • 什么是會話固定攻擊?Spring Boot 中要如何防御會話固定攻擊?
  • 集群化部署,Spring Security 要如何處理 session 共享?
  • 松哥手把手教你在 SpringBoot 中防御 CSRF 攻擊!so easy!
  • 要學就學透徹!Spring Security 中 CSRF 防御源碼解析
  • Spring Boot 中密碼加密的兩種姿勢!
  • Spring Security 要怎么學?為什么一定要成體系的學習?
  • Spring Security 兩種資源放行策略,千萬別用錯了!
  • 松哥手把手教你入門 Spring Boot + CAS 單點登錄
  • Spring Boot 實現(xiàn)單點登錄的第三種方案!
  • Spring Boot+CAS 單點登錄,如何對接數(shù)據(jù)庫?
  • Spring Boot+CAS 默認登錄頁面太丑了,怎么辦?
  • 用 Swagger 測試接口,怎么在請求頭中攜帶 Token?
  • Spring Boot 中三種跨域場景總結(jié)
  • 1.什么是 HttpBasic

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

    HttpBasic 最大的優(yōu)勢在于使用非常簡單,沒有復雜的頁面交互,只需要在請求頭中攜帶相應的信息就可以認證成功,而且它是一種無狀態(tài)登錄,也就是 session 中并不會記錄用戶的登錄信息。

    HttpBasic 最大的問題在于安全性,因為用戶名/密碼只是簡單的通過 Base64 編碼之后就開始傳送了,很容易被工具嗅探到,進而暴露用戶信息。

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

    這里,松哥將和大家分享 Spring Security 中的這兩種認證方式。

    2.HttpBasic 認證

    我們先來看實現(xiàn),再來分析它的認證流程。

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

    接下來創(chuàng)建一個測試接口:

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

    再開啟 HttpBasic 認證:

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

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

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

    配置完成后,啟動項目,訪問 /hello 接口,此時瀏覽器中會有彈出框,讓我們輸入用戶名/密碼信息:

    此時我們查看請求響應頭,如下:

    可以看到,瀏覽器響應了 401,同時還攜帶了一個 WWW-Authenticate 響應頭,這個是用來描述認證形式的,如果我們使用的是 HttpBasic 認證,默認響應頭格式如圖所示。

    接下來我們輸入用戶名密碼,點擊 Sign In 進行登錄,登錄成功后,就可以成功訪問到 /hello 接口了。

    我們查看第二次的請求,如下:

    大家可以看到,在請求頭中,多了一個 Authorization 字段,該字段的值為 Basic amF2YWJveToxMjM=,

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

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

    解碼結(jié)果如下:

    可以看到,這就是我們的用戶名密碼信息。用戶名/密碼只是經(jīng)過簡單的 Base64 編碼之后就開始傳遞了,所以說,這種認證方式比較危險??。

    我們再來稍微總結(jié)一下 HttpBasic 認證的流程:

  • 瀏覽器發(fā)出請求,說要訪問 /hello 接口。
  • 服務端返回 401,表示未認證。同時在響應頭中攜帶 WWW-Authenticate 字段來描述認證形式。
  • 瀏覽器收到 401 響應之后,彈出對話框,要求用戶輸入用戶名/密碼,用戶輸入完用戶名/密碼之后,瀏覽器會將之進行 Base64 編碼,編碼完成后,發(fā)送到服務端。
  • 服務端對瀏覽器傳來的信息進行解碼,并校驗,當沒問題的時候,給客戶端作出響應。
  • 大致的流程就是這樣。

    3.Http 摘要認證

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

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

  • 瀏覽器發(fā)出請求,說要訪問 /hello 接口。
  • 服務端返回 401,表示未認證,同時在響應頭中攜帶 WWW-Authenticate 字段來描述認證形式。不同的是,這次服務端會計算出一個隨機字符串,一同返回前端,這樣可以防止重放攻擊(所謂重放攻擊就是別人嗅探到你的摘要信息,把摘要當成密碼一次次發(fā)送服務端,加一個會變化的隨機字符串,生成的摘要信息就會變化,就可以防止重放攻擊),如下:
  • 同時,服務端返回的字段還有一個 qop,表示保護級別,auth 表示只進行身份驗證;auth-int 表示還要校驗內(nèi)容。

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

  • 客戶端選擇一個算法,根據(jù)該算法計算出密碼以及其他數(shù)據(jù)的摘要,如下:
  • 可以看到,客戶端發(fā)送到服務端的數(shù)據(jù)比較多。

    • nonce 就是服務端發(fā)來的隨機字符串。
    • response 是生成的摘要信息。
    • nc 表示請求此時,可以防止重放攻擊。
    • cnonce 表示客戶端發(fā)送給服務端的隨機字符串。
  • 服務端根據(jù)客戶端發(fā)送來的用戶名,可以查詢出用戶密碼,再根據(jù)用戶密碼可以計算出摘要信息,再將摘要信息和客戶端發(fā)送來的摘要信息進行對比,就能確認用戶身份。
  • 這就是整個流程。

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

    好了,那這個在 Spring Security 代碼中該怎么實現(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();
    ????}

    }

    配置無非就是兩方面,一方面是服務端隨機字符串的生成,另一方面就是客戶端摘要信息的校驗。

  • 首先提供 DigestAuthenticationEntryPoint 的實例,配置服務端隨機數(shù)生成的一寫參數(shù),例如 nonce 有效期(多長時間會變),realm 的名字,以及生成 nonce 時所需要的 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());
    }

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

  • 配置 DigestAuthenticationFilter 過濾器,主要用來處理前端請求。過濾器的源碼比較長,我這里就不貼出來了,一個核心的思路就是從前端拿到用戶請求的摘要信息,服務端也根據(jù)一直的信息算出來一個摘要,再根據(jù)傳過來的摘要信息進行比對,進而確認用戶身份。
  • 配置完成后,重啟服務端進行測試。

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

    4.小結(jié)

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

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

    好啦,小伙伴們?nèi)绻惺斋@,記得點個在看鼓勵下松哥哦~

    今日干貨

    剛剛發(fā)表查看:66666回復:666

    公眾號后臺回復 ssm,免費獲取松哥純手敲的 SSM 框架學習干貨。

    總結(jié)

    以上是生活随笔為你收集整理的base64编码 springboot_Spring Boot 中如何实现 HTTP 认证?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。