java如何发送认证请求_Java客户端发送双向TLS认证HTTPS请求

给出一个java客户端代码例子,这个客户端程序向REST服务器发送HTTPS请求,客户端和服务器端实现TLS双向认证。

import java.util.Map;

import java.util.HashMap;

import java.util.Map.Entry;

import java.util.Set;

import java.net.HttpURLConnection;

import java.net.URL;

import java.security.KeyStore;

import java.security.cert.CertificateException;

import java.security.cert.X509Certificate;

import java.io.BufferedReader;

import java.io.FileInputStream;

import java.io.IOException;

import java.io.OutputStreamWriter;

import java.io.StringReader;

import java.io.InputStreamReader;

import java.io.InputStream;

import javax.net.ssl.HttpsURLConnection;

import javax.net.ssl.KeyManagerFactory;

import javax.net.ssl.SSLContext;

import javax.net.ssl.SSLSocketFactory;

import javax.net.ssl.TrustManager;

import javax.net.ssl.TrustManagerFactory;

import javax.net.ssl.X509TrustManager;

public class Test {

private String serverUrl = "https://10.20.xxx.xxx:8080/api/v1.1/service/test";

private SSLSocketFactory sslFactory = null;

public void run() {

try {

String requestBody ="{\"instance\":\"instance\",\"list\":[{\"id\":\"id\",\"status\":\"OK\",\"action\":\"UPDATE\"}]}";

HttpURLConnection connection = doHttpRequest(serverUrl, "PUT", requestBody, null);

int responseCode = getResponseCode(connection);

String responseBody = getResponseBodyAsString(connection);

connection.disconnect();

System.out.println("response code=" + responseCode + ", body=[" + responseBody + "]");

} catch (Exception e) {

e.printStackTrace();

}

}

public static void main(String[] args) {

Test test = new Test();

test.run();

}

private synchronized SSLSocketFactory getSSLFactory() throws Exception {

if (sslFactory == null) {

SSLContext sslContext = SSLContext.getInstance("SSL");

TrustManager[] tm = { new MyX509TrustManager() };

KeyStore truststore = KeyStore.getInstance("JKS");

truststore.load(new FileInputStream("cert.jks"), "123456".toCharArray());

KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");

kmf.init(truststore, "123456".toCharArray());

sslContext.init(kmf.getKeyManagers(), tm, new java.security.SecureRandom());

sslFactory = sslContext.getSocketFactory();

}

return sslFactory;

}

private HttpURLConnection doHttpRequest(String requestUrl, String method, String body, Map header) throws Exception {

HttpURLConnection conn;

if (method == null || method.length() == 0 ) {

method = "GET";

}

if ("GET".equals(method) && body != null && ! body.isEmpty()) {

requestUrl = requestUrl + "?" + body;

}

URL url = new URL(requestUrl);

conn = (HttpURLConnection) url.openConnection();

conn.setDoOutput(true);

conn.setDoInput(true);

conn.setUseCaches(false);

conn.setInstanceFollowRedirects(true);

conn.setRequestMethod(method);

if (requestUrl.matches("^(https?)://.*$")){

((HttpsURLConnection) conn).setSSLSocketFactory(this.getSSLFactory());

}

if (header != null) {

for (String key : header.keySet()) {

conn.setRequestProperty(key, header.get(key));

}

}

if (body != null && ! body.isEmpty()) {

if (!method.equals("GET") ) {

OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());

wr.write(body);

wr.close();

}

}

conn.connect();

return conn;

}

public int getResponseCode(HttpURLConnection connection) throws IOException {

return connection.getResponseCode();

}

public String getResponseBodyAsString(HttpURLConnection connection) throws Exception {

BufferedReader reader = null;

if (connection.getResponseCode() == 200) {

reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));

} else {

reader = new BufferedReader(new InputStreamReader(connection.getErrorStream()));

}

StringBuffer buffer = new StringBuffer();

String line=null;

while ((line = reader.readLine()) != null) {

buffer.append(line);

}

return buffer.toString();

}

class MyX509TrustManager implements X509TrustManager {

private X509TrustManager sunJSSEX509TrustManager;

MyX509TrustManager() throws Exception {

// create a "default" JSSE X509TrustManager.

KeyStore ks = KeyStore.getInstance("JKS");

ks.load(new FileInputStream("ca.jks"), "123456".toCharArray());

TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509", "SunJSSE");

tmf.init(ks);

TrustManager tms[] = tmf.getTrustManagers();

/*

* Iterate over the returned trustmanagers, look for an instance of

* X509TrustManager. If found, use that as our "default" trust manager.

*/

for (int i = 0; i < tms.length; i++) {

if (tms[i] instanceof X509TrustManager) {

sunJSSEX509TrustManager = (X509TrustManager) tms[i];

return;

}

}

throw new Exception("Couldn't initialize");

}

@Override

public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {

try {

sunJSSEX509TrustManager.checkClientTrusted(chain, authType);

} catch (CertificateException excep) {

}

}

@Override

public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {

try {

sunJSSEX509TrustManager.checkServerTrusted(chain, authType);

} catch (CertificateException excep) {

}

}

@Override

public X509Certificate[] getAcceptedIssuers() {

return sunJSSEX509TrustManager.getAcceptedIssuers();

}

}

}

