2015-07-21 28 views
1

使用Jersey 2.19,如何從使用Spring Security 3的服務器獲取CSRF令牌併成功登錄?我有兩個項目,一個使用REST的客戶端和一個使用JHipster創建的服務器。使用Jersey通過REST獲取CSRF令牌並在登錄中使用它

首先,我正在做一個GET請求到http://localhost:8080和我得到這個響應頭:

Cache-Control:no-cache, no-store, max-age=0, must-revalidate 
Content-Language:en 
Content-Length:17229 
Content-Type:text/html;charset=utf-8 
Date:Tue, 21 Jul 2015 19:24:40 GMT 
Expires:0 
Last-Modified:Thu, 02 Jul 2015 17:07:31 GMT 
Pragma:no-cache 
Server:Apache-Coyote/1.1 
Set-Cookie:CSRF-TOKEN=0902449b-bac7-43e8-bf24-9ec2c1faa48b; Path=/ 
X-Application-Context:application:dev:8081 
X-Content-Type-Options:nosniff 
X-XSS-Protection:1; mode=block 

我提取的Set-Cookie頭,我從那裏得到的CSRF令牌。然後我做一個POST請求是這樣的:

http://localhost:8080/api/authentication?j_username=user&j_password=user&submit=Login 

有了這個請求頭:

Content-Type: application/x-www-form-urlencoded 
X-CSRF-TOKEN: <extracted token> 

使用Chrome的插件郵遞員,我可以爲登錄正確的post請求,但新澤西州,我無法正確發送CSRF令牌(我得到403響應)。

這是響應:

{"timestamp":1437507680089,"status":403,"error":"Forbidden","message":"Expected CSRF token not found. Has your session expired?","path":"/api/authentication"} 

這是球衣代碼:

WebTarget hostTarget = getClient().target("http://localhost:8080"); 

Response r = hostTarget.request().get(); 
String header = r.getHeaderString("Set-Cookie"); 
String csrf = null; 

List<HttpCookie> cookies = HttpCookie.parse(header); 

for (HttpCookie c : cookies) { 
    if("CSRF-TOKEN".equals(c.getName())){ 
     csrf = c.getValue(); 
     break; 
    } 
} 

WebTarget loginTarget = hostTarget.path("/api/authentication"); 
loginTarget = loginTarget.queryParam("j_username", username) 
    .queryParam("j_password", password) 
    .queryParam("submit", "Login"); 

Builder req = loginTarget.request(MediaType.APPLICATION_JSON_TYPE); 
if (csrf != null) { 
    req = req.header("X-CSRF-TOKEN", csrf); 
} 

Response cr = req.post(Entity.entity(null, 
     MediaType.APPLICATION_FORM_URLENCODED_TYPE)); 

System.out.println("Response: " + cr.readEntity(String.class)); 

感謝您的時間。

+1

您是否在通過郵遞員發送CSRF cookie令牌不可用時進行檢查?也許調用成功,因爲cookie可用於令牌 –

+0

使用郵遞員,如果我省略了X-CSRF-TOKEN我在請求參數'_csrf'或頭部'X-CSRF'上找到「403無效的CSRF令牌null' -TOKEN」。」使用_csrf作爲請求參數或所提到的標題與郵遞員一起工作。不過,當我在客戶端代碼中省略CSRF令牌用法時,我仍然得到問題中提到的403響應。 – dovahkiin

回答

1

經過多次試驗和錯誤,我找到了解決方案。重要的是要採取計數cookies(如羅曼沃特納所示)REST配置與春季安全進行通信。必須存在的重要cookie是JSESSIONID和標題X-CSRF-TOKEN(或者服務器中配置的任何標題名稱),因此將它們捕獲到初始請求中並再次發送。

我決定以這種方式將所有的cookie發送到服務器。

WebTarget hostTarget = getClient().target("http://localhost:8080"); 

Response r = hostTarget.request().get(); 
String headerCookies = r.getHeaderString("Set-Cookie"); 

Map<String, NewCookie> cookies = r.getCookies(); 
String csrf = cookies.get("CSRF-TOKEN").getValue(); 

WebTarget loginTarget = hostTarget.path("/api/authentication"); 
loginTarget = loginTarget.queryParam("j_username", username) 
    .queryParam("j_password", password) 
    .queryParam("submit", "Login"); 

Builder req = loginTarget.request(MediaType.APPLICATION_JSON_TYPE); 
req = req.header("Cookie", headerCookies); 

if (csrf != null) { 
    req = req.header("X-CSRF-TOKEN", csrf); 
} 

Response cr = req.post(Entity.entity(null, 
     MediaType.APPLICATION_FORM_URLENCODED_TYPE)); 

//The response is empty (in my case) with status code 200 
System.out.println("Response: " + cr.readEntity(String.class)); 
相關問題