Java HTTP POST 和从 CURL 转换的 GET
Java HTTP POST and GET converted from CURL
嘿,我正在尽力将这个有效的 CURL 脚本转换为 Java:
@ECHO off
set COOKIES=.\cookies.txt
set USER=myUN
set PASSWORD="myPW"
set HOST=https://zzzzzzz.zzzzz.zz.zz:9443
cls
ECHO "Get the session cookie-------------------------------------"
set out1 = curl -k -c %cookies% "%host%/qm/authenticated/identity" > nul
ECHO "-----------------------------------------------------------"
ECHO "Use the session cookie to logon----------------------------"
curl -k -L -b %COOKIES% -c %COOKIES% -d j_username=%USER% -d j_password=%PASSWORD% %host%/qm/authenticated/j_security_check > nul
ECHO "-----------------------------------------------------------"
ECHO "Use the cookie to get the catalog--------------------------"
curl -k -L -b %COOKIES% -H "Accept: application/xml" %host%/qm/process/project-areas/_zzzzzzzzzzzzzzzzzzzz/members
ECHO "-----------------------------------------------------------"
其中:
-k: Allow insecure server connections when using SSL
-c <filename>: Write cookies to <filename> after operation
-L: Follow redirects
-b <data>: Send cookies from string/file
-H <header/@file>: Pass custom header(s) to server
-d <data>: HTTP POST data
我四处搜索 java 包含创建 cookie 示例的代码,但我还没有找到可以帮助我完成上述代码的代码。
我能找到并修改 POST 调用的最接近的是:
CookieStore cookieStore = new BasicCookieStore();
String USER = "myUN";
String PASSWORD = "myPW";
String HOST = "https://zzzzzzz.zzzzz.zz.zz:9443";
// CookieSpecs.STANDARD is the RFC 6265 compliant policy
RequestConfig requestConfig = RequestConfig
.custom()
.setCookieSpec(CookieSpecs.STANDARD)
.build();
// automatically follow redirects
CloseableHttpClient client = HttpClients
.custom()
.setRedirectStrategy(new LaxRedirectStrategy())
.setDefaultRequestConfig(requestConfig)
.setDefaultCookieStore(cookieStore)
.build();
HttpPost postIT = new HttpPost(HOST + "/qm/authenticated/identity");
List<NameValuePair> urlParams = new ArrayList<>();
urlParams.add(new BasicNameValuePair("j_username", USER));
urlParams.add(new BasicNameValuePair("j_password", PASSWORD));
postIT.setEntity(new UrlEncodedFormEntity(urlParams));
HttpResponse mmmCookie = client.execute(postIT);
// ... we have our cookie!
对于 postIT,值为:
POST https://zzzzz.zzz.zzzz.zzzz:9443/qm/authenticated/identity HTTP/1.1
但是,它有一个错误:
error: null
不确定为什么错误为空,因为 postIT 有数据?因此,我不仅无法 运行 我所做的修改后的代码,我仍然想知道如何使用 cookie 调用 GET 命令 即使上面的代码有效。
所以,简而言之:
- 修复 httpPost 错误。
- 如何在其他 GET 方法上发送 cookie。
帮助会很大!
VGR 更新:
public static void main(String[] args) throws IOException {
Path currentRelativePath = Paths.get("").toAbsolutePath();
PermissiveTrustManager blah = new PermissiveTrustManager();
blah.readMembers("https://zzzzzz.zzzz.zz.zzz:9443", "zzzzzz", "zzzzzzz", currentRelativePath);
}
错误在这一行:
check(tm -> tm.checkServerTrusted(certChain, authType, socket), socket);
certChain、authType、socket里面都有数据
由于我们不知道是什么导致了你的神秘错误,我建议放弃第三方库,并使用 java.net 包:
public void readMembers(String schemeAndAuthority,
String username,
String password,
Path membersFileToWrite)
throws IOException {
URI baseURI = URI.create(schemeAndAuthority);
CookieHandler oldCookieHandler = CookieHandler.getDefault();
boolean oldFollowRedirects = HttpURLConnection.getFollowRedirects();
CookieHandler.setDefault(new CookieManager());
HttpURLConnection.setFollowRedirects(true);
try {
HttpURLConnection connection;
URI authURI = baseURI.resolve("/qm/authenticated/identity");
connection = (HttpURLConnection) authURI.toURL().openConnection();
connection.getResponseCode();
URI securityURI = baseURI.resolve(
"/qm/authenticated/j_security_check");
String postData =
"j_username=" + URLEncoder.encode(username, "UTF-8") + "&" +
"j_password=" + URLEncoder.encode(password, "UTF-8");
connection = (HttpURLConnection)
securityURI.toURL().openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
connection.setDoOutput(true);
try (OutputStream postBody = connection.getOutputStream()) {
postBody.write(postData.getBytes(StandardCharsets.UTF_8));
}
connection.getResponseCode();
URI catalogURI = baseURI.resolve(
"/qm/process/project-areas/_zzzzzzzzzzzzzzzzzzzz/members");
connection = (HttpURLConnection)
catalogURI.toURL().openConnection();
connection.setRequestProperty("Accept", "application/xml");
try (InputStream responseBody = connection.getInputStream()) {
Files.copy(responseBody, membersFileToWrite);
}
} finally {
CookieHandler.setDefault(oldCookieHandler);
HttpURLConnection.setFollowRedirects(oldFollowRedirects);
}
}
但是,上面的代码没有提供与 curl 的 -k
选项等效的选项。为此,我们必须创建一个允许所有证书的自定义 SSLContext, initialized with a TrustManager:
static class PermissiveTrustManager
extends X509ExtendedTrustManager {
private final X509ExtendedTrustManager[] realTrustManagers;
private interface Checker {
void checkWith(X509ExtendedTrustManager realTrustManager)
throws CertificateException;
}
PermissiveTrustManager() {
TrustManagerFactory factory;
try {
factory = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
factory.init((KeyStore) null);
} catch (GeneralSecurityException e) {
// We should not be able to get here.
throw new RuntimeException(e);
}
TrustManager[] allTrustManagers = factory.getTrustManagers();
realTrustManagers = Arrays.stream(allTrustManagers)
.filter(tm -> tm instanceof X509ExtendedTrustManager)
.map(tm -> (X509ExtendedTrustManager) tm)
.toArray(X509ExtendedTrustManager[]::new);
}
private void check(Checker checker) {
try {
for (X509ExtendedTrustManager realTrustManager : realTrustManagers) {
checker.checkWith(realTrustManager);
}
} catch (CertificateException e) {
System.err.println("Ignoring invalid certificate");
e.printStackTrace();
}
}
private void check(Checker checker,
Socket socket) {
try {
for (X509ExtendedTrustManager realTrustManager : realTrustManagers) {
checker.checkWith(realTrustManager);
}
} catch (CertificateException e) {
System.err.println("Ignoring invalid certificate for " +
socket.getRemoteSocketAddress());
e.printStackTrace();
}
}
@Override
public void checkClientTrusted(X509Certificate[] certChain,
String authType,
Socket socket) {
check(tm -> tm.checkClientTrusted(certChain, authType, socket), socket);
}
@Override
public void checkClientTrusted(X509Certificate[] certChain,
String authType,
SSLEngine engine) {
check(tm -> tm.checkClientTrusted(certChain, authType, engine));
}
@Override
public void checkServerTrusted(X509Certificate[] certChain,
String authType,
Socket socket) {
check(tm -> tm.checkServerTrusted(certChain, authType, socket), socket);
}
@Override
public void checkServerTrusted(X509Certificate[] certChain,
String authType,
SSLEngine engine) {
check(tm -> tm.checkServerTrusted(certChain, authType, engine));
}
@Override
public void checkClientTrusted(X509Certificate[] certChain,
String authType) {
check(tm -> tm.checkClientTrusted(certChain, authType));
}
@Override
public void checkServerTrusted(X509Certificate[] certChain,
String authType) {
check(tm -> tm.checkServerTrusted(certChain, authType));
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
private static SSLContext createPermissiveSSLContext()
throws IOException {
TrustManager[] trustManagers = { new PermissiveTrustManager() };
try {
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, trustManagers, null);
return context;
} catch (GeneralSecurityException e) {
throw new IOException(e);
}
}
public void readMembers(String schemeAndAuthority,
String username,
String password,
Path membersFileToWrite)
throws IOException {
URI baseURI = URI.create(schemeAndAuthority);
CookieHandler oldCookieHandler = CookieHandler.getDefault();
boolean oldFollowRedirects = HttpURLConnection.getFollowRedirects();
SSLContext oldSSLContext = null;
try {
oldSSLContext = SSLContext.getDefault();
} catch (GeneralSecurityException e) {
e.printStackTrace();
}
CookieHandler.setDefault(new CookieManager());
HttpURLConnection.setFollowRedirects(true);
SSLContext.setDefault(createPermissiveSSLContext());
try {
HttpURLConnection connection;
URI authURI = baseURI.resolve("/qm/authenticated/identity");
connection = (HttpURLConnection) authURI.toURL().openConnection();
connection.getResponseCode();
URI securityURI = baseURI.resolve(
"/qm/authenticated/j_security_check");
String postData =
"j_username=" + URLEncoder.encode(username, "UTF-8") + "&" +
"j_password=" + URLEncoder.encode(password, "UTF-8");
connection = (HttpURLConnection)
securityURI.toURL().openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
connection.setDoOutput(true);
try (OutputStream postBody = connection.getOutputStream()) {
postBody.write(postData.getBytes(StandardCharsets.UTF_8));
}
connection.getResponseCode();
URI catalogURI = baseURI.resolve(
"/qm/process/project-areas/_zzzzzzzzzzzzzzzzzzzz/members");
connection = (HttpURLConnection)
catalogURI.toURL().openConnection();
connection.setRequestProperty("Accept", "application/xml");
try (InputStream responseBody = connection.getInputStream()) {
Files.copy(responseBody, membersFileToWrite);
}
} finally {
CookieHandler.setDefault(oldCookieHandler);
HttpURLConnection.setFollowRedirects(oldFollowRedirects);
if (oldSSLContext != null) {
SSLContext.setDefault(oldSSLContext);
}
}
}
显然,我无法对此进行测试。
您可以这样调用方法:
new CatalogRetriever().readMembers(
"https://zzzzzzz.zzzzz.zz.zz:9443", "myUN", "myPW",
Paths.get("members"));
如the URI docs所述,方案是http:
或https:
部分。权限是 //
后跟 hostname/port(和可选的 user/password,具体取决于协议)。
嘿,我正在尽力将这个有效的 CURL 脚本转换为 Java:
@ECHO off
set COOKIES=.\cookies.txt
set USER=myUN
set PASSWORD="myPW"
set HOST=https://zzzzzzz.zzzzz.zz.zz:9443
cls
ECHO "Get the session cookie-------------------------------------"
set out1 = curl -k -c %cookies% "%host%/qm/authenticated/identity" > nul
ECHO "-----------------------------------------------------------"
ECHO "Use the session cookie to logon----------------------------"
curl -k -L -b %COOKIES% -c %COOKIES% -d j_username=%USER% -d j_password=%PASSWORD% %host%/qm/authenticated/j_security_check > nul
ECHO "-----------------------------------------------------------"
ECHO "Use the cookie to get the catalog--------------------------"
curl -k -L -b %COOKIES% -H "Accept: application/xml" %host%/qm/process/project-areas/_zzzzzzzzzzzzzzzzzzzz/members
ECHO "-----------------------------------------------------------"
其中:
-k: Allow insecure server connections when using SSL
-c <filename>: Write cookies to <filename> after operation
-L: Follow redirects
-b <data>: Send cookies from string/file
-H <header/@file>: Pass custom header(s) to server
-d <data>: HTTP POST data
我四处搜索 java 包含创建 cookie 示例的代码,但我还没有找到可以帮助我完成上述代码的代码。
我能找到并修改 POST 调用的最接近的是:
CookieStore cookieStore = new BasicCookieStore();
String USER = "myUN";
String PASSWORD = "myPW";
String HOST = "https://zzzzzzz.zzzzz.zz.zz:9443";
// CookieSpecs.STANDARD is the RFC 6265 compliant policy
RequestConfig requestConfig = RequestConfig
.custom()
.setCookieSpec(CookieSpecs.STANDARD)
.build();
// automatically follow redirects
CloseableHttpClient client = HttpClients
.custom()
.setRedirectStrategy(new LaxRedirectStrategy())
.setDefaultRequestConfig(requestConfig)
.setDefaultCookieStore(cookieStore)
.build();
HttpPost postIT = new HttpPost(HOST + "/qm/authenticated/identity");
List<NameValuePair> urlParams = new ArrayList<>();
urlParams.add(new BasicNameValuePair("j_username", USER));
urlParams.add(new BasicNameValuePair("j_password", PASSWORD));
postIT.setEntity(new UrlEncodedFormEntity(urlParams));
HttpResponse mmmCookie = client.execute(postIT);
// ... we have our cookie!
对于 postIT,值为:
POST https://zzzzz.zzz.zzzz.zzzz:9443/qm/authenticated/identity HTTP/1.1
但是,它有一个错误:
error: null
不确定为什么错误为空,因为 postIT 有数据?因此,我不仅无法 运行 我所做的修改后的代码,我仍然想知道如何使用 cookie 调用 GET 命令 即使上面的代码有效。
所以,简而言之:
- 修复 httpPost 错误。
- 如何在其他 GET 方法上发送 cookie。
帮助会很大!
VGR 更新:
public static void main(String[] args) throws IOException {
Path currentRelativePath = Paths.get("").toAbsolutePath();
PermissiveTrustManager blah = new PermissiveTrustManager();
blah.readMembers("https://zzzzzz.zzzz.zz.zzz:9443", "zzzzzz", "zzzzzzz", currentRelativePath);
}
错误在这一行:
check(tm -> tm.checkServerTrusted(certChain, authType, socket), socket);
certChain、authType、socket里面都有数据
由于我们不知道是什么导致了你的神秘错误,我建议放弃第三方库,并使用 java.net 包:
public void readMembers(String schemeAndAuthority,
String username,
String password,
Path membersFileToWrite)
throws IOException {
URI baseURI = URI.create(schemeAndAuthority);
CookieHandler oldCookieHandler = CookieHandler.getDefault();
boolean oldFollowRedirects = HttpURLConnection.getFollowRedirects();
CookieHandler.setDefault(new CookieManager());
HttpURLConnection.setFollowRedirects(true);
try {
HttpURLConnection connection;
URI authURI = baseURI.resolve("/qm/authenticated/identity");
connection = (HttpURLConnection) authURI.toURL().openConnection();
connection.getResponseCode();
URI securityURI = baseURI.resolve(
"/qm/authenticated/j_security_check");
String postData =
"j_username=" + URLEncoder.encode(username, "UTF-8") + "&" +
"j_password=" + URLEncoder.encode(password, "UTF-8");
connection = (HttpURLConnection)
securityURI.toURL().openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
connection.setDoOutput(true);
try (OutputStream postBody = connection.getOutputStream()) {
postBody.write(postData.getBytes(StandardCharsets.UTF_8));
}
connection.getResponseCode();
URI catalogURI = baseURI.resolve(
"/qm/process/project-areas/_zzzzzzzzzzzzzzzzzzzz/members");
connection = (HttpURLConnection)
catalogURI.toURL().openConnection();
connection.setRequestProperty("Accept", "application/xml");
try (InputStream responseBody = connection.getInputStream()) {
Files.copy(responseBody, membersFileToWrite);
}
} finally {
CookieHandler.setDefault(oldCookieHandler);
HttpURLConnection.setFollowRedirects(oldFollowRedirects);
}
}
但是,上面的代码没有提供与 curl 的 -k
选项等效的选项。为此,我们必须创建一个允许所有证书的自定义 SSLContext, initialized with a TrustManager:
static class PermissiveTrustManager
extends X509ExtendedTrustManager {
private final X509ExtendedTrustManager[] realTrustManagers;
private interface Checker {
void checkWith(X509ExtendedTrustManager realTrustManager)
throws CertificateException;
}
PermissiveTrustManager() {
TrustManagerFactory factory;
try {
factory = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
factory.init((KeyStore) null);
} catch (GeneralSecurityException e) {
// We should not be able to get here.
throw new RuntimeException(e);
}
TrustManager[] allTrustManagers = factory.getTrustManagers();
realTrustManagers = Arrays.stream(allTrustManagers)
.filter(tm -> tm instanceof X509ExtendedTrustManager)
.map(tm -> (X509ExtendedTrustManager) tm)
.toArray(X509ExtendedTrustManager[]::new);
}
private void check(Checker checker) {
try {
for (X509ExtendedTrustManager realTrustManager : realTrustManagers) {
checker.checkWith(realTrustManager);
}
} catch (CertificateException e) {
System.err.println("Ignoring invalid certificate");
e.printStackTrace();
}
}
private void check(Checker checker,
Socket socket) {
try {
for (X509ExtendedTrustManager realTrustManager : realTrustManagers) {
checker.checkWith(realTrustManager);
}
} catch (CertificateException e) {
System.err.println("Ignoring invalid certificate for " +
socket.getRemoteSocketAddress());
e.printStackTrace();
}
}
@Override
public void checkClientTrusted(X509Certificate[] certChain,
String authType,
Socket socket) {
check(tm -> tm.checkClientTrusted(certChain, authType, socket), socket);
}
@Override
public void checkClientTrusted(X509Certificate[] certChain,
String authType,
SSLEngine engine) {
check(tm -> tm.checkClientTrusted(certChain, authType, engine));
}
@Override
public void checkServerTrusted(X509Certificate[] certChain,
String authType,
Socket socket) {
check(tm -> tm.checkServerTrusted(certChain, authType, socket), socket);
}
@Override
public void checkServerTrusted(X509Certificate[] certChain,
String authType,
SSLEngine engine) {
check(tm -> tm.checkServerTrusted(certChain, authType, engine));
}
@Override
public void checkClientTrusted(X509Certificate[] certChain,
String authType) {
check(tm -> tm.checkClientTrusted(certChain, authType));
}
@Override
public void checkServerTrusted(X509Certificate[] certChain,
String authType) {
check(tm -> tm.checkServerTrusted(certChain, authType));
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}
private static SSLContext createPermissiveSSLContext()
throws IOException {
TrustManager[] trustManagers = { new PermissiveTrustManager() };
try {
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, trustManagers, null);
return context;
} catch (GeneralSecurityException e) {
throw new IOException(e);
}
}
public void readMembers(String schemeAndAuthority,
String username,
String password,
Path membersFileToWrite)
throws IOException {
URI baseURI = URI.create(schemeAndAuthority);
CookieHandler oldCookieHandler = CookieHandler.getDefault();
boolean oldFollowRedirects = HttpURLConnection.getFollowRedirects();
SSLContext oldSSLContext = null;
try {
oldSSLContext = SSLContext.getDefault();
} catch (GeneralSecurityException e) {
e.printStackTrace();
}
CookieHandler.setDefault(new CookieManager());
HttpURLConnection.setFollowRedirects(true);
SSLContext.setDefault(createPermissiveSSLContext());
try {
HttpURLConnection connection;
URI authURI = baseURI.resolve("/qm/authenticated/identity");
connection = (HttpURLConnection) authURI.toURL().openConnection();
connection.getResponseCode();
URI securityURI = baseURI.resolve(
"/qm/authenticated/j_security_check");
String postData =
"j_username=" + URLEncoder.encode(username, "UTF-8") + "&" +
"j_password=" + URLEncoder.encode(password, "UTF-8");
connection = (HttpURLConnection)
securityURI.toURL().openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
connection.setDoOutput(true);
try (OutputStream postBody = connection.getOutputStream()) {
postBody.write(postData.getBytes(StandardCharsets.UTF_8));
}
connection.getResponseCode();
URI catalogURI = baseURI.resolve(
"/qm/process/project-areas/_zzzzzzzzzzzzzzzzzzzz/members");
connection = (HttpURLConnection)
catalogURI.toURL().openConnection();
connection.setRequestProperty("Accept", "application/xml");
try (InputStream responseBody = connection.getInputStream()) {
Files.copy(responseBody, membersFileToWrite);
}
} finally {
CookieHandler.setDefault(oldCookieHandler);
HttpURLConnection.setFollowRedirects(oldFollowRedirects);
if (oldSSLContext != null) {
SSLContext.setDefault(oldSSLContext);
}
}
}
显然,我无法对此进行测试。
您可以这样调用方法:
new CatalogRetriever().readMembers(
"https://zzzzzzz.zzzzz.zz.zz:9443", "myUN", "myPW",
Paths.get("members"));
如the URI docs所述,方案是http:
或https:
部分。权限是 //
后跟 hostname/port(和可选的 user/password,具体取决于协议)。