HttpClient4.3教程 第四章 HTTP认证

2024-04-29 01:38

本文主要是介绍HttpClient4.3教程 第四章 HTTP认证,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

HttpClient既支持HTTP标准规范定义的认证模式,又支持一些广泛使用的非标准认证模式,比如NTLM和SPNEGO。

4.1.用户凭证

任何用户认证的过程,都需要一系列的凭证来确定用户的身份。最简单的用户凭证可以是用户名和密码这种形式。UsernamePasswordCredentials这个类可以用来表示这种情况,这种凭据包含明文的用户名和密码。

这个类对于HTTP标准规范中定义的认证模式来说已经足够了。

    UsernamePasswordCredentials creds = new UsernamePasswordCredentials("user", "pwd");System.out.println(creds.getUserPrincipal().getName());System.out.println(creds.getPassword());

上述代码会在控制台输出:

    userpwd

NTCredentials是微软的windows系统使用的一种凭据,包含username、password,还包括一系列其他的属性,比如用户所在的域名。在Microsoft Windows的网络环境中,同一个用户可以属于不同的域,所以他也就有不同的凭据。

    NTCredentials creds = new NTCredentials("user", "pwd", "workstation", "domain");System.out.println(creds.getUserPrincipal().getName());System.out.println(creds.getPassword());

上述代码输出:

    DOMAIN/userpwd

4.2. 认证方案

AutoScheme接口表示一个抽象的面向挑战/响应的认证方案。一个认证方案要支持下面的功能:

  • 客户端请求服务器受保护的资源,服务器会发送过来一个chanllenge(挑战),认证方案(Authentication scheme)需要解析、处理这个挑战
  • 为processed challenge提供一些属性值:认证方案的类型,和此方案需要的一些参数,这种方案适用的范围
  • 使用给定的授权信息生成授权字符串;生成http请求,用来响应服务器发送来过的授权challenge

请注意:一个认证方案可能是有状态的,因为它可能涉及到一系列的挑战/响应。

HttpClient实现了下面几种AutoScheme:

  • Basic: Basic认证方案是在RFC2617号文档中定义的。这种授权方案用明文来传输凭证信息,所以它是不安全的。虽然Basic认证方案本身是不安全的,但是它一旦和TLS/SSL加密技术结合起来使用,就完全足够了。
  • Digest: Digest(摘要)认证方案是在RFC2617号文档中定义的。Digest认证方案比Basic方案安全多了,对于那些受不了Basic+TLS/SSL传输开销的系统,digest方案是个不错的选择。
  • NTLM: NTLM认证方案是个专有的认证方案,由微软开发,并且针对windows平台做了优化。NTLM被认为比Digest更安全。
  • SPNEGO: SPNEGO(Simple and Protected GSSAPI Negotiation Mechanism)是GSSAPI的一个“伪机制”,它用来协商真正的认证机制。SPNEGO最明显的用途是在微软的HTTP协商认证机制拓展上。可协商的子机制包括NTLM、Kerberos。目前,HttpCLient只支持Kerberos机制。(原文:The negotiable sub-mechanisms include NTLM and Kerberos supported by Active Directory. At present HttpClient only supports the Kerberos sub-mechanism.)

4.3. 凭证 provider

凭证providers旨在维护一套用户的凭证,当需要某种特定的凭证时,providers就应该能产生这种凭证。认证的具体内容包括主机名、端口号、realm name和认证方案名。当使用凭据provider的时候,我们可以很模糊的指定主机名、端口号、realm和认证方案,不用写的很精确。因为,凭据provider会根据我们指定的内容,筛选出一个最匹配的方案。

