HttpsURLConnection:使用 IDE JDK 可用于身份验证但不适用于 JRE!!这很奇怪
HttpsURLConnection: using IDE JDK works for authentication but not with JRE!! That's weird
我有一个应用程序使用 HttpsURLConnection 与 pfx 文件和会话 cookie 来检索网页信息。
问题是,如果我像这样启动 jar,它是否有效:
"C:\Program Files\Java\jdk1.8.0_111\bin\java.exe" -jar "app"
但是如果我用我的 JRE 启动 jar,它就不起作用了:
java -jar "app.jar"
它只是没有得到认证...
我读了一些相关内容:How to provide ntlm authentication while calling any url?
但是禁用此 JRE "NTLM" 限制对我没有帮助。据我所知我没有使用 "NTLM".
谢谢你...
public void connect() {
try {
URL url = new URL(HTTPS_URL);
conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(getFactory(new File(KEY_STORE_FILE), KEY_STORE_PASS, new File(TRUST_STORE_FILE), TRUST_STORE_PASS));
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Accept-Language", "es,es-ES;q=0.9,en;q=0.8,de;q=0.7");
conn.setInstanceFollowRedirects(true);
if (!cookies.isEmpty()) {
for (Map.Entry<String, String> entry : cookies.entrySet()) {
if (entry.getKey() != null && entry.getValue() != null) {
conn.setRequestProperty(entry.getKey(), entry.getValue());
}
}
}
conn.connect();
this.headers = conn.getHeaderFields();
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
responsebody += line;
}
br.close();
} catch (MalformedURLException e) {
System.out.println(e.toString());
e.printStackTrace();
} catch (SSLPeerUnverifiedException e) {
System.out.println(e.toString());
e.printStackTrace();
} catch (IOException e) {
System.out.println(e.toString());
e.printStackTrace();
}
}
private SSLSocketFactory getFactory(File pKeyFile, String pKeyPassword, File pTrustStoreFile, String pTrustStorePassword) {
SSLSocketFactory socketFactory = null;
try {
KeyManagerFactory keyManagerFactory;
keyManagerFactory = KeyManagerFactory.getInstance(KEY_MANAGER_ALGORITHM);
KeyStore keyStore;
keyStore = KeyStore.getInstance(KEY_STORE_FORMAT);
InputStream keyInput = new FileInputStream(pKeyFile);
keyStore.load(keyInput, pKeyPassword.toCharArray());
keyInput.close();
keyManagerFactory.init(keyStore, pKeyPassword.toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TRUST_MANAGER_ALGORITHM);
KeyStore trustStore;
trustStore = KeyStore.getInstance(TRUST_STORE_FORMAT);
InputStream trustStoreInput = new FileInputStream(pTrustStoreFile);
trustStore.load(trustStoreInput, pTrustStorePassword.toCharArray());
trustStoreInput.close();
trustManagerFactory.init(trustStore);
SSLContext context = SSLContext.getInstance(SSL_CONTEXT_ALGORITHM);
context.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());
socketFactory = context.getSocketFactory();
} catch (IOException e) {
if (e.toString().contains("keystore password was incorrect")) {
System.out.println("Contraseña del certificado inválida: " + pKeyFile.getName());
}
System.out.println(e.toString());
e.printStackTrace();
} catch (Exception e) {
System.out.println(e.toString());
e.printStackTrace();
return (socketFactory);
}
return socketFactory;
}
我解决了,我问自己是否可以帮助别人:
问题是我用了下面这句话:
conn.setInstanceFollowRedirects(true);
并且远程主机已重定向到具有不同 IP 地址的子域。所以在 JDK 的较新版本中,他们添加了一个限制,你不能重定向到不同的 ip 地址......它会清除你所有的请求数据。这就是为什么我的应用程序在 JDK 版本中有效,而在较新版本中无效。
我的解决方法是在没有 .instanceFollowRedirects 的情况下跟随重定向:
Map<String,List<String>> headers = conn.getHeaderFields();
if (headers.containsKey("Location")){
return cert_request(headers.get("Location").get(0),KEY_STORE_FILE,KEY_STORE_PASS,TRUST_STORE_FILE,TRUST_STORE_PASS,cookie);
}
基本上我return一个新的请求对象,新的URL和之前请求的参数,你可以随心所欲。
我有一个应用程序使用 HttpsURLConnection 与 pfx 文件和会话 cookie 来检索网页信息。
问题是,如果我像这样启动 jar,它是否有效:
"C:\Program Files\Java\jdk1.8.0_111\bin\java.exe" -jar "app"
但是如果我用我的 JRE 启动 jar,它就不起作用了:
java -jar "app.jar"
它只是没有得到认证...
我读了一些相关内容:How to provide ntlm authentication while calling any url?
但是禁用此 JRE "NTLM" 限制对我没有帮助。据我所知我没有使用 "NTLM".
谢谢你...
public void connect() {
try {
URL url = new URL(HTTPS_URL);
conn = (HttpsURLConnection) url.openConnection();
conn.setSSLSocketFactory(getFactory(new File(KEY_STORE_FILE), KEY_STORE_PASS, new File(TRUST_STORE_FILE), TRUST_STORE_PASS));
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Accept-Language", "es,es-ES;q=0.9,en;q=0.8,de;q=0.7");
conn.setInstanceFollowRedirects(true);
if (!cookies.isEmpty()) {
for (Map.Entry<String, String> entry : cookies.entrySet()) {
if (entry.getKey() != null && entry.getValue() != null) {
conn.setRequestProperty(entry.getKey(), entry.getValue());
}
}
}
conn.connect();
this.headers = conn.getHeaderFields();
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
responsebody += line;
}
br.close();
} catch (MalformedURLException e) {
System.out.println(e.toString());
e.printStackTrace();
} catch (SSLPeerUnverifiedException e) {
System.out.println(e.toString());
e.printStackTrace();
} catch (IOException e) {
System.out.println(e.toString());
e.printStackTrace();
}
}
private SSLSocketFactory getFactory(File pKeyFile, String pKeyPassword, File pTrustStoreFile, String pTrustStorePassword) {
SSLSocketFactory socketFactory = null;
try {
KeyManagerFactory keyManagerFactory;
keyManagerFactory = KeyManagerFactory.getInstance(KEY_MANAGER_ALGORITHM);
KeyStore keyStore;
keyStore = KeyStore.getInstance(KEY_STORE_FORMAT);
InputStream keyInput = new FileInputStream(pKeyFile);
keyStore.load(keyInput, pKeyPassword.toCharArray());
keyInput.close();
keyManagerFactory.init(keyStore, pKeyPassword.toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TRUST_MANAGER_ALGORITHM);
KeyStore trustStore;
trustStore = KeyStore.getInstance(TRUST_STORE_FORMAT);
InputStream trustStoreInput = new FileInputStream(pTrustStoreFile);
trustStore.load(trustStoreInput, pTrustStorePassword.toCharArray());
trustStoreInput.close();
trustManagerFactory.init(trustStore);
SSLContext context = SSLContext.getInstance(SSL_CONTEXT_ALGORITHM);
context.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());
socketFactory = context.getSocketFactory();
} catch (IOException e) {
if (e.toString().contains("keystore password was incorrect")) {
System.out.println("Contraseña del certificado inválida: " + pKeyFile.getName());
}
System.out.println(e.toString());
e.printStackTrace();
} catch (Exception e) {
System.out.println(e.toString());
e.printStackTrace();
return (socketFactory);
}
return socketFactory;
}
我解决了,我问自己是否可以帮助别人:
问题是我用了下面这句话:
conn.setInstanceFollowRedirects(true);
并且远程主机已重定向到具有不同 IP 地址的子域。所以在 JDK 的较新版本中,他们添加了一个限制,你不能重定向到不同的 ip 地址......它会清除你所有的请求数据。这就是为什么我的应用程序在 JDK 版本中有效,而在较新版本中无效。
我的解决方法是在没有 .instanceFollowRedirects 的情况下跟随重定向:
Map<String,List<String>> headers = conn.getHeaderFields();
if (headers.containsKey("Location")){
return cert_request(headers.get("Location").get(0),KEY_STORE_FILE,KEY_STORE_PASS,TRUST_STORE_FILE,TRUST_STORE_PASS,cookie);
}
基本上我return一个新的请求对象,新的URL和之前请求的参数,你可以随心所欲。