1. 程式人生 > >HttpClient 三種 Http Basic Authentication 認證方式,你瞭解了嗎?

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

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 的三種驗證方式,希望對你有所幫助。

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

原始碼 點選此處

最後

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