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

相关文章

MySQL5.7免安装版配置图文教程(一劳永逸)

MySQL5.7免安装版配置图文教程 Mysql是一个比较流行且很好用的一款数据库软件,如下记录了我学习总结的mysql免安装版的配置经验。 一、 软件下载   5.7 32位https://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.19-win32.zip 5.7 64位https://dev.mysql.com/get/D

FL Studio 21.2.3.4004官方中文破解版下载安装激活教程重磅发布含注册机

今天带来的是FL Studio 21中文版,内置破解补丁,可以完美激活程序。所有功能均可在线编辑,用户可直接操作。同时,因为FL Studio 21是最新版本,所以增加了新的功能。共有八种乐器和效果器插件,包括效果链、音频发送、侧链控制、高级自动化、插件延迟补偿等十多种,帮助用户创作更多流行的音乐作品。 喜欢音乐制作的小伙伴千万不要错过这个功能强大,安装便捷的音乐软件哦!如果你们已经下载好

C++从入门到精通(最详细教程,12万总结,带你掌握c++知识,涵盖大量知识点)

目录 一、面向对象的思想 二、类的使用 1.类的构成 2.类的设计 三、对象的基本使用 四、类的构造函数 1.构造函数的作用 2.构造函数的特点 3.默认构造函数 3.1.合成的默认构造函数 3.2.手动定义的默认构造函数 四、自定义的重载构造函数 五、拷贝构造函数 1.手动定义的拷贝构造函数 2.合成的拷贝构造函数 3.什么时候调用拷贝构造函数 六、赋值构造函数

C语言入门级教程九

C语言入门级教程                  icesongqiang 2016.12.12 总结 scanf("%s,%s",a,b) 中间只有‘,’是达不到效果的,scanf 是连同‘,’一起读入a的;结构体变量要注意到底需要的是哪一个元素; 简单的图书结构体 /** 1.为图书建立相应的结构体* 2.利用结构体数组实现多本图书的存取*/#define _CRT

C语言入门级教程 八

C语言入门级教程                  icesongqiang 2016.12.05 总结 一维指针,二维指针以及行指针是不同的类型; 矩阵转置 /**矩阵转置* 内部设置一个大的方阵,用来装用户的矩阵,* 只在输入输出时按照用户的长,宽输出* 两重循环,每次内循环执行交换功能* @author icesongqiang 1204*/ #include

C语言入门级教程 七

C语言入门级教程                  icesongqiang 2016.11.28 总结 关于宏定义,宏定义会在编译时在宏的所在位置按定义展开,也就是替换过程。如 #define swap(a,b) {double temp=a;a=b;b=temp;} 那么就会在swap(a,b) 出现的地方由{double temp=a;a=b;b=temp;} 替换掉,注意

C语言入门级教程六

C语言入门级教程                  icesongqiang 2016.11.21 总结 这次上机,有的同学依然会犯一些基础的错误,比如 1.字符串的初始化与结束 2.数据类型不匹配(输入输出 %d %f) 3.循环语句 if语句不加大括号 4. 关于字符串逆序输出,我们重点的考察的是逆序存放,而不是简单地直接从最后一个开始打印,直接打印到第0个结束。 下

C语言入门级教程五

C语言入门级教程                  icesongqiang 2016.11.14 本次试验暴露出来的一些问题: 1. if() 条件判断等于,里面一定是if(a==b) , 而if(a=b) 执行赋值操作,赋值的数就是表达式的值; 2. 字符串拼接,将char b[80] 拼接到 char a[80] 后,一定要添加 '\0' ; 3. 单词统计很多同学的统

C语言入门级教程二

C语言入门级教程                  icesongqiang 2016.10.24 熟悉运算符的左右结合性 这里只提出比较重要的几个。 1). “? : “的右结合性 2). “*=, +=, =+”和”/=”的右结合性  例如:int ia=12; ia += ia -= ia *= ia;很多同学都可以得到结果为0,但是其中ia的具体变化情况其实知道的不

C语言入门级教程

C语言入门级教程                  icesongqiang 2016.10.17 数据类型 常用数据类型 整型(int, short, long, c++11 long long)字符型(char)实型(float, double)枚举类型(enum )构造数据类型 结构体类型数组类型指针类型空类型(void) 实验一 各种类型和其格式化输出语句