https 完整web开发
Tomcat 6.0 配置
1、生成安全访问的证书。
命令行下执行:keytool -genkey -alias tomcat -keyalg RSA -keystore c:\tomcat.keystore
然后按提示输入一些密码等信息:
输入keystore密码:
再次输入新密码:
您的名字与姓氏是什么?
[Unknown]: tomcat
您的组织单位名称是什么?
[Unknown]: tomcat
您的组织名称是什么?
[Unknown]: tomcat
您所在的城市或区域名称是什么?
[Unknown]: bj
您所在的州或省份名称是什么?
[Unknown]: bj
该单位的两字母国家代码是什么
[Unknown]: cn
CN=tomcat, OU=tomcat, O=tomcat, L=bj, ST=bj, C=cn 正确吗?
[否]: y
输入<tomcat>的主密码
(如果和 keystore 密码相同,按回车):
输入完成后,会在C盘下生成tomcat.keystore文件,这个文件的位置不做要求。
注:上述命令中的蓝色部分可以不输入,这样会默认生成一个.keystore的证书文件。
2、配置tomcat,使其支持https连接。
打开tomcat目录下conf/server.xml文件,将之前的连接部分注释,找到以下节点:
<!-- Define a SSL HTTP/1.1 Connector on port 8443 This connector uses the JSSE configuration, when using APR, the connector should be using the OpenSSL style configuration described in the APR documentation --> <!-- <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" /> -->
将<connectore节点的注释去掉,8443修改为你要使用的端口。节点中添加两个属性:keystoreFile="C:/tomcat.keystore" keystorePass="123456"
其中,keystoreFile指的是你第一步生成的证书文件位置,keystorePass是你在生成证书时所输入的密码。
通过以上两步操作,基本上就可以使用https访问tomcat连接了,不过我在使用tomcat6配置的时候,启动tomcat报错:
2011-9-8 10:11:20 org.apache.catalina.core.AprLifecycleListener init 信息: Loaded APR based Apache Tomcat Native library 1.1.20. 2011-9-8 10:11:20 org.apache.catalina.core.AprLifecycleListener init 信息: APR capabilities: IPv6 [true], sendfile [true], accept filters [false], random [true]. 2011-9-8 10:11:20 org.apache.catalina.startup.SetAllPropertiesRule begin 警告: [SetAllPropertiesRule]{Server/Service/Connector} Setting property 'keystoreFile' to 'C:\tomcat.keystore' did not find a matching property. 2011-9-8 10:11:20 org.apache.catalina.startup.SetAllPropertiesRule begin 警告: [SetAllPropertiesRule]{Server/Service/Connector} Setting property 'keystorePass' to 'mvtech' did not find a matching property. 2011-9-8 10:11:20 org.apache.catalina.startup.SetAllPropertiesRule begin 警告: [SetAllPropertiesRule]{Server/Service/Connector} Setting property 'clientAuth' to 'false' did not find a matching property. 2011-9-8 10:11:20 org.apache.coyote.http11.Http11AprProtocol init 严重: Error initializing endpoint java.lang.Exception: No Certificate file specified or invalid file format at org.apache.tomcat.jni.SSLContext.setCertificate(Native Method) at org.apache.tomcat.util.net.AprEndpoint.init(AprEndpoint.java:720) at org.apache.coyote.http11.Http11AprProtocol.init(Http11AprProtocol.java:107) at org.apache.catalina.connector.Connector.initialize(Connector.java:1014) at org.apache.catalina.core.StandardService.initialize(StandardService.java:680) at org.apache.catalina.core.StandardServer.initialize(StandardServer.java:795) at org.apache.catalina.startup.Catalina.load(Catalina.java:524) at org.apache.catalina.startup.Catalina.load(Catalina.java:548) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:261) at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413) 2011-9-8 10:11:20 org.apache.catalina.startup.Catalina load 严重: Catalina.start LifecycleException: Protocol handler initialization failed: java.lang.Exception: No Certificate file specified or invalid file format at org.apache.catalina.connector.Connector.initialize(Connector.java:1016) at org.apache.catalina.core.StandardService.initialize(StandardService.java:680) at org.apache.catalina.core.StandardServer.initialize(StandardServer.java:795) at org.apache.catalina.startup.Catalina.load(Catalina.java:524) at org.apache.catalina.startup.Catalina.load(Catalina.java:548) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:261) at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:413)
在网上看到有朋友的解决办法,是找到tomcat的bin目录下有个tcnative-1.dll文件,然后将其删除,重新启动tomcat一切正常。
至此,可以通过https方式访问你的应用了。
但是此时如果你用Http方式访问应用,页面会返回乱码或者空,但是也不报错,为了更好的使用,我们需要在客户输入http时能够自动跳转到Https方式,这就需要第三步,让你的应用强制使用https方式访问了。
打开tomcat下conf/web.xml文件,在最下方的<welcome-file-list>节点之后添加:
<login-config> <!-- Authorization setting for SSL --> <auth-method>CLIENT-CERT</auth-method> <realm-name>Client Cert Users-only Area</realm-name> </login-config> <security-constraint> <!-- Authorization setting for SSL --> <web-resource-collection > <web-resource-name >SSL</web-resource-name> <url-pattern>/*</url-pattern> </web-resource-collection> <user-data-constraint> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint> </security-constraint>
配置完成。。。。。。
源码解析
服务端
服务端的构建比较简单,一个action搞定
package com.httpsDemo.action; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class PostHttpsAction extends HttpServlet { /** * */ private static final long serialVersionUID = 1L; @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("post success ..."); InputStream in = req.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(in)); String result = br.readLine(); System.out.println(result); resp.getOutputStream().write(result.getBytes("utf-8")); return; } }
注意web.xml配置.
客户端
工具类一个搞定
package com.saygou.weixin; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSession; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; public class HttpsUtil { private static class TrustAnyTrustManager implements X509TrustManager { public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[] {}; } } private static class TrustAnyHostnameVerifier implements HostnameVerifier { public boolean verify(String hostname, SSLSession session) { return true; } } /** * post方式请求服务器(https协议) * * @param url * 请求地址 * @param content * 参数 * @param charset * 编码 * @return * @throws NoSuchAlgorithmException * @throws KeyManagementException * @throws IOException */ public static byte[] post(String url, String content, String charset) throws NoSuchAlgorithmException, Exception, IOException { SSLContext sc = SSLContext.getInstance("SSL","SunJSSE"); sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom()); URL console = new URL(url); HttpsURLConnection conn = (HttpsURLConnection) console.openConnection(); conn.setSSLSocketFactory(sc.getSocketFactory()); //设置默认证书--如果没有这句将会报错,错误信息↓↓↓ //java.io.IOException: HTTPS hostname wrong: should be <127.0.0.1> conn.setHostnameVerifier(new TrustAnyHostnameVerifier()); conn.setDoOutput(true); conn.connect(); DataOutputStream out = new DataOutputStream(conn.getOutputStream()); out.write(content.getBytes(charset)); // 刷新、关闭 out.flush(); out.close(); InputStream is = conn.getInputStream(); if (is != null) { ByteArrayOutputStream outStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len = 0; while ((len = is.read(buffer)) != -1) { outStream.write(buffer, 0, len); } is.close(); return outStream.toByteArray(); } return null; } /** * 测试 * @param args * @throws Exception */ public static void main(String[] args) throws Exception { try { byte[] b = HttpsUtil.post("https://127.0.0.1:8443/httpsDemo/hs", "{'name':'Jack'}", "utf-8"); System.out.println(new String(b)); } catch (KeyManagementException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchAlgorithmException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }