关于weblogic host name varify 的一个问题记录

简介:

关于weblogic host name varify 的一个问题

问题是项目组一个同事发现的。
出问题的代码如下:


1
2
3
4
5
6
7
8
9
10
StringBuilder document =  new  StringBuilder();
URL url =  new  URL(Constants.URL); // 远程url,实际值为:https://mapi.alipay.com/...
URLConnection conn = url.openConnection();
BufferedReader reader =  new  BufferedReader( new  InputStreamReader(
     conn.getInputStream()));
String line =  null ;
while  ((line = reader.readLine()) !=  null ) {
   document.append(line +  " " );
}
reader.close();


当在weblogic服务器上运行时,抛出了如下异常:

1
2
3
4
5
6
7
8
9
< 2013 - 10 - 22  下午 02 11 12 秒 CST> <Error> <HTTP> <BEA- 101019 > <[ServletContext @25331129 [app:httpTest module:WebContent path:/TestHTTPS spec-version: 2.5 ]] Servlet failed with IOException
javax.net.ssl.SSLKeyException: [Security: 090504 ]Certificate chain received from mapi.alipay.com -  110.75 . 142.31  failed hostname verification check. Certificate contained *.alipay.com but check expected mapi.alipay.com
   at com.certicom.tls.interfaceimpl.TLSConnectionImpl.fireException(Unknown Source)
   at com.certicom.tls.interfaceimpl.TLSConnectionImpl.fireAlertSent(Unknown Source)
   at com.certicom.tls.record.handshake.HandshakeHandler.fireAlert(Unknown Source)
   at com.certicom.tls.record.handshake.HandshakeHandler.fireAlert(Unknown Source)
   at com.certicom.tls.record.handshake.ClientStateReceivedServerHello.handle(Unknown Source)
   Truncated. see log file  for  complete stacktrace
>


经过那位同事的不懈努力,发现了问题所在:
在作为客户端发起https请求时,weblogic服务器会对所请求的服务端做SSL的主机名验证,验证方法是对服务端的授权证书和https请求的URL进行比对,比对规则视配置项而定。这项配置在weblogic服务器的console→环境→服务器→配置→SSL页面上,展开“高级”(advanced)菜单中。查看其中的“主机名验证”(host name varify )选项,会发现这里的默认配置为“BEA 主机名验证器”(BEA host name varify )。这个默认配置会对授权证书和URL进行完全匹配的验证,也就是必须完全相同,才认为是验证通过,并给https请求放行。

对应到系统中出问题的地方,就是因为授权证书中的地址是“*.alipay.com”(采用了通配符的写法),而实际访问的地址是“mapi.alipay.com”。在完全匹配的规则下,当然会验证失败。

网上查到的解决办法,多半是直接关闭weblogic的主机名验证服务,也就是在上述配置项中选择“无”(none)。但是这种选择确实有风险。