只要我们自定义的凭据provider实现了CredentialsProvider这个接口,就可以在HttpClient中使用。默认的凭据provider叫做BasicCredentialsProvider,它使用java.util.HashMapCredentialsProvider进行了简单的实现。

    CredentialsProvider credsProvider = new BasicCredentialsProvider();credsProvider.setCredentials(new AuthScope("somehost", AuthScope.ANY_PORT), new UsernamePasswordCredentials("u1", "p1"));credsProvider.setCredentials(new AuthScope("somehost", 8080), new UsernamePasswordCredentials("u2", "p2"));credsProvider.setCredentials(new AuthScope("otherhost", 8080, AuthScope.ANY_REALM, "ntlm"), new UsernamePasswordCredentials("u3", "p3"));System.out.println(credsProvider.getCredentials(new AuthScope("somehost", 80, "realm", "basic")));System.out.println(credsProvider.getCredentials(new AuthScope("somehost", 8080, "realm", "basic")));System.out.println(credsProvider.getCredentials(new AuthScope("otherhost", 8080, "realm", "basic")));System.out.println(credsProvider.getCredentials(new AuthScope("otherhost", 8080, null, "ntlm")));

上面代码输出:

    [principal: u1][principal: u2]null[principal: u3]

4.4.HTTP授权和执行上下文

HttpClient依赖AuthState类去跟踪认证过程中的状态的详细信息。在Http请求过程中,HttpClient创建两个AuthState实例:一个用于目标服务器认证,一个用于代理服务器认证。如果服务器或者代理服务器需要用户的授权信息,AuthScopeAutoScheme和认证信息就会被填充到两个AuthScope实例中。通过对AutoState的检测,我们可以确定请求的授权类型,确定是否有匹配的AuthScheme,确定凭据provider根据指定的授权类型是否成功生成了用户的授权信息。

在Http请求执行过程中,HttpClient会向执行上下文中添加下面的授权对象:

  • Lookup对象,表示使用的认证方案。这个对象的值可以在本地上下文中进行设置,来覆盖默认值。
  • CredentialsProvider对象,表示认证方案provider,这个对象的值可以在本地上下文中进行设置,来覆盖默认值。
  • AuthState对象,表示目标服务器的认证状态,这个对象的值可以在本地上下文中进行设置,来覆盖默认值。
  • AuthState对象,表示代理服务器的认证状态,这个对象的值可以在本地上下文中进行设置,来覆盖默认值。
  • AuthCache对象,表示认证数据的缓存,这个对象的值可以在本地上下文中进行设置,来覆盖默认值。

我们可以在请求执行前,自定义本地HttpContext对象来设置需要的http认证上下文;也可以在请求执行后,再检测HttpContext的状态,来查看授权是否成功。

    CloseableHttpClient httpclient = <...>CredentialsProvider credsProvider = <...>Lookup<AuthSchemeProvider> authRegistry = <...>AuthCache authCache = <...>HttpClientContext context = HttpClientContext.create();context.setCredentialsProvider(credsProvider);context.setAuthSchemeRegistry(authRegistry);context.setAuthCache(authCache);HttpGet httpget = new HttpGet("http://www.itnose.net/");CloseableHttpResponse response1 = httpclient.execute(httpget, context);<...>AuthState proxyAuthState = context.getProxyAuthState();System.out.println("Proxy auth state: " + proxyAuthState.getState());System.out.println("Proxy auth scheme: " + proxyAuthState.getAuthScheme());System.out.println("Proxy auth credentials: " + proxyAuthState.getCredentials());AuthState targetAuthState = context.getTargetAuthState();System.out.println("Target auth state: " + targetAuthState.getState());System.out.println("Target auth scheme: " + targetAuthState.getAuthScheme());System.out.println("Target auth credentials: " + targetAuthState.getCredentials());

4.5. 缓存认证数据

从版本4.1开始,HttpClient就会自动缓存验证通过的认证信息。但是为了使用这个缓存的认证信息,我们必须在同一个上下文中执行逻辑相关的请求。一旦超出该上下文的作用范围,缓存的认证信息就会失效。

4.6. 抢先认证

HttpClient默认不支持抢先认证,因为一旦抢先认证被误用或者错用,会导致一系列的安全问题,比如会把用户的认证信息以明文的方式发送给未授权的第三方服务器。因此,需要用户自己根据自己应用的具体环境来评估抢先认证带来的好处和带来的风险。

