JAVA https ssl 连接验证服务端证书

摘要: 在服务端部署的应用,很多情况下是采用HTTPS SSL 方式,这种方式唯一的好处是数据在通过浏览器传输到 web application server  之间是加密的,一般不容易破解。有时候需要另外一个客户端:比如是Android 应用用https 方式去调用 API , 从安全性角度考虑,服务端颁发的证书授权的域名或者IP或者主机名,应该与客户端请求的URL 是一致的。如果不一致,就可能存在安全隐患。一般这种情况是在单向HTTPS 的情况才考虑,因为只有服务端证书,而没有客户端证书, 所以才需要验证客户端请求的URL 与服务端 证书授权的域名等是否一致。

在服务端部署的应用,很多情况下是采用HTTPS SSL 方式,这种方式唯一的好处是数据在通过浏览器传输到 web application server 之间是加密的,一般不容易破解。有时候需要另外一个客户端:比如是Android 应用用https 方式去调用 API , 从安全性角度考虑,服务端颁发的证书授权的域名或者IP或者主机名,应该与客户端请求的URL 是一致的。如果不一致,就可能存在安全隐患。

一般这种情况是在单向HTTPS 的情况才考虑,因为只有服务端证书,而没有客户端证书, 所以才需要验证客户端请求的URL 与服务端 证书授权的域名等是否一致。

看上去有点多此一举,但有些特例的情况下还是会用到, 它的一个基本思路是,首先是信任所有服务端的证书,连接上之后,再去获得证书的信息,然后对比请求的URL ,后面就是你自己的逻辑,想怎么玩就怎么玩, 下面是一段DEMO 代码

package com.test.www;

import java.io.FileOutputStream;
import java.io.ObjectOutputStream;
import java.security.cert.CertPath;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;

public class Test1 {
	public static void main(String args[]) throws Exception {
		HostnameVerifier hv = new HostnameVerifier() {
			public boolean verify(String urlHostName, SSLSession session) {
				System.out.println("Warning: URL Host: " + urlHostName
						+ " vs. " + session.getPeerHost());
				return true;
			}
		};
		trustAllHttpsCertificates();
		HttpsURLConnection.setDefaultHostnameVerifier(hv);

		SSLSocketFactory factory = HttpsURLConnection
				.getDefaultSSLSocketFactory();
		SSLSocket socket = (SSLSocket) factory.createSocket("portal.xxxxx.com",
				9443);// portal.xxxxx.com 192.168.1.15

		socket.startHandshake();
		SSLSession session = socket.getSession();
		// String sslHost = session.getPeerHost();
		// String host = "portal.xxxxx.com";
		// System.out.println("Host=" + host);
		// System.out.println("SSL Host=" + sslHost);
		// if (host.equals(sslHost)) {
		// System.out.println("good");
		// } else {
		// System.out.println("bad");
		// }

		java.security.cert.Certificate[] servercerts = session
				.getPeerCertificates();

		for (int i = 0; i < servercerts.length; i++) {
			X509Certificate c = (X509Certificate) servercerts[i];
			System.out.println(getValByAttributeTypeFromIssuerDN(c.getSubjectDN().toString(), "CN="));
		}

	}

	private static String getValByAttributeTypeFromIssuerDN(String dn,
			String attributeType) {
		String[] dnSplits = dn.split(",");
		for (String dnSplit : dnSplits) {
			if (dnSplit.contains(attributeType)) {
				String[] cnSplits = dnSplit.trim().split("=");
				if (cnSplits[1] != null) {
					return cnSplits[1].trim();
				}
			}
		}
		return "";
	}

	private static void trustAllHttpsCertificates() throws Exception {
		javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
		javax.net.ssl.TrustManager tm = new miTM();

		trustAllCerts[0] = tm;
		javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext
				.getInstance("SSL");
		sc.init(null, trustAllCerts, null);
		javax.net.ssl.HttpsURLConnection.setDefaultSSLSocketFactory(sc
				.getSocketFactory());
	}

	static class miTM implements javax.net.ssl.TrustManager,
			javax.net.ssl.X509TrustManager {
		public java.security.cert.X509Certificate[] getAcceptedIssuers() {
			return null;
		}

		public boolean isServerTrusted(
				java.security.cert.X509Certificate[] certs) {
			return true;
		}

		public boolean isClientTrusted(
				java.security.cert.X509Certificate[] certs) {
			return true;
		}

		public void checkServerTrusted(
				java.security.cert.X509Certificate[] certs, String authType)
				throws java.security.cert.CertificateException {
			return;
		}

		public void checkClientTrusted(
				java.security.cert.X509Certificate[] certs, String authType)
				throws java.security.cert.CertificateException {
			return;
		}
	}
}

上一篇: python/django生成动态验证码, 动态刷新, 直接修改 img src 属性
下一篇: jquery 动态创建form 并提交
 评论 ( What Do You Think )
名称
邮箱
网址
评论
验证
   
 

 


  • 微信公众号

  • 我的微信

站点声明:

1、一号门博客CMS,由Python, MySQL, Nginx, Wsgi 强力驱动

2、部分文章或者资源来源于互联网, 有时候很难判断是否侵权, 若有侵权, 请联系邮箱:summer@yihaomen.com, 同时欢迎大家注册用户,主动发布无版权争议的 文章/资源.

3、鄂ICP备14001754号-3, 鄂公网安备 42280202422812号