Android HttpUrlConnection 无法 Post - 错误 403
Android HttpUrlConnection Cannot Post - Error 403
我正在尝试使用 spring 安全 csrf 针对我的网络服务发布 HttpPost。
首先,我尝试通过 GET 请求恢复 XSRF TOKEN,就像这样
public static CookieManager xcsrfToken() throws IOException{
String token;
URL url = new URL(urlBase);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
CookieManager cookieManager = new CookieManager();
con.connect();
List<String> cookieHeader = con.getHeaderFields().get("Set-Cookie");
if (cookieHeader != null) {
for (String cookie : cookieHeader) {
cookieManager.getCookieStore().add(null, HttpCookie.parse(cookie).get(0));
}
}
System.out.println(con.getHeaderFields());
con.disconnect();
return cookieManager;
}
这是我从 con.getHeaderFields()
中得到的
{null=[HTTP/1.1 200 OK], Cache-Control=[no-cache, no-store, max-age=0, must-revalidate], Content-Language=[pt-BR], Content-Length=[973], Content-Type=[text/html;charset=ISO-8859-1], Date=[Wed, 19 Aug 2015 10:40:18 GMT], Expires=[0], Pragma=[no-cache], Server=[Apache-Coyote/1.1], Set-Cookie=[JSESSIONID=6C9326FBEEA14752068720006F2B5EAA; Path=/webapi/; HttpOnly, XSRF-TOKEN=07cbed7f-834e-4146-8537-0a6b5669f223; Path=/], X-Android-Received-Millis=[1439980819720], X-Android-Response-Source=[NETWORK 200], X-Android-Sent-Millis=[1439980819693], X-Content-Type-Options=[nosniff], X-Frame-Options=[DENY], X-XSS-Protection=[1; mode=block]}
XSRF-TOKEN在我的cookie里,好吧!
如果我打印然后用
System.out.println(cookieManager.getCookieStore().getCookies());
我明白了
[JSESSIONID=5B1D3E2D3E7B3E1E6572A3839BFF3741, XSRF-TOKEN=4d4048bd-f21c-48c6-895e-5f67523ad963]
现在,我正在尝试对服务器发出 POST,就像这样
public static HttpURLConnection makeRequest(String metodo, String uri, String requestBody) throws IOException{
URL url = new URL(urlBase + uri);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setDoInput(true);
con.setDoOutput(!metodo.equals("GET"));
con.setRequestProperty("Content-Type", "application/json");
con.setRequestProperty("Cookie", TextUtils.join("," , xcsrfToken().getCookieStore().getCookies()));
con.connect();
InputStream is = con.getErrorStream();
System.out.println(IOUtils.toString(is, "UTF-8"));
System.out.println(con.getHeaderFields());
return con;
}
但是 header 没有 cookie 就回来了
{null=[HTTP/1.1 403 Forbidden], Cache-Control=[no-cache, no-store, max-age=0, must-revalidate], Content-Language=[en], Content-Length=[1149], Content-Type=[text/html;charset=utf-8], Date=[Wed, 19 Aug 2015 10:42:18 GMT], Expires=[0], Pragma=[no-cache], Server=[Apache-Coyote/1.1], X-Android-Received-Millis=[1439980939827], X-Android-Response-Source=[NETWORK 403], X-Android-Sent-Millis=[1439980939811], X-Content-Type-Options=[nosniff], X-Frame-Options=[DENY], X-XSS-Protection=[1; mode=block]}
它说没有 CSRF 有效令牌
Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-XSRF-TOKEN'.
在我的网络服务中,由于 angularJs.
,令牌被配置为重命名为 XSRF-TOKEN
解决方案
public static void getTokens() throws IOException{
URL url = new URL(urlBase);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
con.connect();
cookieManager = new CookieManager();
List<String> cookieHeader = con.getHeaderFields().get("Set-Cookie");
if (cookieHeader != null) {
for (String cookie : cookieHeader) {
String[] tokens = TextUtils.split(cookie, "=");
if (tokens[0].equals("JSESSIONID"))
cookieManager.getCookieStore().add(null, HttpCookie.parse(cookie).get(0));
if (tokens[0].equals("XSRF-TOKEN")) {
String[] tokenValue = TextUtils.split(tokens[1],";");
xsrfTOKEN = tokenValue[0];
}
}
}
con.disconnect();
}
然后,将其附加到 HttpUrlConnection
con.setRequestProperty("X-XSRF-TOKEN", xsrfTOKEN);
根据我的经验,我们需要将令牌作为请求提交 header。 Spring 默认情况下其名称为 X-CSRF-TOKEN
。但是使用 AngularJS 的人通常会在 Spring 安全配置中将其更改为 X-XSRF-TOKEN
。
但是查看您的代码,我无法确定您是否发送 header。
如果有帮助,这里是我的一个项目的片段(使用 RestAssured):
if (xsrfToken != null && !ctx.getRequestMethod().equals(Method.GET))
requestSpec.header("X-XSRF-TOKEN", xsrfToken);
我正在尝试使用 spring 安全 csrf 针对我的网络服务发布 HttpPost。
首先,我尝试通过 GET 请求恢复 XSRF TOKEN,就像这样
public static CookieManager xcsrfToken() throws IOException{
String token;
URL url = new URL(urlBase);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
CookieManager cookieManager = new CookieManager();
con.connect();
List<String> cookieHeader = con.getHeaderFields().get("Set-Cookie");
if (cookieHeader != null) {
for (String cookie : cookieHeader) {
cookieManager.getCookieStore().add(null, HttpCookie.parse(cookie).get(0));
}
}
System.out.println(con.getHeaderFields());
con.disconnect();
return cookieManager;
}
这是我从 con.getHeaderFields()
中得到的{null=[HTTP/1.1 200 OK], Cache-Control=[no-cache, no-store, max-age=0, must-revalidate], Content-Language=[pt-BR], Content-Length=[973], Content-Type=[text/html;charset=ISO-8859-1], Date=[Wed, 19 Aug 2015 10:40:18 GMT], Expires=[0], Pragma=[no-cache], Server=[Apache-Coyote/1.1], Set-Cookie=[JSESSIONID=6C9326FBEEA14752068720006F2B5EAA; Path=/webapi/; HttpOnly, XSRF-TOKEN=07cbed7f-834e-4146-8537-0a6b5669f223; Path=/], X-Android-Received-Millis=[1439980819720], X-Android-Response-Source=[NETWORK 200], X-Android-Sent-Millis=[1439980819693], X-Content-Type-Options=[nosniff], X-Frame-Options=[DENY], X-XSS-Protection=[1; mode=block]}
XSRF-TOKEN在我的cookie里,好吧! 如果我打印然后用 System.out.println(cookieManager.getCookieStore().getCookies()); 我明白了
[JSESSIONID=5B1D3E2D3E7B3E1E6572A3839BFF3741, XSRF-TOKEN=4d4048bd-f21c-48c6-895e-5f67523ad963]
现在,我正在尝试对服务器发出 POST,就像这样
public static HttpURLConnection makeRequest(String metodo, String uri, String requestBody) throws IOException{
URL url = new URL(urlBase + uri);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setDoInput(true);
con.setDoOutput(!metodo.equals("GET"));
con.setRequestProperty("Content-Type", "application/json");
con.setRequestProperty("Cookie", TextUtils.join("," , xcsrfToken().getCookieStore().getCookies()));
con.connect();
InputStream is = con.getErrorStream();
System.out.println(IOUtils.toString(is, "UTF-8"));
System.out.println(con.getHeaderFields());
return con;
}
但是 header 没有 cookie 就回来了
{null=[HTTP/1.1 403 Forbidden], Cache-Control=[no-cache, no-store, max-age=0, must-revalidate], Content-Language=[en], Content-Length=[1149], Content-Type=[text/html;charset=utf-8], Date=[Wed, 19 Aug 2015 10:42:18 GMT], Expires=[0], Pragma=[no-cache], Server=[Apache-Coyote/1.1], X-Android-Received-Millis=[1439980939827], X-Android-Response-Source=[NETWORK 403], X-Android-Sent-Millis=[1439980939811], X-Content-Type-Options=[nosniff], X-Frame-Options=[DENY], X-XSS-Protection=[1; mode=block]}
它说没有 CSRF 有效令牌
Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-XSRF-TOKEN'.
在我的网络服务中,由于 angularJs.
,令牌被配置为重命名为 XSRF-TOKEN解决方案
public static void getTokens() throws IOException{
URL url = new URL(urlBase);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
con.connect();
cookieManager = new CookieManager();
List<String> cookieHeader = con.getHeaderFields().get("Set-Cookie");
if (cookieHeader != null) {
for (String cookie : cookieHeader) {
String[] tokens = TextUtils.split(cookie, "=");
if (tokens[0].equals("JSESSIONID"))
cookieManager.getCookieStore().add(null, HttpCookie.parse(cookie).get(0));
if (tokens[0].equals("XSRF-TOKEN")) {
String[] tokenValue = TextUtils.split(tokens[1],";");
xsrfTOKEN = tokenValue[0];
}
}
}
con.disconnect();
}
然后,将其附加到 HttpUrlConnection
con.setRequestProperty("X-XSRF-TOKEN", xsrfTOKEN);
根据我的经验,我们需要将令牌作为请求提交 header。 Spring 默认情况下其名称为 X-CSRF-TOKEN
。但是使用 AngularJS 的人通常会在 Spring 安全配置中将其更改为 X-XSRF-TOKEN
。
但是查看您的代码,我无法确定您是否发送 header。
如果有帮助,这里是我的一个项目的片段(使用 RestAssured):
if (xsrfToken != null && !ctx.getRequestMethod().equals(Method.GET))
requestSpec.header("X-XSRF-TOKEN", xsrfToken);