即使如此,HttpClient还是允许我们通过配置来启用抢先认证,方法是提前填充认证信息缓存到上下文中,这样,以这个上下文执行的方法,就会使用抢先认证。

    CloseableHttpClient httpclient = <...>HttpHost targetHost = new HttpHost("localhost", 80, "http");CredentialsProvider credsProvider = new BasicCredentialsProvider();credsProvider.setCredentials(new AuthScope(targetHost.getHostName(), targetHost.getPort()),new UsernamePasswordCredentials("username", "password"));// 创建 AuthCache 对象AuthCache authCache = new BasicAuthCache();//创建 BasicScheme,并把它添加到 auth cache中BasicScheme basicAuth = new BasicScheme();authCache.put(targetHost, basicAuth);// 把AutoCache添加到上下文中HttpClientContext context = HttpClientContext.create();context.setCredentialsProvider(credsProvider);HttpGet httpget = new HttpGet("/");for (int i = 0; i < 3; i++) {CloseableHttpResponse response = httpclient.execute(targetHost, httpget, context);try {HttpEntity entity = response.getEntity();} finally {response.close();}}

4.7. NTLM认证

从版本4.1开始,HttpClient就全面支持NTLMv1、NTLMv2和NTLM2认证。当人我们可以仍旧使用外部的NTLM引擎(比如Samba开发的JCIFS库)作为与Windows互操作性程序的一部分。

4.7.1. NTLM连接持久性

相比BasicDigest认证,NTLM认证要明显需要更多的计算开销,性能影响也比较大。这也可能是微软把NTLM协议设计成有状态连接的主要原因之一。也就是说,NTLM连接一旦建立,用户的身份就会在其整个生命周期和它相关联。NTLM连接的状态性使得连接持久性更加复杂,The stateful nature of NTLM connections makes connection persistence more complex, as for the obvious reason persistent NTLM connections may not be re-used by users with a different user identity. HttpClient中标准的连接管理器就可以管理有状态的连接。但是,同一会话中逻辑相关的请求,必须使用相同的执行上下文,这样才能使用用户的身份信息。否则,HttpClient就会结束旧的连接,为了获取被NTLM协议保护的资源,而为每个HTTP请求,创建一个新的Http连接。更新关于Http状态连接的信息,点击此处。

由于NTLM连接是有状态的,一般推荐使用比较轻量级的方法来处罚NTLM认证(如GET、Head方法),然后使用这个已经建立的连接在执行相对重量级的方法,尤其是需要附件请求实体的请求(如POST、PUT请求)。

    CloseableHttpClient httpclient = <...>CredentialsProvider credsProvider = new BasicCredentialsProvider();credsProvider.setCredentials(AuthScope.ANY,new NTCredentials("user", "pwd", "myworkstation", "microsoft.com"));HttpHost target = new HttpHost("www.itnose.net", 80, "http");//使用相同的上下文来执行逻辑相关的请求HttpClientContext context = HttpClientContext.create();context.setCredentialsProvider(credsProvider);//使用轻量级的请求来触发NTLM认证HttpGet httpget = new HttpGet("/ntlm-protected/info");CloseableHttpResponse response1 = httpclient.execute(target, httpget, context);try {HttpEntity entity1 = response1.getEntity();} finally {response1.close();}//使用相同的上下文,执行重量级的方法HttpPost httppost = new HttpPost("/ntlm-protected/form");httppost.setEntity(new StringEntity("lots and lots of data"));CloseableHttpResponse response2 = httpclient.execute(target, httppost, context);try {HttpEntity entity2 = response2.getEntity();} finally {response2.close();}

4.8. SPNEGO/Kerberos认证

SPNEGO(Simple and Protected GSSAPI Megotiation Mechanism),当双方均不知道对方能使用/提供什么协议的情况下,可以使用SP认证协议。这种协议在Kerberos认证方案中经常使用。It can wrap other mechanisms, however the current version in HttpClient is designed solely with Kerberos in mind.

4.8.1. 在HTTPCIENT中使用SPNEGO

