成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

SpringBoot中如何實現(xiàn)HTTP認證

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

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

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

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

1.什么是 HttpBasic

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

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

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

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

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

2.HttpBasic 認證

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

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

Spring Boot中如何實現(xiàn)HTTP認證

接下來創(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 接口,此時瀏覽器中會有彈出框,讓我們輸入用戶名/密碼信息:

Spring Boot中如何實現(xiàn)HTTP認證

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

Spring Boot中如何實現(xiàn)HTTP認證

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

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

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

Spring Boot中如何實現(xiàn)HTTP認證

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

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

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

解碼結(jié)果如下:

Spring Boot中如何實現(xiàn)HTTP認證

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

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

  1. 瀏覽器發(fā)出請求,說要訪問 /hello 接口。

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

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

  4. 服務(wù)端對瀏覽器傳來的信息進行解碼,并校驗,當(dāng)沒問題的時候,給客戶端作出響應(yīng)。

大致的流程就是這樣。

3.Http 摘要認證

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

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

  1. 瀏覽器發(fā)出請求,說要訪問 /hello 接口。

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

Spring Boot中如何實現(xiàn)HTTP認證

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

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

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

Spring Boot中如何實現(xiàn)HTTP認證

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

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

  • response 是生成的摘要信息。

  • nc 表示請求此時,可以防止重放攻擊。

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

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

這就是整個流程。

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

好了,那這個在 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();
   }

}

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

  1. 首先提供 DigestAuthenticationEntryPoint 的實例,配置服務(wù)端隨機數(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 編碼字符,再將該編碼字符寫回到前端。

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

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

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

4.小結(jié)

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

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

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

分享題目:SpringBoot中如何實現(xiàn)HTTP認證
URL鏈接:http://jinyejixie.com/article0/jdojoo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供域名注冊網(wǎng)站設(shè)計公司、網(wǎng)站導(dǎo)航、動態(tài)網(wǎng)站、全網(wǎng)營銷推廣、App設(shè)計

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都app開發(fā)公司
沈丘县| 驻马店市| 高淳县| 邮箱| 高唐县| 射洪县| 左贡县| 齐河县| 南江县| 蒲城县| 拉萨市| 平凉市| 灵石县| 蒲城县| 泸溪县| 绍兴市| 铁岭市| 习水县| 义乌市| 龙里县| 铅山县| 桂林市| 洪泽县| 湛江市| 高淳县| 淅川县| 克拉玛依市| 黔西| 岳池县| 海兴县| 桦川县| 永宁县| 肇源县| 观塘区| 榆中县| 佳木斯市| 云安县| 丹巴县| 封丘县| 比如县| 宿迁市|