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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > javascript >内容正文

javascript

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

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

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

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)證。

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

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

    Http Basic 認(rèn)證是 Web 服務(wù)器和客戶端之間進(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ì)記錄用戶的登錄信息。

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

    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),如下:

    接下來(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 中配置基本的用戶信息,如下:

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

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

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

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

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

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

    大家可以看到,在請(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é)果如下:

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

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

  • 瀏覽器發(fā)出請(qǐng)求,說(shuō)要訪問(wèn) /hello 接口。
  • 服務(wù)端返回 401,表示未認(rèn)證。同時(shí)在響應(yīng)頭中攜帶 WWW-Authenticate 字段來(lái)描述認(rèn)證形式。
  • 瀏覽器收到 401 響應(yīng)之后,彈出對(duì)話框,要求用戶輸入用戶名/密碼,用戶輸入完用戶名/密碼之后,瀏覽器會(huì)將之進(jìn)行 Base64 編碼,編碼完成后,發(fā)送到服務(wù)端。
  • 服務(wù)端對(duì)瀏覽器傳來(lái)的信息進(jìn)行解碼,并校驗(yàn),當(dāng)沒(méi)問(wèn)題的時(shí)候,給客戶端作出響應(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)證流程是這樣的:

  • 瀏覽器發(fā)出請(qǐng)求,說(shuō)要訪問(wèn) /hello 接口。
  • 服務(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ì)變化,就可以防止重放攻擊),如下:
  • 同時(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ù)端。

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

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

    一言以蔽之,原本的用戶密碼被摘要信息代替了,為了安全,摘要信息會(huì)根據(jù)服務(wù)端返回的隨機(jī)字符串而發(fā)生變化,服務(wù)端根據(jù)用戶密碼,同樣算出密碼的摘要信息,再和客戶端傳來(lái)的摘要信息進(jìn)行對(duì)比,沒(méi)問(wèn)題的話,用戶就算認(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ī)字符串的生成,另一方面就是客戶端摘要信息的校驗(yàn)。

  • 首先提供 DigestAuthenticationEntryPoint 的實(shí)例,配置服務(wù)端隨機(jī)數(shù)生成的一寫(xiě)參數(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ě)回到前端。

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

    測(cè)試效果其實(shí)和 HttpBasic 認(rèn)證是一樣的,所有的變化,只是背后的實(shí)現(xiàn)有所變化而已,用戶體驗(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)绻胱约悍烙胤殴?#xff0c;就可以參考這里的實(shí)現(xiàn)思路。

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

    今日干貨

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

    公眾號(hào)后臺(tái)回復(fù) ssm,免費(fèi)獲取松哥純手敲的 SSM 框架學(xué)習(xí)干貨。

    總結(jié)

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

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