SPNEGO认证方案兼容Sun java 1.5及以上版本。但是强烈推荐jdk1.6以上。Sun的JRE提供的类就已经几乎完全可以处理Kerberos和SPNEGO token。这就意味着,需要设置很多的GSS类。SpnegoScheme是个很简单的类,可以用它来handle marshalling the tokens and 读写正确的头消息。

最好的开始方法就是从示例程序中找到KerberosHttpClient.java这个文件,尝试让它运行起来。运行过程有可能会出现很多问题,但是如果人品比较高可能会顺利一点。这个文件会提供一些输出,来帮我们调试。

在Windows系统中,应该默认使用用户的登陆凭据;当然我们也可以使用kinit来覆盖这个凭据,比如$JAVA_HOME\bin\kinit testuser@AD.EXAMPLE.NET,这在我们测试和调试的时候就显得很有用了。如果想用回Windows默认的登陆凭据,删除kinit创建的缓存文件即可。

确保在krb5.conf文件中列出domain_realms。这能解决很多不必要的问题。

4.8.2. 使用GSS/JAVA KERBEROS

下面的这份文档是针对Windows系统的,但是很多信息同样适合Unix。

org.ietf.jgss这个类有很多的配置参数,这些参数大部分都在krb5.conf/krb5.ini文件中配置。更多的信息,参考此处。

login.conf文件

下面是一个基本的login.conf文件,使用于Windows平台的IIS和JBoss Negotiation模块。

系统配置文件java.security.auth.login.config可以指定login.conf文件的路径。
login.conf的内容可能会是下面的样子:

    com.sun.security.jgss.login {com.sun.security.auth.module.Krb5LoginModule required client=TRUE useTicketCache=true;};com.sun.security.jgss.initiate {com.sun.security.auth.module.Krb5LoginModule required client=TRUE useTicketCache=true;};com.sun.security.jgss.accept {com.sun.security.auth.module.Krb5LoginModule required client=TRUE useTicketCache=true;};

4.8.4. KRB5.CONF / KRB5.INI 文件

如果没有手动指定,系统会使用默认配置。如果要手动指定,可以在java.security.krb5.conf中设置系统变量,指定krb5.conf的路径。krb5.conf的内容可能是下面的样子:

    [libdefaults]default_realm = AD.EXAMPLE.NETudp_preference_limit = 1[realms]AD.EXAMPLE.NET = {kdc = KDC.AD.EXAMPLE.NET}[domain_realms].ad.example.net=AD.EXAMPLE.NETad.example.net=AD.EXAMPLE.NET

4.8.5. WINDOWS详细的配置

为了允许Windows使用当前用户的tickets,javax.security.auth.useSubjectCredsOnly这个系统变量应该设置成false,并且需要在Windows注册表中添加allowtgtsessionkey这个项,而且要allow session keys to be sent in the Kerberos Ticket-Granting Ticket.

Windows Server 2003和Windows 2000 SP4,配置如下:

    HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa\Kerberos\ParametersValue Name: allowtgtsessionkeyValue Type: REG_DWORDValue: 0x01

Windows XP SP2 配置如下:

    HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa\Kerberos\Value Name: allowtgtsessionkeyValue Type: REG_DWORDValue: 0x01

 

这篇关于HttpClient4.3教程 第四章 HTTP认证的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/944799

相关文章

用户登录认证和权限授权(SpringSecurity、JWT、session)