准备客户端证书

使用openssl生成PEM格式证书

包含三个文件:

ca.pem // CA证书

cert.pem // 客户端证书

key.pem // 客户端私钥

使用keytool生成JKS格式证书

使用JDK自带的keytool工具从PEM格式证书生成JKS格式证书

$ keytool -import -noprompt -file ca.pem -keystore ca.jks -storepass 123456

$ openssl pkcs12 -export -in cert.pem -inkey key.pem -out cert.p12 -passout pass:123456

$ keytool -importkeystore -srckeystore cert.p12 -srcstoretype PKCS12 -srcstorepass 123456 -deststorepass 123456} -destkeystore cert.jks

工具keytool 一般在${JDK_HOME}/bin目录下面;"123456"是随便取的密码。

最终生成两个需要的JKS格式证书。

ca.jks # CA证书

cert.jks # 客户端证书

其实是我一直没有找到java如何直接加载PEM格式证书;如果能加载PEM格式证书,就不需要转换成JKS格式。

编译运行

javac Test.java && java Test

### 回答1: Java 语言中,https双向认证即为客户端和服务器双方都需要进行身份验证。这种方式能够提供更高级别的安全保障,因为双方都需要证明自己的身份。 在 Java 中,可以使用 java.net 包中的 HttpsURLConnection 类实现双向认证。要使用双向认证,需要客户端和服务器都持有一个数字证书,并且客户端需要在与服务器通信时提供证书,服务器也需要验证客户端的证书。 代码实现细节较复杂,这里不再赘述。有兴趣的读者可以查找相关的资料进行学习。 ### 回答2: Java语言中的HTTPS双向认证是建立在传输层安全协议(TLS/SSL)之上的一种加密通信机制。在HTTPS连接中,服务器和客户端之间进行双向认证,以确保通信的安全性。 双向认证主要包括以下步骤: 首先,服务器需要具有一张数字证书,该证书由可信任的第三方机构(如CA)颁发。证书中包含了服务器的公钥,以及其他相关信息。服务器会将此证书发送客户端。 然后,客户端会收到服务器发送的数字证书。客户端会验证证书的合法性,并检查证书中的相关信息,如颁发机构、有效期等。如果证书合法,客户端会直接使用证书中的公钥进行加密。 接下来,客户端会生成一个随机数(密钥),并使用服务器的公钥对其进行加密,然后将加密后的密钥发送给服务器。 服务器收到客户端发送的加密后的密钥后,会使用自己的私钥进行解密操作,得到客户端生成的随机数。 此后,服务器和客户端都拥有了相同的随机数(密钥),它们可以使用该密钥进行对称加密和解密操作,保证通信的机密性和完整性。 通过以上双向认证的流程,HTTPS连接实现了身份验证和数据加密,确保了通信的安全性。在Java语言中,可以使用相关的API和工具来实现双向认证,如Java KeyStore用于存储和管理数字证书,以及使用SSLContext和SSLParameters等类来配置和控制SSL/TLS连接的安全参数。 ### 回答3: Java语言中的HTTPS双向认证是一种网络通信模式,在该模式中,服务器和客户端之间进行双向验证以确保安全通信。 首先,客户端向服务器发起HTTPS连接请求。服务器会将自己的数字证书发送客户端,该数字证书包含服务器的公钥,并由数字证书颁发机构签名验证。客户端会验证服务器的证书是否合法和有效。 接下来,客户端生成自己的密钥对,并将公钥发送给服务器。客户端的公钥也被包含在数字证书中,并由客户端的数字证书颁发机构签名验证。服务器会验证客户端的证书是否合法和有效。 在双向认证过程中,客户端和服务器都进行了证书的验证和身份的验证。只有在双方都验证通过的情况下,它们才能建立安全的连接,继续进行通信。 双向认证可以提供更高的安全性,因为不仅服务器验证客户端身份,客户端也可以验证服务器身份。这有效防止了中间人攻击和伪造服务器的问题。 在Java语言中,可以使用Java标准库中的SSLSocket和SSLServerSocket类来实现HTTPS双向认证。服务器可以配置使用自己的私钥和证书,用于验证客户端请求,而客户端可以使用其私钥和证书来验证服务器。 双向认证HTTPS协议中的一种重要机制,可以在保证通信安全的同时提供双方身份的验证。它广泛应用于银行、电商等对安全性要求较高的应用场景中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值