HttpClient 三种 Http Basic Authentication 认证方式,你了解了吗?

4,644 阅读4分钟

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 的三种验证方式,希望对你有所帮助。

文章不足之处,望大家多多指点,共同学习,共同进步

源代码 点击此处

最后

打个小广告,欢迎扫码关注微信公众号:「平头哥的技术博文」,一起进步吧。

平头哥的技术博文