经过那位同事的继续努力,发现了另一种解决方法
将代码修改如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
StringBuffer result =  new  StringBuffer();
HttpClient httpClient =  new  DefaultHttpClient();
// 使用的请求方式是GET
HttpGet httpGet =  new  HttpGet(Constants.URL);
try  {
   HttpResponse response = httpClient.execute(httpGet);
   HttpEntity httpEntity = response.getEntity();
   if  (httpEntity !=  null ) {
     InputStream inputStream = httpEntity.getContent();
     byte [] responseByte =  new  byte [ 2048 ];
     int  len =  0 ;
     while  ((len = inputStream.read(responseByte)) != - 1 ) {
       result.append( new  String(responseByte,  0 , len));
     }
   }
catch  (ClientProtocolException e) {
   e.printStackTrace();
catch  (IOException e) {
   e.printStackTrace();
finally  {
   // 关闭http请求
   httpClient.getConnectionManager().shutdown();
}


最主要的修改点,就是将直接用URL打开URLConnection的方法用HttpClient进行了改写。改写之后,即使weblogic服务器的配置仍然是“BEA 主机名验证器”,https请求也能够畅通无阻。

之所以能够成功,是因为HttpClient中,对发起的Https请求会附加一个主机名验证器,默认的是BrowserCompatHostnameVerifier。这个验证器与Firefox的工作方式是相同的,它可以匹配所有子域的通配符(比如”*.foo.com”)。HttpClient还有两个主机名验证器,按下不表。

然后,那位同事和我们讨论了一下为什么使用了HttpClient之后,weblogic上配置的主机名验证器就失效了呢?

weblogic在对外发出https请求时,会将这个请求封装为一个“weblogic.security.SSL.SSLClientInfo”类的实例。在这个实例中,有一个字段是“private HostnameVerifier hostnameVerifier;”。weblogic在通过“weblogic.security.utils.SSLSetup"类来构建这个实例的时候,会判断原有连接中是否自带有HostnameVerifier。如果有,则使用原配;否则,就会按照weblogic服务器的配置,组装上一个主机名验证器。

所以,当使用了HttpClient之后,服务器就会按照HttpClient自带的主机名验证器进行验证,而自己的配置却被置之脑后了。

除了使用HttpClient,还有两种方式可以解决这个问题。

其一是仿照HttpClient的思路,为Https请求带上一个自定义的主机名验证器,
代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
URL url =  new  URL(Constants.URL); // 远程url
HttpsURLConnection conn =  new  HttpsURLConnection(url);
conn.setHostnameVerifier( new  HostnameVerifier() {
   @Override
   public  boolean  verify(String arg0, SSLSession arg1) {
     System.out.println( "这里是自定义的特殊处理:只打印,不校验" );
     return  true ;
   }
});
System.out.println(conn.getHostnameVerifier());
BufferedReader reader =  new  BufferedReader( new  InputStreamReader(
     conn.getInputStream()));
String line =  null ;
while  ((line = reader.readLine()) !=  null ) {
   document.append(line +  " " );
}
reader.close();


这里使用的是HttpsURLConnection,因为只有这个类,才有setHostnameVerifier等相关接口。

另一种方式是为weblogic自定义一个主机名校验器,并为服务器做“定制主机名验证器”的相关配置。
自定义校验器的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package  verifier;
import  javax.net.ssl.SSLSession;
import  weblogic.security.SSL.HostnameVerifier;
/**
  * 自定义的主机名验证类
  * @since 2013-10-14
  * @version 1.0.0
  */
public  class  CustomerVerifier  implements  HostnameVerifier {
   /**
    * 验证方法。
    * @since 2013-10-14
    * @param arg0
    * @param arg1
    * @return
    * @see weblogic.security.SSL.HostnameVerifier#verify(java.lang.String,
    *   javax.net.ssl.SSLSession)
    *
    */
   @Override
   public  boolean  verify(String arg0, SSLSession arg1) {
     System.out.println( "this is the CustomerVerifier by Loy, arg0 = "
         + arg0 +  ", arg1 = "  + arg1);
     return  true ;
   }
}


在服务器上做如下配置:
1、主机名验证选项选择“定制主机名验证器”;
2、“定制主机名验证器:”输入框中输入自定义的类的全路径类名,如“verifier.CustomerVerifier”;
3、将自定义类的class文件放到weblogic服务器的ClassPath下,如将其导出为jar包,并在weblogic启动脚本中加入配置:set CLASSPATH=%CLASSPATH%;D:\bea\user_projects\domains\car_domain_10\lib\CustomerVerifier.jar

配置完成后,重启服务器,然后再次运行最早的那段会抛出异常的代码。正常情况下,这个请求就能够获得返回数据了。




本文转自 斯然在天边 51CTO博客,原文链接:http://blog.51cto.com/winters1224/1313111,如需转载请自行联系原作者

相关文章
|
5月前
|
Java 应用服务中间件 Linux
centos7安装weblogic
centos7安装weblogic
137 1
|
负载均衡 Java 应用服务中间件
Weblogic的了解、安装及其使用(三)
Weblogic的了解、安装及其使用
1529 0
|
Oracle Java 关系型数据库
Weblogic的了解、安装及其使用(二)
Weblogic的了解、安装及其使用
1108 0
|
开发框架 Kubernetes 监控
Weblogic的了解、安装及其使用(一)
Weblogic的了解、安装及其使用
2994 0
|
安全 Oracle Java
Oracle Weblogic--CentOS Linux 8.5.2安装weblogic11G
Weblogic在centos上详细安装步骤及安装过程中可能遇到的问题
356 0
Oracle Weblogic--CentOS Linux 8.5.2安装weblogic11G
|
Oracle 关系型数据库 Java
EOS Platform 7.2下安装weblogic插件
在实际工作中,需要用到EOS Platform,这是一个基于Eclipse的开发工具,自带了Tomcat,可以满足大部分需要,但是有时候需要使用Weblogic,这就得手动安装Weblogic插件了。这个过程与Eclipse相同(Eclipse下安装weblogic插件),本文中在EOS Platform 7.2中安装Weblogic插件。
210 0
EOS Platform 7.2下安装weblogic插件
|
Oracle 关系型数据库 Java
Eclipse下安装weblogic插件
安装好weblogic dev版本(Windows下安装weblogic dev版本),可以在Eclipse中安装weblogic server tools插件,直接连接到weblogic server,发布、部署、调试都变得简单些。
717 0
Eclipse下安装weblogic插件
|
Oracle 关系型数据库 Java
Windows下安装weblogic dev版本
在开发过程中,有一种情况是比较尴尬的:需要用到某个软件,但是只需要用到这个软件中的一小部分功能,这样既浪费的磁盘空间,又浪费了CPU空间。比如Weblogic,完整版包括很多功能,但是开发过程中,只是需要创建数据源、部署项目,然后进行测试即可。所以开发过程中,需要一款简化的Weblogic(Weblogic开发版)是挺有必要的(如果电脑配置比较壕,也可以任性的使用完整版)。
340 0
Windows下安装weblogic dev版本
|
XML SQL 开发框架
Weblogic安装与配置详解
Weblogic安装与配置用Eclipse MyEclipse WebLogic8.1开发第一个Web程序1.安装jreEclipse虽然由java开发,但本身并不自带jre。所以你必须先自己安装,去http://java.sun.com/downloads下载最新J2SE1.4.2_03的jre安装文件j2re-1_4_2_03-windows-i586-p.exe。安装成功后,重启机器,并将jre的bin文件夹路径添加到系统环境变量PATH中,如:C:\Program Files\Java\j2re1.4.2_03\bin。
466 0
|
Java Linux 应用服务中间件
Linux安装weblogic服务
Linux安装weblogic服务 一、环境准备: Linux系统 jdk-7u75-linux-x64.tar.gz(http://pan.baidu.com/s/1kTh5Vx1) wls1212_dev.zip(http://pan.baidu.com/s/1nttDkq1) 二、安装步骤: 1、首先创建weblogic用户、用户组并设置主目录 [root@localhost ~]# useradd -d /weblogic weblogic [root@localhost ~]# passwd weblogic 更改用户 weblogic 的密码。
2850 0