HTTPS 客户端发送请求(二)

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();
		}
	}
}
时间: 2024-08-08 22:08:51

HTTPS 客户端发送请求(二)的相关文章

HTTPS 客户端发送请求(一)

HTTPS 发送请求(一) 摘 要 JSSE是一个SSL和TLS的纯Java实现,通过JSSE可以很容易地编程实现对HTTPS站点的访问.但是,如果该站点的证书未经权威机构的验证,JSSE将拒绝信任该证书从而不能访问HTTPS站点.本文在简要介绍JSSE的基础上提出了两种解决该问题的方法. 引言 过去的十几年,网络上已经积累了大量的Web应用.如今,无论是整合原有的Web应用系统,还是进行新的Web开发,都要求通过编程来访问某些Web页面.传统的方法是使用Socket接口,但现在很多开发平台或工

HTTPS 客户端发送请求(三)

HTTPS 请求不忽略证书方式 加载原始keystore方式 在第一章中我们生成了一张证书,并放在了c://tomcat.keystore下,我们就使用这个证书来完成请求 package httpsClient; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.net.Ma

zookeeper源码分析之一客户端发送请求流程

znode 可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个功能是zookeeper对于应用最重要的特性,通过这个特性可以实现的功能包括配置的集中管理,集群管理,分布式锁等等. 知识准备: zookeeper定义的状态有: Unknown (-1),Disconnected (0),NoSyncConnected (1),SyncConnected (3),AuthFailed (4),ConnectedReadOnly (5),Sasl

java接受从安卓客户端发送过来的get请求时,出现乱码的解决思路及方法

今天下午遇到了这样一个感觉很常见的问题,但是度娘了N遍,却始终找不到有效的解决方法,于是乎,在苦求他人无果的情况下,研究出了一种简单有效的方法,具体实现思路如下: (1).让安卓客户端在发送get请求之前,先通过String str = URLEncode.encode(str, "utf-8");指定编码格式为UTF-8:这样安卓客户端在给服务器端发送请求时就会以UTF-8的格式发送. (2).服务器端通过request.getParameter("str");方

Hessian客户端向服务端发送请求头

Hessian客户端向服务端发送数据 场景:项目日志Token处理,即用户发送一个请求时生成一个日志Token,该Token从各个服务之间传递,并使用该Token记录日志,直至请求结束.可以根据该Token定位所有日志. 问题:由于目前项目使用Hessian协议,所有Token必须使用Hessian传递.查阅相关资料,发现可以请求头传递数据. 解决方法:定义与线程相关的请求头上下文,在客户端发送请求之前,增加请求头.服务端获取请求时,从请求中解决请求头,并放入请求头上下文中,供服务端使用. 实现

关于ASP.NET Web API 客户端的请求报文中添加 Authorization

当你使用客户端发送请求 Web API 的时候,因为API 有验证,所以你的请求报文中必须有”Authorization“,那么就需要手动添加了! HttpClient client = new HttpClient(); client.BaseAddress = new Uri("http://localhost:9014/"); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(&

脱离微信客户端发送微信消息(二)

Python版本:使用微信API发送微信消息 本文代码借用朋友编写的成品代码,使用Python3编写,配合上一篇文章:<脱离微信客户端发送微信消息(一)>经过试验完全可以发送微信消息. 文件:BaseData.py Python3代码: 1 # -*- coding: utf-8 -*- 2 3 corpid="XXXXXXX" # 设置-权限设置-部门-查看CorpID 4 corpsecret="YYYYYYYYYY" # 设置-权限设置-部门-查看

spring,spring mvc ,mina,接收http请求然后调用mina给客户端发送信息

这里比较复杂的莫过于spring的配置了那就先上配置applicationContext.xml mina的配置在最下面 <spring  -- mina >这个 之上的 配置有velocity和memcache还有springjdbc,自动装配,json对象支持(注解@ResponseBody), 切面事务管理 ,  当然这些大家能用的上的 拿走  用不上删掉(跟没说一样) <?xml version="1.0" encoding="UTF-8"

TCP Incast 问题TCP INCAST解决思路 应用场景:在集群文件系统内,客户端应用请求某个逻辑数据块(通常情况下一个读数据块大小是1MB),该数据块以条带化方式分别存储在几个存储服务器上,即采用更小的数据片存储(32KB,256KB等),这种小数据片称为服务器请求单元(SRU)。只有当客户端接收到所有的服务器返回的其所请求数据块的SRU后才继续发送出下一个数据块请求,即客户端同时向

TCP INCAST解决思路 应用场景:在集群文件系统内,客户端应用请求某个逻辑数据块(通常情况下一个读数据块大小是1MB),该数据块以条带化方式分别存储在几个存储服务器上,即采用更小的数据片存储(32KB,256KB等),这种小数据片称为服务器请求单元(SRU).只有当客户端接收到所有的服务器返回的其所请求数据块的SRU后才继续发送出下一个数据块请求,即客户端同时向多个存储服务器发起并发TCP请求,且所有服务器同时向客户端发送SRU. 出现的问题: 1)         这种多对一的服务器向客