具有CSRF保护的Java Jersey POST请求
我有一个SpringBootREST服务,它提供了一些方法。它们受CSRF和用户名/密码基本身份验证(https)保护 但是,当我尝试执行POST请求时,它失败,状态代码为403,并显示消息“无法验证提供的CSRF令牌,因为找不到您的会话” 这是我的客户代码:具有CSRF保护的Java Jersey POST请求,java,spring,jersey,jersey-2.0,jersey-client,Java,Spring,Jersey,Jersey 2.0,Jersey Client,我有一个SpringBootREST服务,它提供了一些方法。它们受CSRF和用户名/密码基本身份验证(https)保护 但是,当我尝试执行POST请求时,它失败,状态代码为403,并显示消息“无法验证提供的CSRF令牌,因为找不到您的会话” 这是我的客户代码: ApiMessage msg = new ApiMessage("Client1", "Key1", "Value1"); // Set up Basic Authentication HttpAuthentic
ApiMessage msg = new ApiMessage("Client1", "Key1", "Value1");
// Set up Basic Authentication
HttpAuthenticationFeature feature = HttpAuthenticationFeature.basicBuilder()
.nonPreemptive()
.credentials(ApiUser, ApiUserPassword)
.build();
ClientConfig clientConfig = new ClientConfig();
clientConfig.register(feature);
Client client = ClientBuilder.newClient(clientConfig);
// Set up client and target (ApiHost = URI for the request Ressource)
WebTarget target = client.target(ApiHost);
WebTarget checkTarget = target.path("check");
Invocation.Builder invocationBuilder = checkTarget.request(MediaType.APPLICATION_JSON);
// Do a first request to get the CSRF Header
Response response = invocationBuilder.post(Entity.entity(msg, MediaType.APPLICATION_JSON));
if (response.getStatus() == 200) {
System.out.println("Without CSRF - everything worked. ");
} else if (response.getStatus() == 403) {
System.out.println("CSRF Protection: " + response.getStatus() + response.readEntity(String.class));
// Get CSRF Token out of the response
Map<String, NewCookie> cookies = response.getCookies();
String csrf = cookies.get("XSRF-TOKEN").getValue();
// Add the Token to the header and POST again
invocationBuilder.header("X-XSRF-TOKEN", csrf);
response = invocationBuilder.post(Entity.entity(msg, MediaType.APPLICATION_JSON));
if (response.getStatus() != 200) {
System.out.println("Error: " + response.getStatus() + response.readEntity(String.class));
} else {
System.out.println("With CSRF - everything worked. ");
}
} else {
System.out.println(response.getStatus() + " " + response.readEntity(String.class));
}
ApiMessage msg=新的ApiMessage(“Client1”、“Key1”、“Value1”);
//设置基本身份验证
HttpAuthenticationFeature=HttpAuthenticationFeature.basicBuilder()
.非强制性的
.凭据(ApiUser、ApiUserPassword)
.build();
ClientConfig ClientConfig=new ClientConfig();
clientConfig.register(功能);
Client Client=ClientBuilder.newClient(clientConfig);
//设置客户端和目标(请求资源的ApiHost=URI)
WebTarget=client.target(ApiHost);
WebTarget checkTarget=target.path(“检查”);
Invocation.Builder invocationBuilder=checkTarget.request(MediaType.APPLICATION\ujson);
//执行第一个请求以获取CSRF头
Response-Response=invocationBuilder.post(Entity.Entity(msg,MediaType.APPLICATION_JSON));
if(response.getStatus()==200){
System.out.println(“没有CSRF-一切正常”);
}else if(response.getStatus()==403){
System.out.println(“CSRF保护:+response.getStatus()+response.readEntity(String.class));
//从响应中获取CSRF令牌
映射cookies=response.getCookies();
字符串csrf=cookies.get(“XSRF-TOKEN”).getValue();
//将令牌添加到标题并再次发布
invocationBuilder.header(“X-XSRF-TOKEN”,csrf);
response=invocationBuilder.post(Entity.Entity(msg,MediaType.APPLICATION_JSON));
if(response.getStatus()!=200){
System.out.println(“错误:+response.getStatus()+response.readEntity(String.class));
}否则{
System.out.println(“使用CSRF-一切正常”);
}
}否则{
System.out.println(response.getStatus()+“”+response.readEntity(String.class));
}
第一个请求以状态403结束,消息“无法验证提供的CSRF令牌,因为找不到您的会话”。
之后,我成功地从响应头中提取CSRF令牌。
但是,第二个带有CSRF头的请求失败,并出现相同的错误
在邮递员身上做同样的事也行
知道我的错误在哪里吗?我做错了什么吗?可能还有一个会话cookie需要发送回去,比如JSESSIONID。拿那块饼干。从
NewCookie
创建Cookie
,并将其添加到请求中
NewCookie session = cookies.get("JSESSIONID");
Cookie cookie = session.toCookie();
invocationBuilder.cookie(cookie);
如果不是JSESSIONID,请检查所有cookies。可能是其他原因。调用Map cookies=response.getCookies()时,只有一个Cookie返回;在《邮差》中,我可以看到两个cookie:XSRF-TOKEN和JSESSIONID。但是在我的Java客户机中,我只得到XSRF令牌,这很奇怪。我将在稍后进行测试。首先,我对我喜欢访问的资源执行POST请求,并对其进行基本身份验证。我得到了两个cookie:XSRF-TOKEN和JSESSIONID。然后,我用cookie XSRF-TOKEN的值设置头X-XSRF-TOKEN,并将POST请求重新发送到同一个资源,您在Postman中第一个请求返回的请求是403?这就是你上面的代码所暗示的。是的,邮递员的第一个答案是403。第二个请求(带有CSRF头)以200结尾。