一、用tomcat搭建一个简单的webapp
在tomcat的webapps下新建一个文件夹,放入jsp,html文件及一个包含web.xml的WEB-INF文件夹即可。
因此不能把Eclipse编辑好的web项目直接弄到webapps下,那里面还有好多乱七八糟的东西,eclipse自动部署功能能根据路径合理分配
二、单向认证服务:
1.域名绑定:C:\Windows\System32\drivers\etc\hosts 末尾加上127.0.0.1 www.zlex.org
2.证书导入:Internet选项->内容->证书->导入(这里我们用的是keytool生成的本地证书,如果是国际CA签发的数字证书,则无需导入)
3.修改tomcat的serverl.xml:
<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="conf/zlex.keystore"
keystorePass="123456"
/>
注意把密钥库放进来
端口可以改成443(https默认端口,就可以不用指定端口访问了,此时的访问url为:https://www.zlex.org:8443)
4.添加jsp页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="java.util.Enumeration" %>>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>zlex.org</title>
</head>
<body>
<p>request属性信息</p>
<pre>
<%
for (Enumeration en = request.getAttributeNames();en.hasMoreElements();){
String name=(String)en.nextElement();
out.println(name);
out.println(" = "+request.getAttribute(name));
out.println();
}
%>
</pre>
</body>
</html>
5.配置web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:web="http://xmlns.jcp.org/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd
http://xmlns.jcp.org/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_9" version="2.4">
<display-name>ssl</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
在tomcat下创建ssl目录,将index,jsp放进来,并创建WEB-INF及文件夹下的web.xml(如5),访问页面:
request属性信息
javax.servlet.request.ssl_session = 54d41ab802da0207344a29822d0e7f5a9ce230a366278cc453977d1c8ffb01cd javax.servlet.request.key_size = 256 javax.servlet.request.ssl_session_mgr = org.apache.tomcat.util.net.jsse.JSSESupport@7a5cae00 javax.servlet.request.cipher_suite = TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 javax.servlet.request.ssl_session_id = 54d41ab802da0207344a29822d0e7f5a9ce230a366278cc453977d1c8ffb01cd
至此服务器的安全协议的单向验证已经实现,下面我们从客户端用代码访问。
三、客服端访问服务:
我们的目标是:对已经有的网络连接conn绑定上https协议,即为HttpsURLConnection配置SSLSocketFactory
Class SSLContext
- java.lang.Object
-
- javax.net.ssl.SSLContext
-
getSocketFactory
public final SSLSocketFactory getSocketFactory()
Returns aSocketFactory
object for this context.-
Returns:
-
the
SocketFactory
object
Throws:
-
IllegalStateException
- if the SSLContextImpl requires initialization and theinit()
has not been called
-
the
Class SSLContext
- java.lang.Object
-
- javax.net.ssl.SSLContext
void | init(KeyManager[] km, TrustManager[] tm, SecureRandom random)
Initializes this context.
|
KeyManager可有KeyManagerFactory(密钥库管理工厂)产生,
TrustManager可有TrustManagerFactory(信任库管理工厂)产生;
两个工厂均直接继承于Object,并列关系,初始化时均需要KeyStore(密钥库)对象。密钥库管理工厂还额外需要密码
public abstract class HttpsCoder {
private static final String PROCOTOL = "TLS";
private static KeyStore getKeyStore(String keyStorePath,String password) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException{
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream is = new FileInputStream(keyStorePath);
ks.load(is, password.toCharArray());
is.close();
return ks;
}
private static SSLSocketFactory getSSLSocketFactory(String password,String keyStorePath,String trustStorePath) throws NoSuchAlgorithmException, KeyStoreException, CertificateException, IOException, UnrecoverableKeyException, KeyManagementException{
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
KeyStore keyStore = getKeyStore(keyStorePath,password);
keyManagerFactory.init(keyStore, password.toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore trustStore = getKeyStore(trustStorePath,password);
trustManagerFactory.init(trustStore);
SSLContext ctx = SSLContext.getInstance(PROCOTOL);
ctx.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());
return ctx.getSocketFactory();
}
public static void configSSLSocketFactory(HttpsURLConnection conn,String password,String keyStorePath,String trustStorePath) throws UnrecoverableKeyException, KeyManagementException, NoSuchAlgorithmException, KeyStoreException, CertificateException, IOException{
SSLSocketFactory sslSocketFactory = getSSLSocketFactory(password,keyStorePath,trustStorePath);
conn.setSSLSocketFactory(sslSocketFactory);
}
}
SSL:安全套接字层,位于TCP/IP模型传输层,作为网络通信中提供安全及数据完整性的一种安全协议
TLS:传输层安全,基于SSL上的通用化协议,也位于传输层,作为SSL的继承者,提供安全和数据完整性的安全协议
四、客户端测试用例:
public class HttpsCoderTest extends TestCase {
private String password = "123456";
private String keyStorePath="F:/Java/jdk1.8.0/bin/zlex.keystore";
private String trustStorePath="F:/Java/jdk1.8.0/bin/zlex.keystore";
private String httpsUrl = "https://www.zlex.org:8443/SSL/";
@Test
public void test() throws IOException, UnrecoverableKeyException, KeyManagementException, NoSuchAlgorithmException, KeyStoreException, CertificateException{
URL url = new URL(httpsUrl);
HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
conn.setDoInput(true);
HttpsCoder.configSSLSocketFactory(conn, password, keyStorePath, trustStorePath);
int length = conn.getContentLength();
System.err.println("i am out here"+length);
byte[] data = null;
if(length!=-1){
System.err.println("i am in here");
DataInputStream dis = new DataInputStream(conn.getInputStream());
data = new byte[length];
dis.readFully(data);//把输入流数据输入到data
dis.close();
System.err.println(new String(data));
}
conn.disconnect();
assertNotNull(data);
}
}
客户端建立连接的步骤:
url.openConnection()-> DataInputStream->readFully
在打开连接后,更改为https