java访问Https服务的客户端示例
关于证书
1、每个人都可以使用一些证书生成工具为自己的https站点生成证书(比如JDK的keytool),大家称它为“自签名证书”,但是自己生成的证书是不被浏览器承认的,所以浏览器会报安全提示,要求你手动安装证书,提示风险,是否继续等。只有通过权威的CA机构付费获得的证书才能被浏览器承认。
2、证书(无客户端服务端之分)保存着IP信息、证书过期时间、证书所有者地址信息等。
双向认证
1、先决条件是有两个或两个以上的证书,一个是服务端证书,另一个或多个是客户端证书。
2、服务端保存着客户端的证书并信任该证书,客户端保存着服务端的证书并信任该证书。这样,在证书验证成功的情况下即可完成请求响应。
3、双向认证安全性更高。
单向认证
1、客户端保存着服务端的证书并信任该证书即可。
2、https一般是单向认证,这样可以让绝大部分人可以访问你的站点。
使用示例代码:
public interface PCIHttpClient { /** 请求头信息:Content-Type **/
public static final String CONTENT_TYPE = "Content-Type";
/** 请求头信息:User-Agent **/
public static final String USER_AGENT = "User-Agent";
/** 默认的内容类型 **/
public static final String DEFAULT_CONTENTTYPE = "application/x-www-form-urlencoded;charset=UTF-8";
/** 默认的用户代理(浏览器类型) **/
public static final String DEFAULT_USERAGENT = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; SLCC1; .NET CLR 2.0.50727; .NET CLR 3.0.04506; InfoPath.1; .NET CLR 1.1.4322; CIBA)";
/** 默认的读取超时时间(单位毫秒) **/
public static final int DEFAULT_TIMEOUT = 180000;
/** 默认的连接超时时间(单位毫秒) **/
public static final int DEFAULT_CONNECTION_TIMEOUT = 60000; /**
* 发送GET方式请求数据,并接收响应数据
*
* @param url 请求地址
* @param timeout 超时时间(单位毫秒)
* @return 响应内容(字符串)
* @throws IOException
*/
public String sendGetAndResponseAsString(String url,
int timeout) throws IOException; /**
* 发送GET方式请求数据,并接收响应数据
*
* @param url 请求地址
* @param headers 请求头信息
* @param timeout 超时时间(单位毫秒)
* @return 响应内容(字符串)
* @throws IOException
*/
public String sendGetAndResponseAsString(String url,
Map<String, String> headers, int timeout) throws IOException; /**
* 发送GET方式请求数据,并接收响应数据
*
* @param url 请求地址
* @param headers 请求头信息
* @param params 请求参数
* @param charsetName 字符编码
* @param timeout 超时时间(单位毫秒)
* @return 响应内容(字符串)
* @throws IOException
*/
public String sendGetAndResponseAsString(String url,
Map<String, String> headers, Map<String, String> params,
String charsetName, int timeout) throws IOException; /**
* 发送GET方式请求数据,并接收响应数据
*
* @param url 请求地址
* @param timeout 超时时间(单位毫秒)
* @return 响应内容(字节数组)
* @throws IOException
*/
public byte[] sendGetAndResponseAsByteArray(String url,
int timeout) throws IOException; /**
* 发送GET方式请求数据,并接收响应数据
*
* @param url 请求地址
* @param headers 请求头信息
* @param timeout 超时时间(单位毫秒)
* @return 响应内容(字节数组)
* @throws IOException
*/
public byte[] sendGetAndResponseAsByteArray(String url,
Map<String, String> headers, int timeout) throws IOException; /**
* 发送GET方式请求数据,并接收响应数据
*
* @param url 请求地址
* @param headers 请求头信息
* @param params 请求参数
* @param charsetName 字符编码
* @param timeout 超时时间(单位毫秒)
* @return 响应内容(字节数组)
* @throws IOException
*/
public byte[] sendGetAndResponseAsByteArray(String url,
Map<String, String> headers, Map<String, String> params,
String charsetName, int timeout) throws IOException; /**
* 发送GET方式请求数据,并接收响应数据
*
* @param url 请求地址
* @param headers 请求头信息
* @param params 请求参数
* @param charsetName 字符编码
* @param timeout 超时时间(单位毫秒)
* @return 响应内容(输入流)
* @throws IOException
*/
public InputStream sendGetAndResponseAsStream(String url,
Map<String, String> headers, Map<String, String> params,
String charsetName, int timeout) throws IOException; /**
* 发送GET方式请求
*
* @param url 请求地址
* @param headers 请求头信息
* @param params 请求参数
* @param charsetName 字符编码
* @param timeout 超时时间(单位毫秒)
* @param output 响应内容(输出流)
* @throws IOException
*/
public void sendGet(String url, Map<String, String> headers,
Map<String, String> params, String charsetName, int timeout,
OutputStream output) throws IOException; /**
* 发送POST方式请求数据,并接收响应数据
*
* @param url 请求地址
* @param params 请求参数
* @param charsetName 字符编码
* @param timeout 超时时间(单位毫秒)
* @return 响应内容(字符串)
* @throws IOException
*/
public String sendPostAndResponseAsString(String url,
Map<String, String> params, String charsetName, int timeout) throws IOException; /**
* 发送POST方式请求数据,并接收响应数据
*
* @param url 请求地址
* @param headers 请求头信息
* @param params 请求参数
* @param timeout 超时时间(单位毫秒)
* @param charsetName 字符编码
* @return 响应内容(字符串)
* @throws IOException
*/
public String sendPostAndResponseAsString(String url,
Map<String, String> headers, Map<String, String> params,
int timeout, String charsetName) throws IOException; /**
* 发送POST方式请求数据,并接收响应数据
*
* @param url 请求地址
* @param headers 请求头信息
* @param stringOrStream 请求体内容(字符串或者输入流)
* @param charsetName 字符编码
* @param timeout 超时时间(单位毫秒)
* @return 响应内容(字符串)
* @throws IOException
*/
public String sendPostAndResponseAsString(String url,
Map<String, String> headers, Object stringOrStream,
String charsetName, int timeout) throws IOException; /**
* 发送POST方式请求数据,并接收响应数据
*
* @param url 请求地址
* @param headers 请求头信息
* @param params 请求参数
* @param stringOrStream 请求体内容(字符串或者输入流)
* @param charsetName 字符编码
* @param timeout 超时时间(单位毫秒)
* @return 响应内容(字符串)
* @throws IOException
*/
public String sendPostAndResponseAsString(String url,
Map<String, String> headers, Map<String, String> params,
Object stringOrStream, String charsetName, int timeout) throws IOException; /**
* 发送POST方式请求数据,并接收响应数据
*
* @param url 请求地址
* @param params 请求参数
* @param charsetName 字符编码
* @param timeout 超时时间(单位毫秒)
* @return 响应内容(字节数组)
* @throws IOException
*/
public byte[] sendPostAndResponseAsByteArray(String url,
Map<String, String> params, String charsetName, int timeout) throws IOException; /**
* 发送POST方式请求数据,并接收响应数据
*
* @param url 请求地址
* @param headers 请求头信息
* @param params 请求参数
* @param timeout 超时时间(单位毫秒)
* @param charsetName 字符编码
* @return 响应内容(字节数组)
* @throws IOException
*/
public byte[] sendPostAndResponseAsByteArray(String url,
Map<String, String> headers, Map<String, String> params,
int timeout, String charsetName) throws IOException; /**
* 发送POST方式请求数据,并接收响应数据
*
* @param url 请求地址
* @param headers 请求头信息
* @param stringOrStream 请求体内容(字符串或者输入流)
* @param charsetName 字符编码
* @param timeout 超时时间(单位毫秒)
* @return 响应内容(字节数组)
* @throws IOException
*/
public byte[] sendPostAndResponseAsByteArray(String url,
Map<String, String> headers, Object stringOrStream,
String charsetName, int timeout) throws IOException; /**
* 发送POST方式请求数据,并接收响应数据
*
* @param url 请求地址
* @param headers 请求头信息
* @param params 请求参数
* @param stringOrStream 请求体内容(字符串或者输入流)
* @param charsetName 字符编码
* @param timeout 超时时间(单位毫秒)
* @return 响应内容(字节数组)
* @throws IOException
*/
public byte[] sendPostAndResponseAsByteArray(String url,
Map<String, String> headers, Map<String, String> params,
Object stringOrStream, String charsetName, int timeout) throws IOException; /**
* 发送POST方式请求数据,并接收响应数据
*
* @param url 请求地址
* @param headers 请求头信息
* @param params 请求参数
* @param stringOrStream 请求体内容(字符串或者输入流)
* @param charsetName 字符编码
* @param timeout 超时时间(单位毫秒)
* @return 响应内容(输入流)
* @throws IOException
*/
public InputStream sendPostAndResponseAsStream(String url,
Map<String, String> headers, Map<String, String> params,
Object stringOrStream, String charsetName, int timeout) throws IOException; /**
* 发送POST方式请求
*
* @param url 请求地址
* @param headers 请求头信息
* @param params 请求参数
* @param stringOrStream 请求体内容(字符串或者输入流)
* @param charsetName 字符编码
* @param timeout 超时时间(单位毫秒)
* @param output 响应内容(输出流)
* @throws IOException
*/
public void sendPost(String url, Map<String, String> headers,
Map<String, String> params, Object stringOrStream,
String charsetName, int timeout, OutputStream output) throws IOException; /**
* 发送GET方式请求
*
* @param url 请求地址
* @param headers 请求头信息
* @param params 请求参数
* @param charsetName 字符编码
* @param timeout 超时时间(单位毫秒)
* @return
* @throws IOException
*
* @since 2.0.0
*/
public PCIHttpResponse sendGet(String url, Map<String, String> headers,
Map<String, String> params, String charsetName, int timeout) throws IOException; /**
* 发送POST方式请求
*
* @param url 请求地址
* @param headers 请求头信息
* @param params 请求参数
* @param stringOrStream 请求体内容(字符串或者输入流)
* @param charsetName 字符编码
* @param timeout 超时时间(单位毫秒)
* @return
* @throws IOException
*
* @since 2.0.0
*/
public PCIHttpResponse sendPost(String url, Map<String, String> headers,
Map<String, String> params, Object stringOrStream,
String charsetName, int timeout) throws IOException; }
public class CustomConstants { /** 字符编码:UTF-8 */
public static final String CHARSET_UTF8 = "UTF-8"; }
public class CustomStringUtils { private static LogUtils logger = new LogUtils(CustomStringUtils.class); /**
* 长度不足,左补字符
* @param str
* @param ch
* @param len
* @return
*/
public static String leftFill(String str, char ch, int len) {
if (str == null) {
str = "";
}
while (str.length() < len) {
str = ch + str;
}
return str;
} /**
* 长度不足,右补字符
* @param str
* @param ch
* @param len
* @return
*/
public static String rightFill(String str, char ch, int len) {
if (str == null) {
str = "";
}
while (str.length() < len) {
str = str + ch;
}
return str;
} /**
* 拼接字符串
* @param objs
* @return
*/
public static String append(Object... objs) {
if (objs == null || objs.length == 0) {
return "";
}
StringBuffer buffer = new StringBuffer();
for (Object obj : objs) {
buffer.append(obj);
}
return buffer.toString();
} /**
* 如果字符串为空,则返回空字符
* @param str
* @return
*/
public static String nullToBlank(String str) {
return str == null ? "" : str;
} /**
* 将map转化成字符串
* @param map
* @return 格式:key1=value1&key2=value2...
*/
public static String convertMapToString(Map<String, String> map) {
if (map == null || map.isEmpty()) {
return null;
}
StringBuffer buffer = new StringBuffer();
boolean first = true;
for (Map.Entry<String, String> entry : map.entrySet()) {
if (first) {
buffer.append(entry.getKey()).append("=").append(entry.getValue());
first = false;
} else {
buffer.append("&").append(entry.getKey()).append("=").append(entry.getValue());
}
}
return buffer.toString();
} /**
* 将map转化成字符串,并对map.value进行URL编码
* @param map
* @param encoding
* @return 格式:key1=value1&key2=value2...
*/
public static String convertMapToString(Map<String, String> map, String encoding) {
if (map == null || map.isEmpty()) {
return null;
}
StringBuffer buffer = new StringBuffer();
boolean first = true;
for (Map.Entry<String, String> entry : map.entrySet()) {
if (first) {
buffer.append(entry.getKey()).append("=").append(urlEncode(entry.getValue(), encoding));
first = false;
} else {
buffer.append("&").append(entry.getKey()).append("=").append(urlEncode(entry.getValue(), encoding));
}
}
return buffer.toString();
} /**
* 将map转化成字符串(当参数值为null时,则忽略该参数)
* @param map
* @return 格式:key1=value1&key2=value2...
*/
public static String convertMapToStringIgnoreNull(Map<String, String> map) {
if (map == null || map.isEmpty()) {
return null;
}
StringBuffer buffer = new StringBuffer();
boolean first = true;
for (Map.Entry<String, String> entry : map.entrySet()) {
if (entry.getValue() == null) {
continue;
}
if (first) {
buffer.append(entry.getKey()).append("=").append(entry.getValue());
first = false;
} else {
buffer.append("&").append(entry.getKey()).append("=").append(entry.getValue());
}
}
return buffer.toString();
} /**
* 将map转化成字符串,并对map.value进行URL编码(当参数值为null时,则忽略该参数)
* @param map
* @param encoding
* @return 格式:key1=value1&key2=value2...
*/
public static String convertMapToStringIgnoreNull(Map<String, String> map, String encoding) {
if (map == null || map.isEmpty()) {
return null;
}
StringBuffer buffer = new StringBuffer();
boolean first = true;
for (Map.Entry<String, String> entry : map.entrySet()) {
if (entry.getValue() == null) {
continue;
}
if (first) {
buffer.append(entry.getKey()).append("=").append(urlEncode(entry.getValue(), encoding));
first = false;
} else {
buffer.append("&").append(entry.getKey()).append("=").append(urlEncode(entry.getValue(), encoding));
}
}
return buffer.toString();
} /**
* 对字符串进行URL编码
* @param str
* @param encoding
* @return
*/
public static String urlEncode(String str, String encoding) {
if (str == null || "".equals(str)) {
return str;
}
try {
return URLEncoder.encode(str, encoding);
} catch (UnsupportedEncodingException e) {
logger.error(append("URL encode string error. str=", str, ", encoding=", encoding), e);
return str;
}
} /**
* 对字符串进行URL解码
* @param str
* @param encoding
* @return
*/
public static String urlDecode(String str, String encoding) {
if (str == null || "".equals(str)) {
return str;
}
try {
return URLDecoder.decode(str, encoding);
} catch (UnsupportedEncodingException e) {
logger.error(append("URL decode string error. str=", str, ", encoding=", encoding), e);
return str;
}
} /**
* 字符串的字节长度是否超出边界值
* @param str 字符串
* @param bounds 边界值
* @param charsetName 字符编码
* @return
*/
public static boolean bytesLengthOutOfBounds(
String str, int bounds, String charsetName) {
if (bounds < 0 || str == null || "".equals(str)) {
return false;
}
try {
int bytesLen = str.getBytes(charsetName).length;
return bytesLen > bounds;
} catch (UnsupportedEncodingException e) {
logger.error(append("Check bytes length out of bounds error. str=",
str, ", charsetName=", charsetName), e);
}
return false;
} /**
* @Title: generate
* @Description: 随机生成指定长度的16进制的字符串
* @since: 0.0.1
* @param len 字符串长度
* @return
*/
public static String generateRandomHex(int len){ if (len < 1) {
return null;
} StringBuffer sb = new StringBuffer();
Random random = new Random(); for (int i = 0; i < len; i++) {
sb.append(Integer.toHexString(random.nextInt(16)));
} return sb.toString().toUpperCase();
} /**
* @Title: generateConformOddCheckHex
* @Description: 生成符合奇校验的字符串
* @since: 0.0.1
* @param len 字节长度
* @return
*/
public static String generateConformOddCheckHex(int len) { byte[] bytes = new byte[len];
for (int i = 0; i < len; i++) {
Random random = new Random();
int randomInt = random.nextInt(255);
String binaryString = Integer.toBinaryString(randomInt);
boolean oddCheck = isConformOddCheck(binaryString);
if (!oddCheck) {
randomInt ^= 1;
}
// System.err.println(Integer.toBinaryString(randomInt));
byte b = (byte) randomInt;
bytes[i] = b;
}
String hexString = CommonUtils.byte2hexString(bytes);
return hexString;
} /**
* @Title: oddCheck
* @Description: 检验是否符合奇校验
* @since: 0.0.1
* @param binaryString
* @return
*/
private static boolean isConformOddCheck(String binaryString) {
int sum = 0;
char[] charArray = binaryString.toCharArray();
for(char c : charArray){
if (c == '1') {
sum ++;
}
}
if (sum%2 == 1) {
return true;
}
return false;
} }
public class IOUtils { private static LogUtils logger = new LogUtils(IOUtils.class); /** 默认的缓冲区大小 **/
private static final int DEFAULT_BUFFER_SIZE = 4096; /**
* 将字节输入流转换成字节数组
* @param input
* @return
* @throws IOException
*/
public static byte[] toByteArray(InputStream input) throws IOException {
ByteArrayOutputStream output = null;
try {
output = new ByteArrayOutputStream();
copy(input, output);
return output.toByteArray();
} finally {
closeQuietly(output);
}
} /**
* 将字符输入流转换成字节数组
* @param reader
* @return
* @throws IOException
*/
public static byte[] toByteArray(Reader reader) throws IOException {
ByteArrayOutputStream output = null;
try {
output = new ByteArrayOutputStream();
copy(reader, output);
return output.toByteArray();
} finally {
closeQuietly(output);
}
} /**
* 将字符输入流转换成字节数组
* @param reader
* @param encoding
* @return
* @throws IOException
*/
public static byte[] toByteArray(Reader reader, String encoding) throws IOException {
ByteArrayOutputStream output = null;
try {
output = new ByteArrayOutputStream();
copy(reader, output, encoding);
return output.toByteArray();
} finally {
closeQuietly(output);
}
} /**
* 将字节输入流转换成字符串
* @param input
* @return
* @throws IOException
*/
public static String toString(InputStream input) throws IOException {
StringWriter writer = null;
try {
writer = new StringWriter();
copy(input, writer);
return writer.toString();
} finally {
closeQuietly(writer);
}
} /**
* 将字节输入流转换成字符串
* @param input
* @param encoding
* @return
* @throws IOException
*/
public static String toString(InputStream input, String encoding) throws IOException {
StringWriter writer = null;
try {
writer = new StringWriter();
copy(input, writer, encoding);
return writer.toString();
} finally {
closeQuietly(writer);
}
} /**
* 将字符输入流转换成字符串
* @param reader
* @return
* @throws IOException
*/
public static String toString(Reader reader) throws IOException {
StringWriter writer = null;
try {
writer = new StringWriter();
copy(reader, writer);
return writer.toString();
} finally {
closeQuietly(writer);
}
} /**
* 按行读取字节输入流
* @param input
* @return
* @throws IOException
*/
public static List<String> readLines(InputStream input) throws IOException {
// InputStreamReader reader = new InputStreamReader(input);
// return readLines(reader);
InputStreamReader reader = null;
try {
reader = new InputStreamReader(input);
return readLines(reader);
} finally {
closeQuietly(reader);
}
} /**
* 按行读取字节输入流
* @param input
* @param encoding
* @return
* @throws IOException
*/
public static List<String> readLines(InputStream input, String encoding) throws IOException {
// if (encoding == null) {
// return readLines(input);
// }
// InputStreamReader reader = new InputStreamReader(input, encoding);
// return readLines(reader);
if (encoding == null) {
return readLines(input);
}
InputStreamReader reader = null;
try {
reader = new InputStreamReader(input, encoding);
return readLines(reader);
} finally {
closeQuietly(reader);
}
} /**
* 按行读取字符输入流
* @param reader
* @return
* @throws IOException
*/
public static List<String> readLines(Reader reader) throws IOException {
// BufferedReader br = new BufferedReader(reader);
// List<String> lines = new ArrayList<String>();
// String line = br.readLine();
// while (line != null) {
// lines.add(line);
// line = br.readLine();
// }
// return lines;
BufferedReader br = null;
try {
br = new BufferedReader(reader);
List<String> lines = new ArrayList<String>();
String line = br.readLine();
while (line != null) {
lines.add(line);
line = br.readLine();
}
return lines;
} finally {
closeQuietly(br);
}
} /**
* 阻塞地读取字节输入流
* @param input
* @param buffer
* @param off
* @param length
* @throws IOException
*/
public static void read(InputStream input,
byte[] buffer, int off, int length) throws IOException {
while (off < length) {
off = off + input.read(buffer, off, length - off);
if (off < 0) {
throw new IOException("读取时出错[readLen=" + off + "]");
}
}
} /**
* 将字节输入流拷贝到字符输出流
* @param input
* @param writer
* @throws IOException
*/
public static void copy(InputStream input, Writer writer) throws IOException {
// InputStreamReader reader = new InputStreamReader(input);
// copy(reader, writer);
InputStreamReader reader = null;
try {
reader = new InputStreamReader(input);
copy(reader, writer);
} finally {
closeQuietly(reader);
}
} /**
* 将字节输入流拷贝到字符输出流
* @param input
* @param writer
* @param encoding
* @throws IOException
*/
public static void copy(InputStream input, Writer writer, String encoding) throws IOException {
// if (encoding == null) {
// copy(input, writer);
// } else {
// InputStreamReader reader = new InputStreamReader(input, encoding);
// copy(reader, writer);
// }
if (encoding == null) {
copy(input, writer);
} else {
InputStreamReader reader = null;
try {
reader = new InputStreamReader(input, encoding);
copy(reader, writer);
} finally {
closeQuietly(reader);
}
}
} /**
* 将字节输入流拷贝到字节输出流
* @param input
* @param output
* @return 字节数
* @throws IOException
*/
public static int copy(InputStream input, OutputStream output) throws IOException {
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
int count = 0;
int n = 0;
while (-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
output.flush();
return count;
} /**
* 将字符输入流拷贝到字节输出流
* @param reader
* @param output
* @throws IOException
*/
public static void copy(Reader reader, OutputStream output) throws IOException {
// OutputStreamWriter writer = new OutputStreamWriter(output);
// copy(reader, writer);
OutputStreamWriter writer = null;
try {
writer = new OutputStreamWriter(output);
copy(reader, writer);
} finally {
closeQuietly(writer);
}
} /**
* 将字符输入流拷贝到字节输出流
* @param reader
* @param output
* @param encoding
* @throws IOException
*/
public static void copy(Reader reader, OutputStream output, String encoding)
throws IOException {
// if (encoding == null) {
// copy(reader, output);
// } else {
// OutputStreamWriter writer = new OutputStreamWriter(output, encoding);
// copy(reader, writer);
// }
if (encoding == null) {
copy(reader, output);
} else {
OutputStreamWriter writer = null;
try {
writer = new OutputStreamWriter(output, encoding);
copy(reader, writer);
} finally {
closeQuietly(writer);
}
}
} /**
* 将字符输入流拷贝到字符输出流
* @param reader
* @param writer
* @return 字符数
* @throws IOException
*/
public static int copy(Reader reader, Writer writer) throws IOException {
char[] buffer = new char[DEFAULT_BUFFER_SIZE];
int count = 0;
int n = 0;
while (-1 != (n = reader.read(buffer))) {
writer.write(buffer, 0, n);
count += n;
}
writer.flush();
return count;
} /**
* 关闭IO流
* @param close
*/
public static void closeQuietly(Closeable close) {
closeQuietly(close, "关闭IO流出错!");
} /**
* 关闭IO流
* @param close
* @param errorMsg
*/
public static void closeQuietly(Closeable close, String errorMsg) {
if (close != null) {
try {
close.close();
} catch (IOException e) {
logger.error(errorMsg, e);
}
}
}
public class PCIHttpClientImpl4 implements PCIHttpClient { private static LogUtils logger = new LogUtils(PCIHttpClientImpl4.class); private SSLConnectionSocketFactory sslSocketFactory = null; /**
* 构造方法
*
* <p>允许信任任何证书策略和允许任何域名验证</p>
*/
public PCIHttpClientImpl4() {
this(false, false, true, true, null, null, null);
} /**
* 构造方法
*
* @param allowAnyTrustMaterial 是否允许信任任何证书策略
* @param allowAnyHostnameVerifier 是否允许任何域名验证
*/
public PCIHttpClientImpl4(boolean allowAnyTrustMaterial, boolean allowAnyHostnameVerifier) {
this(false, false, allowAnyTrustMaterial, allowAnyHostnameVerifier, null, null, null);
} /**
* 构造方法
*
* @param loadKeyMaterial 是否加载密钥
* @param loadTrustMaterial 是否加载信任证书
* @param keystoreFilePath 密钥库文件路径
* @param storePassword 密钥库密码
* @param keyPassword 私钥密码
*/
public PCIHttpClientImpl4(boolean loadKeyMaterial, boolean loadTrustMaterial,
String keystoreFilePath, String storePassword, String keyPassword) {
this(loadKeyMaterial, loadTrustMaterial, false, true, keystoreFilePath, storePassword, keyPassword);
} /**
* 构造方法
*
* @param loadKeyMaterial 是否加载密钥
* @param loadTrustMaterial 是否加载信任证书(若allowAnyTrustMaterial=true,则loadTrustMaterial无效)
* @param allowAnyTrustMaterial 是否允许信任任何证书策略
* @param allowAnyHostnameVerifier 是否允许任何域名验证
* @param keystoreFilePath 密钥库文件路径
* @param storePassword 密钥库密码
* @param keyPassword 私钥密码
*/
public PCIHttpClientImpl4(boolean loadKeyMaterial, boolean loadTrustMaterial,
boolean allowAnyTrustMaterial, boolean allowAnyHostnameVerifier,
String keystoreFilePath, String storePassword, String keyPassword) {
try {
// Create SSLContext
SSLContextBuilder sslContextBuilder = new SSLContextBuilder();
if (loadKeyMaterial) {
sslContextBuilder.loadKeyMaterial(
new File(keystoreFilePath), storePassword.toCharArray(), keyPassword.toCharArray());
}
if (allowAnyTrustMaterial) {
sslContextBuilder.loadTrustMaterial(null, new AnyTrustStrategy());
} else if (loadTrustMaterial) {
sslContextBuilder.loadTrustMaterial(
new File(keystoreFilePath), storePassword.toCharArray(), new TrustSelfSignedStrategy());
}
SSLContext sslContext = sslContextBuilder.build(); // Create SSLConnectionSocketFactory
if (allowAnyHostnameVerifier) {
sslSocketFactory = new SSLConnectionSocketFactory(sslContext, new AnyHostnameVerifier());
} else {
sslSocketFactory = new SSLConnectionSocketFactory(sslContext);
}
} catch (NoSuchAlgorithmException e) {
logger.error("Error occurred: NoSuchAlgorithmException", e);
} catch (KeyStoreException e) {
logger.error("Error occurred: KeyStoreException", e);
} catch (UnrecoverableKeyException e) {
logger.error("Error occurred: UnrecoverableKeyException", e);
} catch (CertificateException e) {
logger.error("Error occurred: CertificateException", e);
} catch (IOException e) {
logger.error("Error occurred: IOException", e);
} catch (KeyManagementException e) {
logger.error("Error occurred: KeyManagementException", e);
}
} /**
* 信任任何证书策略
*/
private static class AnyTrustStrategy implements TrustStrategy {
@Override
public boolean isTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
return true;
}
} /**
* 允许任何域名验证
*/
private static class AnyHostnameVerifier implements HostnameVerifier {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
} @Override
public String sendGetAndResponseAsString(String url,
int timeout) throws IOException {
return sendGetAndResponseAsString(url, null, null, CustomConstants.CHARSET_UTF8, timeout);
} @Override
public String sendGetAndResponseAsString(String url,
Map<String, String> headers, int timeout) throws IOException {
return sendGetAndResponseAsString(url, headers, null, CustomConstants.CHARSET_UTF8, timeout);
} @Override
public String sendGetAndResponseAsString(String url,
Map<String, String> headers, Map<String, String> params,
String charsetName, int timeout) throws IOException {
byte[] buffer = sendGetAndResponseAsByteArray(url, headers, params, charsetName, timeout);
if (buffer == null) {
return null;
}
return new String(buffer, charsetName);
} @Override
public byte[] sendGetAndResponseAsByteArray(String url,
int timeout) throws IOException {
return sendGetAndResponseAsByteArray(url, null, null, null, timeout);
} @Override
public byte[] sendGetAndResponseAsByteArray(String url,
Map<String, String> headers, int timeout) throws IOException {
return sendGetAndResponseAsByteArray(url, headers, null, null, timeout);
} @Override
public byte[] sendGetAndResponseAsByteArray(String url,
Map<String, String> headers, Map<String, String> params,
String charsetName, int timeout) throws IOException {
ByteArrayOutputStream output = null;
try {
output = new ByteArrayOutputStream();
sendGet(url, headers, params, charsetName, timeout, output);
return output.toByteArray();
} finally {
IOUtils.closeQuietly(output);
}
} @Override
public InputStream sendGetAndResponseAsStream(String url,
Map<String, String> headers, Map<String, String> params,
String charsetName, int timeout) throws IOException {
byte[] buffer = sendGetAndResponseAsByteArray(url, headers, params, charsetName, timeout);
if (buffer == null) {
return null;
}
return new ByteArrayInputStream(buffer);
} @Override
public void sendGet(String url, Map<String, String> headers,
Map<String, String> params, String charsetName, int timeout,
OutputStream output) throws IOException {
if (StringUtils.isEmpty(url)) {
logger.error("The url can not be null.");
throw new IllegalArgumentException("The url can not be null.");
}
sendAndResponseAsStream(new HttpGet(createURI(url, params, charsetName)),
headers, timeout, output);
} @Override
public String sendPostAndResponseAsString(String url,
Map<String, String> params, String charsetName, int timeout) throws IOException {
return sendPostAndResponseAsString(url, null, params, null, charsetName, timeout);
} @Override
public String sendPostAndResponseAsString(String url,
Map<String, String> headers, Map<String, String> params,
int timeout, String charsetName) throws IOException {
return sendPostAndResponseAsString(url, headers, params, null, charsetName, timeout);
} @Override
public String sendPostAndResponseAsString(String url,
Map<String, String> headers, Object stringOrStream,
String charsetName, int timeout) throws IOException {
return sendPostAndResponseAsString(url, headers, null, stringOrStream, charsetName, timeout);
} @Override
public String sendPostAndResponseAsString(String url,
Map<String, String> headers, Map<String, String> params,
Object stringOrStream, String charsetName, int timeout) throws IOException {
byte[] buffer = sendPostAndResponseAsByteArray(
url, headers, params, stringOrStream, charsetName, timeout);
if (buffer == null) {
return null;
}
return new String(buffer, charsetName);
} @Override
public byte[] sendPostAndResponseAsByteArray(String url,
Map<String, String> params, String charsetName, int timeout) throws IOException {
return sendPostAndResponseAsByteArray(url, null, params, null, charsetName, timeout);
} @Override
public byte[] sendPostAndResponseAsByteArray(String url,
Map<String, String> headers, Map<String, String> params,
int timeout, String charsetName) throws IOException {
return sendPostAndResponseAsByteArray(url, headers, params, null, charsetName, timeout);
} @Override
public byte[] sendPostAndResponseAsByteArray(String url,
Map<String, String> headers, Object stringOrStream,
String charsetName, int timeout) throws IOException {
return sendPostAndResponseAsByteArray(url, headers, null, stringOrStream, charsetName, timeout);
} @Override
public byte[] sendPostAndResponseAsByteArray(String url,
Map<String, String> headers, Map<String, String> params,
Object stringOrStream, String charsetName, int timeout) throws IOException {
ByteArrayOutputStream output = null;
try {
output = new ByteArrayOutputStream();
sendPost(url, headers, params, stringOrStream, charsetName, timeout, output);
return output.toByteArray();
} finally {
IOUtils.closeQuietly(output);
}
} @Override
public InputStream sendPostAndResponseAsStream(String url,
Map<String, String> headers, Map<String, String> params,
Object stringOrStream, String charsetName, int timeout) throws IOException {
byte[] buffer = sendPostAndResponseAsByteArray(
url, headers, params, stringOrStream, charsetName, timeout);
if (buffer == null) {
return null;
}
return new ByteArrayInputStream(buffer);
} @Override
public void sendPost(String url, Map<String, String> headers,
Map<String, String> params, Object stringOrStream,
String charsetName, int timeout, OutputStream output) throws IOException {
if (StringUtils.isEmpty(url)) {
logger.error("The url can not be null.");
throw new IllegalArgumentException("The url can not be null.");
} // post请求方式
HttpPost method = new HttpPost(createURI(url, params, charsetName)); // 设置请求头信息
if (headers == null) {
headers = new HashMap<String, String>();
}
if (!headers.containsKey(CONTENT_TYPE)) {
headers.put(CONTENT_TYPE, DEFAULT_CONTENTTYPE);
} // 设置请求体内容
if (stringOrStream != null) {
HttpEntity entity = null;
if (stringOrStream instanceof InputStream) {
entity = new InputStreamEntity((InputStream) stringOrStream);
} else {
entity = new StringEntity(stringOrStream.toString(),
ContentType.create(CONTENT_TYPE, charsetName));
}
method.setEntity(entity);
} // 发送请求数据,并接收响应数据
sendAndResponseAsStream(method, headers, timeout, output);
} /**
* 发送请求数据,并接收响应数据
* @param method 请求方式
* @param headers 请求头信息
* @param timeout 超时时间
* @param output 响应内容(输出流)
* @throws IOException
*/
private void sendAndResponseAsStream(HttpRequestBase method,
Map<String, String> headers, int timeout, OutputStream output) throws IOException {
// 设置请求配置信息
RequestConfig config = RequestConfig.custom()
.setConnectTimeout(DEFAULT_CONNECTION_TIMEOUT) //连接超时时间
.setSocketTimeout(timeout) //读取超时时间
.setCircularRedirectsAllowed(true) //设置是否允许循环重定向(重定向到相同路径)
.build();
method.setConfig(config); // 设置请求头信息
if (headers == null) {
headers = new HashMap<String, String>();
}
if (!headers.containsKey(USER_AGENT)) {
headers.put(USER_AGENT, DEFAULT_USERAGENT);
}
for (Map.Entry<String, String> entry : headers.entrySet()) {
method.setHeader(entry.getKey(), entry.getValue());
} // 发送请求
CloseableHttpClient httpClient = createHttpClient(method.getURI());
CloseableHttpResponse httpResponse = null;
InputStream input = null;
try {
httpResponse = httpClient.execute(method);
int status = httpResponse.getStatusLine().getStatusCode();
if (status != HttpStatus.SC_OK) {
String errorMsg = CustomStringUtils.append("The remote service[",
method.getURI(), "] respose an error status:", status);
logger.error(errorMsg);
if (status >= 500 && status < 600) {
throw new IOException(errorMsg);
}
}
HttpEntity httpEntity = httpResponse.getEntity();
if (httpEntity == null) {
String errorMsg = CustomStringUtils.append("The remote service[",
method.getURI(), "] respose entity is null. status:", status);
logger.error(errorMsg);
throw new IOException(errorMsg);
}
input = httpEntity.getContent();
if (input == null) {
String errorMsg = CustomStringUtils.append("The remote service[",
method.getURI(), "] respose entity content is null. status:", status);
logger.error(errorMsg);
throw new IOException(errorMsg);
}
IOUtils.copy(input, output);
} catch (IOException e) {
logger.error("Access to the remote service[" + method.getURI() + "] error.", e);
throw e;
} finally {
IOUtils.closeQuietly(input);
// method.releaseConnection();
IOUtils.closeQuietly(httpResponse);
IOUtils.closeQuietly(httpClient);
}
} /**
* 创建HttpClient对象
* @param uri
* @return
*/
private CloseableHttpClient createHttpClient(URI uri) {
if ("https".equalsIgnoreCase(uri.getScheme()) && sslSocketFactory != null) {
return HttpClients.custom().setSSLSocketFactory(sslSocketFactory).build();
} else {
return HttpClients.createDefault();
}
} /**
* 创建请求URI
* @param url
* @param params
* @param charsetName
* @return
* @throws IOException
*/
private URI createURI(String url,
Map<String, String> params, String charsetName) throws IOException {
if (params == null || params.isEmpty()) {
return URI.create(url);
}
// 设置请求参数
List<NameValuePair> parameters = new ArrayList<NameValuePair>(params.size());
for (Map.Entry<String, String> entry : params.entrySet()) {
parameters.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
}
try {
return new URIBuilder(url)
.addParameters(parameters)
.setCharset(Charset.forName(charsetName))
.build();
} catch (URISyntaxException e) {
String errorMsg = "Build request URI error, the url is [" + url + "].";
logger.error(errorMsg, e);
throw new IOException(errorMsg, e);
}
} /**
* @see PCIHttpClient.com.bestpay.pgw.tools.http.PGWHttpClient#sendGet(java.lang.String, java.util.Map, java.util.Map, java.lang.String, int)
*/
@Override
public PCIHttpResponse sendGet(String url, Map<String, String> headers,
Map<String, String> params, String charsetName, int timeout)
throws IOException {
if (StringUtils.isEmpty(url)) {
logger.error("The url can not be null.");
throw new IllegalArgumentException("The url can not be null.");
}
return sendAndResponseAsStream(
new HttpGet(createURI(url, params, charsetName)), headers, timeout);
} /**
* @see PCIHttpClient.com.bestpay.pgw.tools.http.PGWHttpClient#sendPost(java.lang.String, java.util.Map, java.util.Map, java.lang.Object, java.lang.String, int)
*/
@Override
public PCIHttpResponse sendPost(String url, Map<String, String> headers,
Map<String, String> params, Object stringOrStream,
String charsetName, int timeout) throws IOException {
if (StringUtils.isEmpty(url)) {
logger.error("The url can not be null.");
throw new IllegalArgumentException("The url can not be null.");
} // post请求方式
HttpPost method = new HttpPost(createURI(url, params, charsetName)); // 设置请求头信息
if (headers == null) {
headers = new HashMap<String, String>();
}
if (!headers.containsKey(CONTENT_TYPE)) {
headers.put(CONTENT_TYPE, DEFAULT_CONTENTTYPE);
} // 设置请求体内容
if (stringOrStream != null) {
HttpEntity entity = null;
if (stringOrStream instanceof InputStream) {
entity = new InputStreamEntity((InputStream) stringOrStream);
} else {
entity = new StringEntity(stringOrStream.toString(),
ContentType.create(CONTENT_TYPE, charsetName));
}
method.setEntity(entity);
} // 发送请求数据,并接收响应数据
return sendAndResponseAsStream(method, headers, timeout);
} /**
* 发送请求数据,并接收响应数据
*
* @param method 请求方式
* @param headers 请求头信息
* @param timeout 超时时间
* @return
* @throws IOException
*
* @since 2.0.0
*/
private PCIHttpResponse sendAndResponseAsStream(HttpRequestBase method,
Map<String, String> headers, int timeout) throws IOException {
// 设置请求配置信息
RequestConfig config = RequestConfig.custom()
.setConnectTimeout(DEFAULT_CONNECTION_TIMEOUT) //连接超时时间
.setSocketTimeout(timeout) //读取超时时间
.setCircularRedirectsAllowed(true) //设置是否允许循环重定向(重定向到相同路径)
.build();
method.setConfig(config); // 设置请求头信息
if (headers == null) {
headers = new HashMap<String, String>();
}
if (!headers.containsKey(USER_AGENT)) {
headers.put(USER_AGENT, DEFAULT_USERAGENT);
}
for (Map.Entry<String, String> entry : headers.entrySet()) {
method.setHeader(entry.getKey(), entry.getValue());
} // 发送请求
CloseableHttpClient httpClient = createHttpClient(method.getURI());
CloseableHttpResponse httpResponse = null;
InputStream responseBodyInputStream = null;
ByteArrayOutputStream responseBodyOutputStream = null;
try {
httpResponse = httpClient.execute(method);
int status = httpResponse.getStatusLine().getStatusCode();
if (status != HttpStatus.SC_OK) {
String errorMsg = CustomStringUtils.append("The remote service[",
method.getURI(), "] respose an error status:", status);
logger.error(errorMsg);
if (status >= 500 && status < 600) {
throw new IOException(errorMsg);
}
} // 获取响应头
Map<String, String> responseHeaders = null;
Header[] httpHeaders = httpResponse.getAllHeaders();
if (httpHeaders != null && httpHeaders.length > 0) {
responseHeaders = new HashMap<String, String>(httpHeaders.length);
for (Header header : httpHeaders) {
responseHeaders.put(header.getName(), header.getValue());
}
} // 获取响应体
byte[] responseBody = null;
HttpEntity httpEntity = httpResponse.getEntity();
if (httpEntity != null) {
responseBodyInputStream = httpEntity.getContent();
if (responseBodyInputStream != null) {
responseBodyOutputStream = new ByteArrayOutputStream();
IOUtils.copy(responseBodyInputStream, responseBodyOutputStream);
responseBody = responseBodyOutputStream.toByteArray();
} else {
logger.warn(CustomStringUtils.append("The remote service[",
method.getURI(), "] respose entity content is null. status:", status));
}
} else {
logger.warn(CustomStringUtils.append("The remote service[",
method.getURI(), "] respose entity is null. status:", status));
} return new PCIHttpResponse(responseHeaders, responseBody);
} catch (IOException e) {
logger.error("Access to the remote service[" + method.getURI() + "] error.", e);
throw e;
} finally {
IOUtils.closeQuietly(responseBodyInputStream);
IOUtils.closeQuietly(responseBodyOutputStream);
// method.releaseConnection();
IOUtils.closeQuietly(httpResponse);
IOUtils.closeQuietly(httpClient);
}
} }
单元测试示例(本示例为双向认证示例,单向认证则对应修改PCIHttpClientImpl4的构造参数即可):
@Test
public void testClock() throws Exception {
String testUrl = "https://mail.xxxxxx.com:8440/service";
Map<String, String> map = new HashMap<String, String>(); map.put("messageType", "2058");
map.put("accessUser", "gxecard_test_user_zhengchuan");
map.put("terminalNo", "1"); String parameter = JSON.toJSONString(map);
String requestJson = "parameter=" + parameter;
System.out.println("requestJson:" + requestJson); // httpClient = new PCIHttpClientImpl4(true, false,
// true, true,
// "D:\\keystore.jks", "123456", "123456"); //证书可以是jks格式也可以是p12格式
httpClient = new PCIHttpClientImpl4(true, false,
true, true,
"D:\\keystore.p12", "123456", "123456"); PCIHttpResponse httpResponse = null;
httpResponse = httpClient.sendPost(testUrl, null, null, requestJson, "UTF-8", 55 * 1000); System.out.println(httpResponse.getBodyString());
}
java访问Https服务的客户端示例的更多相关文章
- Spring提供的用于访问Rest服务的客户端:RestTemplate实践
什么是RestTemplate? RestTemplate是Spring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效 ...
- Java访问HTTPS时证书验证问题
为了尽可能避免安全问题,公司的很多系统服务都逐步https化,虽然开始过程会遇到各种问题,但趋势不改.最完美的https应用是能实现双向认证,客户端用私钥签名用服务端公钥加密,服务端用私钥签名客户端都 ...
- [转载]Java创建WebService服务及客户端实现
Java创建WebService服务及客户端实现 Java创建WebService服务及客户端实现
- Tomcat创建HTTPS访问,java访问https
一 https和ssL HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的 ...
- 国产化之银河麒麟.netcore3.1访问https服务的两个问题
背景 某个项目需要实现基础软件全部国产化,其中操作系统指定银河麒麟,数据库使用达梦V8,CPU平台的范围包括x64.龙芯.飞腾.鲲鹏等. 考虑到这些基础产品对.NETCore的支持,最终选择了3.1版 ...
- java 访问HTTPS rest服务
import java.io.*;import java.net.*;import java.security.cert.CertificateException;import java.securi ...
- Java创建WebService服务及客户端实现(转)
简介 WebService是一种服务的提供方式,通过WebService,不同应用间相互间调用变的很方便,网络上有很多常用的WebService服务,如:http://developer.51cto. ...
- Java 开发 gRPC 服务和客户端
新建一个普通的Maven项目: 配置pom文件,导入gRPC的依赖和插件 pom 中增加外部依赖 <dependency> <groupId>io.grpc</g ...
- Java创建WebService服务及客户端实现
简介 WebService是一种服务的提供方式,通过WebService,不同应用间相互间调用变的很方便,网络上有很多常用的WebService服务,如:http://developer.51cto. ...
随机推荐
- CodeForces - 913C(二进制)
链接:CodeForces - 913C 题意:给出 n 瓶饮料的花费 C 数组,每瓶的体积是 2^(i-1) 升,求至少买 L 升的最少花费. 题解:二进制数的组合可以表示任何一个数.第 i 的饮料 ...
- 【radio-group、radio】 单选项组件说明
radio-group组件是包裹radio组件的容器 原型: <radio-group bindchange="[EventHandle]"> <radio .. ...
- 打包一个Docker镜像,让你的好友加载开启一个容器,并且每隔一秒输出hello,world到指定的文件中
一.两个脚本代码 Dockerfile FROM bash COPY . /usr/herui/ WORKDIR /usr/herui/ CMD [ "sh", "hel ...
- [Clr via C#读书笔记]Cp15枚举和位标识
Cp15枚举和位标识 枚举类型 本质是结构,符号名称-值:好处显而易见:System.Enum;值类型: 编译的时候,符号会转换为常量字段: 枚举支持很多方法和成员: 位标识bit flag 判断和设 ...
- python 打包
一.下载 pip install Pyinstaller 二.使用Pyinstaller 1.使用下载安装的方式安装的Pyinstaller打包方式 将需要打包的文件放在解压得到的Pyinstalle ...
- 清橙 A1318 加强版:Almost
题意: 直接看题面吧 原版:\(n \leq 1e5, q \leq 3e4, TL 5s, ML 256G\) 加强版1:\(n,q \leq 1.5e5, TL 5s, ML 256G\) 加强版 ...
- 十面阿里,七面头条,六个Offer,春招结束
作者:jkgeekjack链接:https://www.nowcoder.com/discuss/80156?type=0&order=0&pos=13&page=2来源:牛客 ...
- 【转载】java byte转十六进制
public static String bytes2HexString(byte[] b) { String ret = ""; for (int i = 0; i < b ...
- 【转】Expressions versus statements in JavaScript
原文地址:http://www.2ality.com/2012/09/expressions-vs-statements.html Update 2012-09-21: New in Sect. 4: ...
- su和sudo的使用
用于用户身份切换 一.su 命令形式 代表内容 su 切换为root,以non-login shell的方式 su - 切换为root,以login shell的方式 su -l 账号 切换为“账号” ...