文章目录 前言一、登录认证1. 问题引入2. Session2.1 实现原理2.2 过滤器Filter2.3 上下文对象 3. JWT3.2 实现步骤3.3 拦截器 HandlerInterceptorAdapter3.4 上下文对象 4. Session VS JWT 二、权限授权1. 权限类型1.1 页面权限(菜单项权限)1.2 ACL模型 (Access Control List访问控

AppScan10.5.0 安装使用教程(看这一篇就够啦)附下载

免责声明 请勿利用文章内的相关技术从事非法测试。由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,作者不为此承担任何责任,请务必遵守网络安全法律法规。本文仅用于测试,请完成测试后24小时删除,请勿用于商业用途。如文中内容涉及侵权行为,请及时联系作者,我们会立刻删除并致歉。 0x01 简介 AppScan是一款网络安全测试工具,属于HCL(前IB

从使用教程、实现原理、差异对比全方面带你玩转业务系统中高频使用的过滤器与拦截器

1.概述 在Java Web开发中,**过滤器(Filter)和拦截器(Interceptor)**是两种常见的组件,用于在请求到达目标资源之前或之后执行一些操作,如日志记录、权限控制、字符编码处理等。虽然它们的作用有些类似,但在实际应用中又有不同之处。本文将深入探讨过滤器与拦截器的实现原理、区别差异以及在实际应用中的使用场景和示例。 过滤器(Filter) 过滤器是一种基于Java Ser

基于u-blox M8L的车载惯性导航系统方案(Carplay Location 认证)

此贴准备记录《基于u-blox M8L的车载惯性导航系统方案(Carplay Location 认证)》,先调查下, 如果有需求我再继续写。

【保姆级教程】VMware Workstation Pro的虚拟机导入vritualbox详细教程

解决方案 1、OVF格式2、VMX格式 1、OVF格式 选定需要导出的虚拟机(关闭或者挂起状态下)依次选择文件-导出为ovf 在Vritualbox导入刚刚导出的.ovf文件 更改路径,按实际需要修改 成功导入 2、VMX格式 如果在VMware Workstation Pro导出的虚拟机格式是.vmx的,这时候我们该如何解决呢?这时候我们就需要借助ovftoo

Java proxy HTTP ftp socket

public class ProxySelectorTest{//测试本地JVM的网络默认配置public void setLocalProxy(){Properties prop = System.getProperties();//设置HTTP访问要使用的代理服务器的地址prop.setProperty("http.proxyHost", "10.10.0.96");//设置HTTP访问要使用

JINGWHALE 数字认证体系 · 进阶知识库

JINGWHALE 数字认证体系 是 JINGWHALE 数字科学艺术创新中心 的数字认证服务。 ◢◤ 宗旨 致力于数字化知行合一的知识赋能! ◥ 数字化人才培养 培养数字化思维,传播数字化知识,赋能各行业数字化。 ◥ 职业人才发展 无缝衔接学校高等教育与企业职业工作( 学校高等教育 <-> JINGWHALE 职业教育 <-> 企业工作 )。 职业人才发展:培养职业需要的人

使用Python实现长短时记忆网络(LSTM)的博客教程

长短时记忆网络(Long Short-Term Memory,LSTM)是一种特殊类型的循环神经网络(RNN),专门设计用来解决序列数据中的长期依赖问题。本教程将介绍如何使用Python和PyTorch库实现一个简单的LSTM模型,并展示其在一个时间序列预测任务中的应用。 什么是长短时记忆网络(LSTM)? 长短时记忆网络是一种循环神经网络的变体,通过引入特殊的记忆单元(记忆细胞)和门控机制,

http 错误码大全

响应码由三位十进制数字组成,它们出现在由HTTP服务器发送的响应的第一行。 响应码分五种类型,由它们的第一位数字表示: 1.1xx:信息,请求收到,继续处理 2.2xx:成功,行为被成功地接受、理解和采纳 3.3xx:重定向,为了完成请求,必须进一步执行的动作 4.4xx:客户端错误,请求包含语法错误或者请求无法实现 5.5xx:服务器错误,服务器不能实现一种明显无效的请求 下表显示每个响应码

Cookies,SSL,httpclient的多线程处理,HTTP方法

HttpClient能自动管理cookie,包括允许服务器设置cookie并在需要的时候自动将cookie返回服务器,它也支持手工设置cookie后发送到服务器端。不幸的是,对如何处理cookie,有几个规范互相冲突:Netscape Cookie 草案, RFC2109, RFC2965,而且还有很大数量的软件商的cookie实现不遵循任何规范. 为了处理这种状况,HttpClient提供了策