HttpClient 三種 Http Basic Authentication 認證方式,你了解了嗎?

  • 2019 年 10 月 3 日
  • 筆記

Http Basic 簡介

HTTP 提供一個用於許可權控制和認證的通用框架。最常用的 HTTP 認證方案是 HTTP Basic authentication。Http Basic 認證是一種用來允許網頁瀏覽器或其他客戶端程式在請求時提供用戶名和口令形式的身份憑證的一種登錄驗證方式。

優點

  • 基本認證的一個優點是基本上所有流行的網頁瀏覽器都支援基本認證。基本認證很少在可公開訪問的互聯網網站上使用,有時候會在小的私有系統中使用(如路由器網頁管理介面)。後來的機制HTTP摘要認證是為替代基本認證而開發的,允許密鑰以相對安全的方式在不安全的通道上傳輸。
  • 程式設計師和系統管理員有時會在可信網路環境中使用基本認證,使用Telnet或其他明文網路協議工具手動地測試Web伺服器。這是一個麻煩的過程,但是網路上傳輸的內容是人可讀的,以便進行診斷。

缺點

  • 雖然基本認證非常容易實現,但該方案創建在以下的假設的基礎上,即:客戶端和伺服器主機之間的連接是安全可信的。特別是,如果沒有使用SSL/TLS這樣的傳輸層安全的協議,那麼以明文傳輸的密鑰和口令很容易被攔截。該方案也同樣沒有對伺服器返回的資訊提供保護。
  • 現存的瀏覽器保存認證資訊直到標籤頁或瀏覽器被關閉,或者用戶清除歷史記錄。HTTP沒有為伺服器提供一種方法指示客戶端丟棄這些被快取的密鑰。這意味著伺服器端在用戶不關閉瀏覽器的情況下,並沒有一種有效的方法來讓用戶註銷

上面是Http Basic的簡介,它不是我們今天的主題,我們今天的主題是:HttpClient 三種 Http Basic Authentication認證方式,是哪三種認證方式呢?接下來我們去一探究竟,我們從模擬 Http Basic 服務端開始。

Http Basic 服務端

我們使用 SpringBoot和Spring Security 簡單的搭建一個具有 HTTP Basic Authentication 的服務。具體的搭建過程我就不陳述了,我在這裡先貼出關鍵程式碼,便於你的理解,完整的程式碼已經上傳到GitHub上面,文章末尾有鏈接。

配置 BasicAuthenticationEntryPoint

@Component  public class MyBasicAuthenticationEntryPoint extends BasicAuthenticationEntryPoint {      @Override      public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {          response.addHeader("WWW-Authenticate", "Basic realm=" + getRealmName());          response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);          PrintWriter printWriter = new PrintWriter(response.getOutputStream());          printWriter.write("Http Status 401: " + authException.getLocalizedMessage());      }        @Override      public void afterPropertiesSet() throws Exception {          setRealmName("developlee");          super.afterPropertiesSet();      }  }

配置 WebSecurityConfigurer

@Configuration  @EnableWebSecurity  public class SecurityConfig extends WebSecurityConfigurerAdapter {      @Autowired      private MyBasicAuthenticationEntryPoint authenticationEntryPoint;        @Override      protected void configure(HttpSecurity http) throws Exception {          http.authorizeRequests()                  .antMatchers("/login").permitAll()                  .anyRequest().authenticated()                  .and()                  // 開啟httpBasic                  .httpBasic()                  // 設置 BasicAuthenticationFilter                  .authenticationEntryPoint(authenticationEntryPoint);      }        @Override      protected void configure(AuthenticationManagerBuilder auth) throws Exception {          auth.inMemoryAuthentication().withUser("jamal").password(passwordEncoder().encode("123456")).authorities("ROLE_USER");      }        @Bean      protected PasswordEncoder passwordEncoder() {          return new BCryptPasswordEncoder();      }  }

編寫 Controller

@RestController  public class WebController {        @RequestMapping(path = "/hello")      public String hello(){          return "驗證通過";      }  }

啟動項目,訪問 http://127.0.0.1:8080/hello


至此,我們的 Http Basic 服務端搭建便已經完成了

HttpClient 三種 Http Basic 驗證方式

標準模式

private String URL_SECURED_BY_BASIC_AUTHENTICATION = "http://127.0.0.1:8080/hello";    private String DEFAULT_USER = "jamal";    private String DEFAULT_PASS = "123456";    @Test  public void CredentialsProvider()throws Exception{      // 創建用戶資訊      CredentialsProvider provider = new BasicCredentialsProvider();      UsernamePasswordCredentials credentials              = new UsernamePasswordCredentials(DEFAULT_USER, DEFAULT_PASS);      provider.setCredentials(AuthScope.ANY, credentials);        // 創建客戶端的時候進行身份驗證      HttpClient client = HttpClientBuilder.create()              .setDefaultCredentialsProvider(provider)              .build();        HttpResponse response = client.execute(              new HttpGet(URL_SECURED_BY_BASIC_AUTHENTICATION));      int statusCode = response.getStatusLine()              .getStatusCode();      Assert.assertEquals(statusCode,200);  }

搶先模式

@Test  public void PreemptiveBasicAuthentication()throws Exception{      // 先進行身份驗證      HttpHost targetHost = new HttpHost("localhost", 8080, "http");      CredentialsProvider credsProvider = new BasicCredentialsProvider();      credsProvider.setCredentials(AuthScope.ANY,              new UsernamePasswordCredentials(DEFAULT_USER, DEFAULT_PASS));        AuthCache authCache = new BasicAuthCache();      // 將身份驗證放入快取中      authCache.put(targetHost, new BasicScheme());        HttpClientContext context = HttpClientContext.create();      context.setCredentialsProvider(credsProvider);      context.setAuthCache(authCache);      HttpClient client = HttpClientBuilder.create().build();      HttpResponse response = client.execute(              new HttpGet(URL_SECURED_BY_BASIC_AUTHENTICATION), context);        int statusCode = response.getStatusLine().getStatusCode();      Assert.assertEquals(statusCode,200);  }

原生 Http Basic 模式

@Test  public void HttpBasicAuth()throws Exception{      HttpGet request = new HttpGet(URL_SECURED_BY_BASIC_AUTHENTICATION);      // 手動構建驗證資訊      String auth = DEFAULT_USER + ":" + DEFAULT_PASS;      byte[] encodedAuth = Base64.encodeBase64(              auth.getBytes(StandardCharsets.UTF_8));      String authHeader = "Basic " + new String(encodedAuth);      // 將驗證資訊放入到 Header      request.setHeader(HttpHeaders.AUTHORIZATION, authHeader);        HttpClient client = HttpClientBuilder.create().build();      HttpResponse response = client.execute(request);        int statusCode = response.getStatusLine().getStatusCode();      Assert.assertEquals(statusCode,200);  }

以上就是 HttpClient Http Basic 的三種驗證方式,希望對你有所幫助。

文章不足之處,望大家多多指點,共同學習,共同進步

源程式碼 點擊此處

最後

打個小廣告,歡迎掃碼關注微信公眾號:「平頭哥的技術博文」,一起進步吧。
平頭哥的技術博文