Basic and Digest Access Authentication (rfc2617) 及HttpClient实现

介绍Basic和Digest

http协议并没有定义相关的安全认证方面的标准,所以就有了Basic and Digest Access Authentication的定义来补充,它的目的就是补充一套基于http服务端的认证机制,保护相关的资源避免被非法用户访问,如果你要访问被保护的资源,则必需要提供合法的用户名和密码。

和https有什么关联?

basic & digest auth 和 https 没有任何关系。前者是为用户认证机制,后者是信息通道加密措施。

basic 和 digest有什么区别?

digest是basic的升级版,更加安全。因为basic是明文传输密码信息,而digest是加密后传输。

digest就是绝对安全的吗?

首先,这个世界上没有绝对的东西。digest默认用MD5(其它算法也可以)对密码进行加密,虽然相比basic认证的明文传输更安全,但是加密算法本身的安全性也值得怀疑(md5是可以反推出原文的)。再者,digest只是对认证信息的加密,后续的内容传输安全性得不到保障。所以https机制的作用就显现出来。

通过上面的相关信息,我们可以得到一个清晰的结论:如果你想加强自己的认证信息的保护,有两种选择,一是基于digest认证;别一种是在https通道上进行basic认证。

basic和digest认证流程

 

1,客户端请求受保护的资源
2,服务器检测到没有授权,则生成一个challenge返回给客户端
3,客户端根据challenge和相关信息计算出digest
4,附带3计算出的信息再次请求1中的资源
5,服务端根据已知的用户密码信息计算出digest并与4中请求的digest比较验证
6,服务端验证通过后返回资源给合法用户

Basic和Digest的认证都是按照上面的流程来,唯一不同的是3和5中计算digest的算法不同:Basic是将密码直接base64编码(明文),而Digest是用MD5进行加密后传输。

下面假设我们现在要请求:http://localhost:8080/index.html 这个路径,而它需要认证后才能访问。


Basic的流程如下:

  1. 在浏览器请求:http://localhost:8080/index.html
  2. 服务器返回401(unauthentication)代码,并附带一个包含challenge的头,格式如下:WWW-Authenticate    Basic realm="Admin All"
  3. 浏览器用:base64(username:password) 编码后的信息添加到请求头中再次请求1中的资源,如果用户名是tomcat,密码是tomcat,则base64(tomcat:tomcat)为(dG9tY2F0OnRvbWNhdA==)。所以头信息为:Authorization    Basic dG9tY2F0OnRvbWNhdA==
  4. 用3中计算的请求头信息再次请求1中的资源
  5. 服务器用3中相同的算法(base64)验证用户密码合法性
  6. 返回index.html的资源

Digest的流程和上面一样,只是challenge和digest的生成算法不同

  1. 在浏览器请求:http://localhost:8080/index.html
  2. 服务器返回401(unauthentication)代码,并附带一个包含challenge的头,格式如下:WWW-Authenticate    Digest realm="Admin All", qop="auth", nonce="1354760194666:4465c7b1921b6d769fd359e5152c453f", opaque="EE9C283E89AFB63E7FF6E2C04C524807"
  3. 浏 览器用MD5编码后的信息添加到请求头中再次请求1中的资源,如果用户名是tomcat,密码是tomcat,则生成的头信息:Authorization    Digest username="tomcat", realm="Admin All", nonce="1354760194666:4465c7b1921b6d769fd359e5152c453f", uri="/web/index.html", response="8d30e6438636fe21c6045246dd034372", opaque="EE9C283E89AFB63E7FF6E2C04C524807", qop=auth, nc=00000001, cnonce="9201a828891792b9"
  4. 用3中计算的请求头信息再次请求1中的资源
  5. 服务器用3中相同的算法(base64)验证用户密码合法性
  6. 返回index.html的资源

这里我们只是讨论流程,具体的challenge和digest的生成算法请参考:RFC2617

HttpClient的实现

示例代码:

HttpHost targetHost = new HttpHost("localhost", 8080);
        
        DefaultHttpClient client = new DefaultHttpClient();
        
        HttpContext context = new BasicHttpContext();
        context.setAttribute(ClientContext.CREDS_PROVIDER, new BasicCredentialsProvider());
        CredentialsProvider provider = (CredentialsProvider)context.getAttribute(ClientContext.CREDS_PROVIDER);
        provider.setCredentials(
                new AuthScope(targetHost.getHostName(), targetHost.getPort()),
                new UsernamePasswordCredentials("tomcat", "admin"));
                
        HttpGet get = new HttpGet("http://localhost:8080/web/Hello");
     HttpResponse response = client.execute(get,context);
        System.out.println(response.getStatusLine());
        HttpEntity entity = response.getEntity();
        String s = EntityUtils.toString(entity);
        System.out.println(s);

 主要类结构图:

Auth流程图:

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
HttpClient可以通过提供的CredentialsProvider接口来实现digest认证。下面是一个示例代码: ```java import org.apache.http.HttpEntity; import org.apache.http.HttpHost; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.client.CredentialsProvider; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.impl.auth.DigestScheme; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.util.EntityUtils; import java.io.IOException; public class DigestAuthExample { public static void main(String[] args) throws IOException { String username = "user"; String password = "password"; HttpHost target = new HttpHost("localhost", 8080, "http"); CredentialsProvider credsProvider = new BasicCredentialsProvider(); credsProvider.setCredentials( new AuthScope(target.getHostName(), target.getPort()), new UsernamePasswordCredentials(username, password)); CloseableHttpClient httpClient = HttpClients.custom() .setDefaultCredentialsProvider(credsProvider) .build(); HttpClientContext context = HttpClientContext.create(); HttpGet httpGet = new HttpGet("/"); CloseableHttpResponse response = httpClient.execute(target, httpGet, context); try { HttpEntity entity = response.getEntity(); EntityUtils.consume(entity); } finally { response.close(); } // Get the digest scheme from the context DigestScheme digestScheme = (DigestScheme) context.getAuthScheme(target); // Use the digest scheme to generate the next request's headers HttpGet httpGet2 = new HttpGet("/"); httpGet2.addHeader(digestScheme.authenticate( new UsernamePasswordCredentials(username, password), httpGet2, context)); CloseableHttpResponse response2 = httpClient.execute(target, httpGet2, context); try { HttpEntity entity = response2.getEntity(); EntityUtils.consume(entity); } finally { response2.close(); } } } ``` 这个示例代码中,使用了BasicCredentialsProvider来提供用户名和密码。当httpClient执行第一次请求时,服务器返回401 Unauthorized响应,httpClient会尝试使用提供的凭据进行认证。然后,httpClient会使用DigestScheme生成下一个请求的摘要认证头。在第二次请求中,httpClient使用这个头来进行认证。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值