最近要用到Nginx配置https转发http的功能,配置是很简单,然而用Java验证时总出现各种问题,这里记录一下整个过程:
1.生成服务器端私钥及自签名证书
下面的步骤在windows与linux下都可以实现
首先,进入你想创建证书和私钥的目录,例如:
# cd /etc/nginx/
创建服务器私钥,命令会让你输入一个口令:
# openssl genrsa -des3 -out server.key 1024
创建签名请求的证书(CSR):
# openssl req -new -key server.key -out server.csr
在加载SSL支持的Nginx并使用上述私钥时除去必须的口令:
# cp server.key server.key.org
# openssl rsa -in server.key.org -out server.key
最后标记证书使用上述私钥和CSR:
# openssl x509 -req -days 3650 -in server.csr -signkey server.key -out server.crt
2.配置Nginx
# 转发到自己的服务器
server {
server_name 192.168.0.194;
listen 6000;
ssl on;
ssl_certificate ../ssl/server.crt;
ssl_certificate_key ../ssl/server.key;
location / {
proxy_pass http://192.168.0.194:5006;
}
}
# 转发至tomcat,实验用
server {
server_name localhost;
listen 7000;
ssl on;
ssl_certificate ../ssl/server.crt;
ssl_certificate_key ../ssl/server.key;
location / {
proxy_pass http://localhost:8080;
}
}
配置完重新加载Nginx:
nginx.exe -s reload
3.网页访问:
点开“高级”,里面有个“继续前往localhost(不安全)的链接,点击后可以跳转到tomcat欢迎页面:
网页访问可以通过导入证书来解决信任问题,参考文章http://blog.getpostman.com/2014/01/28/using-self-signed-certificates-with-postman/,但是我这里一直没办法弹出 Certificate window,只能作罢
4.通过Java代码发送https:post请求
4.1 绕过服器证书验证
本来,想通过Java代码单向验证服务器证书,但是搞了半天也没弄好,各种出错,这里参考的文章如下:
- 这个好全面:http://blog.csdn.net/fw0124/article/details/48341671
- 这个按说可以实现:http://blog.csdn.net/faye0412/article/details/6883879
然而,弄了一天,总是各种出错,最后还是通过忽略校验过程的方式成功返回数据
废话不多说,上代码:
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONObject;
public class SSLNoVerify {
private String url = "https://192.168.0.194:6000";
private String charset = "utf-8";
public void testHttps(){
//构造请求字符串
JSONObject obj = new JSONObject();
obj.put("method", "tx");
JSONObject param = new JSONObject();
param.put("transaction", "14A9AE360F8B97C0A146D8ACA402518F558656B83EDA6E0A9F120633D4EA83BE");
JSONArray arr = new JSONArray();
arr.put(param);
obj.put("params", arr);
String params = obj.toString();
String ret = doHttpsPost(url, params, charset);
System.out.println(ret);
}
public String doHttpsPost(String url,String param,String charset){
HttpClient httpClient = null;
HttpPost httpPost = null;
String result = null;
try{
httpClient = new SSLClient();
httpPost = new HttpPost(url);
//设置参数
StringEntity entity = new StringEntity(param);
httpPost.setEntity(entity);
HttpResponse response = httpClient.execute(httpPost);
if(response != null){
HttpEntity resEntity = response.getEntity();
if(resEntity != null){
result = EntityUtils.toString(resEntity,charset);
}
}
}catch(Exception ex){
ex.printStackTrace();
}
return result;
}
public static void main(String[] args){
TestMain main = new TestMain();
main.testHttps();
}
}
4.2 验证服务器端证书
用的还是1中提到的方法:http://blog.csdn.net/faye0412/article/details/6883879
上代码:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.net.URLConnection;
import java.util.List;
import java.util.Map;
import org.json.JSONArray;
import org.json.JSONObject;
public class HttpRequest {
/**
* 向指定 URL 发送POST方法的请求
*
* @param url
* 发送请求的 URL
* @param param
* 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @return 所代表远程资源的响应结果
*/
public static String sendPost(String url, String param) {
PrintWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
URLConnection conn = realUrl.openConnection();
// 设置通用的请求属性
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
// 发送请求参数
out.print(param);
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应
in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送 POST 请求出现异常!"+e);
e.printStackTrace();
}
//使用finally块来关闭输出流、输入流
finally{
try{
if(out!=null){
out.close();
}
if(in!=null){
in.close();
}
}
catch(IOException ex){
ex.printStackTrace();
}
}
return result;
}
public static void main(String[] args) {
//添加证书信任文件
System.setProperty("javax.net.ssl.trustStore", "jssecacerts");
JSONObject obj = new JSONObject();
obj.put("method", "tx");
JSONObject param = new JSONObject();
param.put("transaction", "14A9AE360F8B97C0A146D8ACA402518F558656B83EDA6E0A9F120633D4EA83BE");
JSONArray arr = new JSONArray();
arr.put(param);
obj.put("params", arr);
System.out.println(obj.toString());
//发送 POST 请求
String sr=HttpRequest.sendPost("https://localhost:6000", obj.toString());
System.out.println(sr);
}
}
输出如下:
{"method":"tx","params":[{"transaction":"14A9AE360F8B97C0A146D8ACA402518F558656B83EDA6E0A9F120633D4EA83BE"}]}
{"result":{"Account":"rU5WparMeBJvH4UxrGp2byHBB78meHLQBb","Amount":"1000000000","Destination":"rBuLBiHmssAMHWQMnEN7nXQXaVj7vhAv6Q","Fee":"10","Flags":2147483648,"Sequence":53,"SigningPubKey":"031EF5537AF0FB46E84E4E932B3F9BC92B552B895B8E6D42FBB3E20D53F0297AF9","TransactionType":"Payment","TxnSignature":"304402207775CCB44B9B52DABDA19D47AEEEC1A2C115BC42C95D612F42453313CBEEB78102204153DC39F28A1F83735D8E4AE3E039ECC705BA5555621F5A12945AD3BA53F91B","date":554440441,"hash":"14A9AE360F8B97C0A146D8ACA402518F558656B83EDA6E0A9F120633D4EA83BE","inLedger":15708,"ledger_index":15708,"meta":{"AffectedNodes":[{"ModifiedNode":{"FinalFields":{"Account":"rBuLBiHmssAMHWQMnEN7nXQXaVj7vhAv6Q","Balance":"32000000000","Flags":0,"OwnerCount":0,"Sequence":1},"LedgerEntryType":"AccountRoot","LedgerIndex":"079B5765FF6A6AD78F2C72D3CF6A96C6F862A5FE550567BB8CE3B31223D36A99","PreviousFields":{"Balance":"31000000000"},"PreviousTxnID":"AF7AD09923196215D92686DC21F3C620C90986CE62FA592ACE419C78DBCC9D14","PreviousTxnLgrSeq":11214}},{"ModifiedNode":{"FinalFields":{"Account":"rU5WparMeBJvH4UxrGp2byHBB78meHLQBb","Balance":"99999964099999422","Flags":0,"OwnerCount":0,"Sequence":54},"LedgerEntryType":"AccountRoot","LedgerIndex":"27D81EA97F3BAE20C39E2E89D5B720058D5ED070356B2B1F68FCE2EAFF15C17F","PreviousFields":{"Balance":"99999965099999432","Sequence":53},"PreviousTxnID":"C44867A6EE055C69228785EC7420AE51AB86F34651CCF3BDCD4E2A58BAEE7DA2","PreviousTxnLgrSeq":15561}}],"TransactionIndex":0,"TransactionResult":"tesSUCCESS","delivered_amount":"1000000000"},"status":"success","validated":false}}
过程中遇到的问题:
- 出现异常: java.security.cert.CertificateException: No subject alternative names present
解决方案:参考https://confluence.atlassian.com/stashkb/no-subject-alternative-names-693896719.html
请求地址中ip换成域名
参考文章:
http://www.cnblogs.com/hzm112567/p/4269316.html
http://blog.csdn.net/qyf_5445/article/details/39047791
http://blog.csdn.net/rongyongfeikai2/article/details/41659353
http://blog.getpostman.com/2014/01/28/using-self-signed-certificates-with-postman/
网友评论