[JAVA加解密]安全协议-单向认证

来源:互联网 发布:模拟经营 知乎 编辑:程序博客网 时间:2024/06/02 14:40

一、用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 = 54d41ab802da0207344a29822d0e7f5a9ce230a366278cc453977d1c8ffb01cdjavax.servlet.request.key_size = 256javax.servlet.request.ssl_session_mgr = org.apache.tomcat.util.net.jsse.JSSESupport@7a5cae00javax.servlet.request.cipher_suite = TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384javax.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 a SocketFactory object for this context.
    Returns:
    the SocketFactory object
    Throws:
    IllegalStateException - if the SSLContextImpl requires initialization and the init() has not been called
我们通过SSLContext来获得SSLSocketFactory对象,而产生SSLContext除了指定协议外,还需要初始化一系列参数:

Class SSLContext

  • java.lang.Object
    • javax.net.ssl.SSLContext

voidinit(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/";@Testpublic 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);//把输入流数据输入到datadis.close();System.err.println(new String(data));}conn.disconnect();assertNotNull(data);}}

客户端建立连接的步骤:

url.openConnection()-> DataInputStream->readFully

在打开连接后,更改为https


0 0