Spring 未找到安全 4 curl csrf 令牌
Spring Security 4 curl csrf token not found
我知道这个问题以前被问过很多,它适用于很多不同的方式,基于我已经在网上和这里问过的问题,我的问题多于我的答案。
所以,我有一个 Spring MVC 4.0 RESTful web-service,我知道它工作正常。我知道它工作正常,因为它通过了我的单元测试。增加安全性的单元测试和作为测试安全性一部分的 "csrf()" 使其工作。我确实注意到添加了这条数据:
Parameters = {_csrf=[435f9968-f643-47e9-9d15-23a5cb361b1d]}
RESTful web-service 使用 Spring Security 4 保护,默认启用 csrf 保护。所有带有 GET 的 web-service 都很好用,正是 POST 阻碍了我的 403 错误。
这是我要实现的卷曲:
curl \
-d '{"SiteId\:"548","SubjectId":TEST_sub","description":"TEST_des"}' \
--cookie "csrftoken=?????????????" \
--cookie "JSESSIONID=openam~A7FF59011F982FBB91C2F908E143327D" \
--cookie "iPlanetDirectoryPro=AQIC5wM2LY4Sfcy_7ZIwOhUsE4KK922nQEue1Bgm7wAtX_k.*AAJTSQACMDE.*; path=/; domain=.mydomain.net" \
-H "X-CSFRToken: ??????" -H "Accept: */*" -H "Content-Type: */*" \
-H "openam-token: AQIC5wM2LY4Sfcy_7ZIwOhUsE4KK922nQEue1Bgm7wAtX_k.*AAJTSQACMDE.*" \
https://spring.mydomain.net/api/subject/build
所以,我知道 -d 参数明确地执行 POST;
我知道我的应用程序需要 iPlanetDirectoryPro 的 --cookie
我知道 -H 表示接受,Content-Type 和 openam_token 都是必需的。
我困惑的是:
csfr 令牌的 -cookie ... 我从哪里获取数据?
session id 或 JSESSIONID 的 -cookie?
当我第一次登录 web-site 时,我有一个 cookie:
JSESSIONID=openam~A7FF59011F982FBB91C2F908E143327D; path=/sso/; domain=spring-auth.mydomain.net; Secure; HttpOnly
现在说到 header:
是 X-CSFR-TOKEN 还是 X-CSFRToken ...我都看过了。
我有一个 SimpleCORSFilter,但是这个 header 不是允许的之一,有必要吗?我可以将它添加到可接受的 header 列表中。
我担心将 _csfr 放入 JSON 数据中。如果我添加了 Jackson 映射器,恐怕 web-service 将无法工作,因为 _csrf 没有匹配的 object,所以如果我这样做的话,我只是假设将它保留在外面.
所以,我在 curl 上做了很多试验和错误,但我今天运气不太好。当我确实让 curl 工作时,我必须将它传递给在 UI 上工作的承包商。他们正在使用 JavaScript 创建对 back-end 的 AJX 调用,因此他们可以将他们需要的任何东西传回 URL、post 数据,并且他们可以添加任何 headers 或 cookie,他们需要传回数据。我把这个留给他们去弄清楚。
任何能让我的 curl 正常工作的帮助都会很棒。谢谢!
更新:
当用户登录到我的应用程序时,我们使用 SiteMinder 示例的衍生版本。
也就是说,当我们成功通过身份验证时,我们会从 OpenAM 获取一个 cookie。然后我们使用 siteminder 示例调用 CustomUserDetailsService,它使用该 cookie 调用 OpenAM 并获取用户名。然后我们对该用户名进行数据库查找以获取该用户的角色。在 none 中,我们是否取回了任何类型的 csrf 令牌。因此,对于我在 Whosebug 上看到的所有示例,没有 csrf 令牌可供我传回。我添加了以下 RESTful web-service.
@RequestMapping(value = "/csrf-token", method = RequestMethod.GET)
public @ResponseBody String getCsrfToken(HttpServletRequest request)
{
CsrfToken token = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
return token.getToken();
}
我可以随时成功调用此 URL 并获得一个令牌 return 返回给客户端。例如:“45757c25-1af7-40d3-ab8b-1a9cd823efc5”
所以,我正在两个地方对此进行测试:Firefox 的 RESTClient 和 curl ...
在 RESTClient 中,我可以发出请求并获得一个 csrf 令牌,然后我尝试将其放入 RESTClient 中,如下所示:
URL: https://spring.mydomain.net/api/subject/build?_csrf=[45757c25-1af7-40d3-ab8b-1a9cd823efc5]
Headers:
openam_token: AQIC5wM2LY4SfczkVMBTIq4pyjcec7QkyN0PJbY3NdmF8WE.*AAJTSQACMDE.*
X-CSRF-TOKEN: [45757c25-1af7-40d3-ab8b-1a9cd823efc5]
我还需要什么吗,因为它还没有工作。
卷曲:
curl \
-d '{"SiteId\:"548","SubjectId":TEST_sub","description":"TEST_des"}' \
--cookie "csrftoken=45757c25-1af7-40d3-ab8b-1a9cd823efc5" \
--cookie "JSESSIONID=openam~A7FF59011F982FBB91C2F908E143327D" \
--cookie "iPlanetDirectoryPro=AQIC5wM2LY4Sfcy_7ZIwOhUsE4KK922nQEue1Bgm7wAtX_k.*AAJTSQACMDE.*; path=/; domain=.mydomain.net" \
-H "X-CSFR-TOKEN: 45757c25-1af7-40d3-ab8b-1a9cd823efc5"
-H "Accept: */*" -H "Content-Type: */*" \
-H "openam-token: AQIC5wM2LY4Sfcy_7ZIwOhUsE4KK922nQEue1Bgm7wAtX_k.*AAJTSQACMDE.*" \
https://spring.mydomain.net/api/subject/build
再说一次,我缺少什么来完成这项工作????
我是否必须以某种方式组合我在 RESTClient 中的调用以获取此令牌,然后再到我的 POST?我如何在卷曲中结合这些?我知道每个 session 有一个 csrf 令牌,我想知道我可以拨打一个电话并获取此令牌,然后在下一个请求中使用它以传回 POST.
我不做 front-end,我们有另一家公司正在处理 UI 和 Ajax 电话,我希望能够测试我的 web-service 在我把它传递给他们之前打电话给他们。
再次感谢!
我认为这不能完全回答您的问题,但这是我添加 csrf 令牌的方法:
$(function () {
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
$(document).ajaxSend(function(e, xhr, options) {
xhr.setRequestHeader(header, token);
});
});
我查看了我的一个请求 headers 及其 "X-CSRF-TOKEN"
至于 curl,我找到了其他测试方法,通常是在单独的测试配置中禁用 CSRF。
经过多次尝试和错误的努力,我终于找到了如何使这项工作成功的方法。
根据之前的帖子,我有一个正确的想法,让我自己的控制器成为 return 一个令牌,这在上面突出显示。当我调用该服务以获取令牌时,我还确保我获取了 JSESSION 的 cookie。那是请求请求的 session,所以我必须确保在取回令牌后我抓住了它:
Cookie: JSESSIONID=3A74721AD18E758D7B8DC54FB32A6515; Path=/services/; HttpOnly
csrf_token: db7e3100-bd2d-4ecf-8c0d-20b8b4e17b20
现在,无论是使用 Firefox RESTClient 还是使用 curl,您都需要两件事:
curl \
-d '{"SiteId\:"548","SubjectId":TEST_sub","description":"TEST_des"}' \
--cookie '\JSESSIONID=3A74721AD18E758D7B8DC54FB32A6515;' \
--cookie "iPlanetDirectoryPro=AQIC5wM2LY4Sfcy_7ZIwOhUsE4KK922nQEue1Bgm7wAtX_k.*AAJTSQACMDE.*; path=/; domain=.mydomain.net" \
-H "X-CSFR-TOKEN: db7e3100-bd2d-4ecf-8c0d-20b8b4e17b20"
-H "Accept: */*" -H "Content-Type: application/json" \
-H "openam-token: AQIC5wM2LY4Sfcy_7ZIwOhUsE4KK922nQEue1Bgm7wAtX_k.*AAJTSQACMDE.*" \
https://spring.mydomain.net/api/subject/build
请注意,JSESSION id 的 cookie 来自我首先获得 csrf 令牌 (db7e3100-bd2d-4ecf-8c0d-20b8b4e17b20) 的请求。
请注意,我确实需要 X-CSFR-TOKEN 来包含令牌,并且我在 SimpleCORSFilter 中启用了 header。
所以,这成功了!!!!我能够将令牌正确传递给 URL,并且我可以看到他记录了 int。能看到controller的访问,以及我传入的数据
REST 控制器定义为:
@RequestMapping(value = "/build", method = RequestMethod.POST, produces = "application/json", headers = "Content-Type=application/json")
public MyEntity build(@RequestBody SubjectImportDTO subjectImportDTO)
{
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
User user = null;
if (principal instanceof User)
{
user = ((User) principal);
}
MyEntity entity = service.build(subjectImportDTO);
return entity;
}
现在,URL 被找到,被调用,在后端工作,并准备好 return 一个实体......但是我从 curl 或火狐 REST 客户端。我认为如果我们甚至无法找到 REST 端点开始,就会产生 404 错误,所以这是我的另一个问题。
我知道这个问题以前被问过很多,它适用于很多不同的方式,基于我已经在网上和这里问过的问题,我的问题多于我的答案。
所以,我有一个 Spring MVC 4.0 RESTful web-service,我知道它工作正常。我知道它工作正常,因为它通过了我的单元测试。增加安全性的单元测试和作为测试安全性一部分的 "csrf()" 使其工作。我确实注意到添加了这条数据:
Parameters = {_csrf=[435f9968-f643-47e9-9d15-23a5cb361b1d]}
RESTful web-service 使用 Spring Security 4 保护,默认启用 csrf 保护。所有带有 GET 的 web-service 都很好用,正是 POST 阻碍了我的 403 错误。
这是我要实现的卷曲:
curl \
-d '{"SiteId\:"548","SubjectId":TEST_sub","description":"TEST_des"}' \
--cookie "csrftoken=?????????????" \
--cookie "JSESSIONID=openam~A7FF59011F982FBB91C2F908E143327D" \
--cookie "iPlanetDirectoryPro=AQIC5wM2LY4Sfcy_7ZIwOhUsE4KK922nQEue1Bgm7wAtX_k.*AAJTSQACMDE.*; path=/; domain=.mydomain.net" \
-H "X-CSFRToken: ??????" -H "Accept: */*" -H "Content-Type: */*" \
-H "openam-token: AQIC5wM2LY4Sfcy_7ZIwOhUsE4KK922nQEue1Bgm7wAtX_k.*AAJTSQACMDE.*" \
https://spring.mydomain.net/api/subject/build
所以,我知道 -d 参数明确地执行 POST; 我知道我的应用程序需要 iPlanetDirectoryPro 的 --cookie 我知道 -H 表示接受,Content-Type 和 openam_token 都是必需的。
我困惑的是: csfr 令牌的 -cookie ... 我从哪里获取数据? session id 或 JSESSIONID 的 -cookie? 当我第一次登录 web-site 时,我有一个 cookie:
JSESSIONID=openam~A7FF59011F982FBB91C2F908E143327D; path=/sso/; domain=spring-auth.mydomain.net; Secure; HttpOnly
现在说到 header: 是 X-CSFR-TOKEN 还是 X-CSFRToken ...我都看过了。
我有一个 SimpleCORSFilter,但是这个 header 不是允许的之一,有必要吗?我可以将它添加到可接受的 header 列表中。
我担心将 _csfr 放入 JSON 数据中。如果我添加了 Jackson 映射器,恐怕 web-service 将无法工作,因为 _csrf 没有匹配的 object,所以如果我这样做的话,我只是假设将它保留在外面.
所以,我在 curl 上做了很多试验和错误,但我今天运气不太好。当我确实让 curl 工作时,我必须将它传递给在 UI 上工作的承包商。他们正在使用 JavaScript 创建对 back-end 的 AJX 调用,因此他们可以将他们需要的任何东西传回 URL、post 数据,并且他们可以添加任何 headers 或 cookie,他们需要传回数据。我把这个留给他们去弄清楚。
任何能让我的 curl 正常工作的帮助都会很棒。谢谢!
更新: 当用户登录到我的应用程序时,我们使用 SiteMinder 示例的衍生版本。 也就是说,当我们成功通过身份验证时,我们会从 OpenAM 获取一个 cookie。然后我们使用 siteminder 示例调用 CustomUserDetailsService,它使用该 cookie 调用 OpenAM 并获取用户名。然后我们对该用户名进行数据库查找以获取该用户的角色。在 none 中,我们是否取回了任何类型的 csrf 令牌。因此,对于我在 Whosebug 上看到的所有示例,没有 csrf 令牌可供我传回。我添加了以下 RESTful web-service.
@RequestMapping(value = "/csrf-token", method = RequestMethod.GET)
public @ResponseBody String getCsrfToken(HttpServletRequest request)
{
CsrfToken token = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
return token.getToken();
}
我可以随时成功调用此 URL 并获得一个令牌 return 返回给客户端。例如:“45757c25-1af7-40d3-ab8b-1a9cd823efc5”
所以,我正在两个地方对此进行测试:Firefox 的 RESTClient 和 curl ...
在 RESTClient 中,我可以发出请求并获得一个 csrf 令牌,然后我尝试将其放入 RESTClient 中,如下所示:
URL: https://spring.mydomain.net/api/subject/build?_csrf=[45757c25-1af7-40d3-ab8b-1a9cd823efc5]
Headers:
openam_token: AQIC5wM2LY4SfczkVMBTIq4pyjcec7QkyN0PJbY3NdmF8WE.*AAJTSQACMDE.*
X-CSRF-TOKEN: [45757c25-1af7-40d3-ab8b-1a9cd823efc5]
我还需要什么吗,因为它还没有工作。
卷曲:
curl \
-d '{"SiteId\:"548","SubjectId":TEST_sub","description":"TEST_des"}' \
--cookie "csrftoken=45757c25-1af7-40d3-ab8b-1a9cd823efc5" \
--cookie "JSESSIONID=openam~A7FF59011F982FBB91C2F908E143327D" \
--cookie "iPlanetDirectoryPro=AQIC5wM2LY4Sfcy_7ZIwOhUsE4KK922nQEue1Bgm7wAtX_k.*AAJTSQACMDE.*; path=/; domain=.mydomain.net" \
-H "X-CSFR-TOKEN: 45757c25-1af7-40d3-ab8b-1a9cd823efc5"
-H "Accept: */*" -H "Content-Type: */*" \
-H "openam-token: AQIC5wM2LY4Sfcy_7ZIwOhUsE4KK922nQEue1Bgm7wAtX_k.*AAJTSQACMDE.*" \
https://spring.mydomain.net/api/subject/build
再说一次,我缺少什么来完成这项工作????
我是否必须以某种方式组合我在 RESTClient 中的调用以获取此令牌,然后再到我的 POST?我如何在卷曲中结合这些?我知道每个 session 有一个 csrf 令牌,我想知道我可以拨打一个电话并获取此令牌,然后在下一个请求中使用它以传回 POST.
我不做 front-end,我们有另一家公司正在处理 UI 和 Ajax 电话,我希望能够测试我的 web-service 在我把它传递给他们之前打电话给他们。
再次感谢!
我认为这不能完全回答您的问题,但这是我添加 csrf 令牌的方法:
$(function () {
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
$(document).ajaxSend(function(e, xhr, options) {
xhr.setRequestHeader(header, token);
});
});
我查看了我的一个请求 headers 及其 "X-CSRF-TOKEN"
至于 curl,我找到了其他测试方法,通常是在单独的测试配置中禁用 CSRF。
经过多次尝试和错误的努力,我终于找到了如何使这项工作成功的方法。
根据之前的帖子,我有一个正确的想法,让我自己的控制器成为 return 一个令牌,这在上面突出显示。当我调用该服务以获取令牌时,我还确保我获取了 JSESSION 的 cookie。那是请求请求的 session,所以我必须确保在取回令牌后我抓住了它:
Cookie: JSESSIONID=3A74721AD18E758D7B8DC54FB32A6515; Path=/services/; HttpOnly
csrf_token: db7e3100-bd2d-4ecf-8c0d-20b8b4e17b20
现在,无论是使用 Firefox RESTClient 还是使用 curl,您都需要两件事:
curl \
-d '{"SiteId\:"548","SubjectId":TEST_sub","description":"TEST_des"}' \
--cookie '\JSESSIONID=3A74721AD18E758D7B8DC54FB32A6515;' \
--cookie "iPlanetDirectoryPro=AQIC5wM2LY4Sfcy_7ZIwOhUsE4KK922nQEue1Bgm7wAtX_k.*AAJTSQACMDE.*; path=/; domain=.mydomain.net" \
-H "X-CSFR-TOKEN: db7e3100-bd2d-4ecf-8c0d-20b8b4e17b20"
-H "Accept: */*" -H "Content-Type: application/json" \
-H "openam-token: AQIC5wM2LY4Sfcy_7ZIwOhUsE4KK922nQEue1Bgm7wAtX_k.*AAJTSQACMDE.*" \
https://spring.mydomain.net/api/subject/build
请注意,JSESSION id 的 cookie 来自我首先获得 csrf 令牌 (db7e3100-bd2d-4ecf-8c0d-20b8b4e17b20) 的请求。 请注意,我确实需要 X-CSFR-TOKEN 来包含令牌,并且我在 SimpleCORSFilter 中启用了 header。
所以,这成功了!!!!我能够将令牌正确传递给 URL,并且我可以看到他记录了 int。能看到controller的访问,以及我传入的数据
REST 控制器定义为:
@RequestMapping(value = "/build", method = RequestMethod.POST, produces = "application/json", headers = "Content-Type=application/json")
public MyEntity build(@RequestBody SubjectImportDTO subjectImportDTO)
{
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
User user = null;
if (principal instanceof User)
{
user = ((User) principal);
}
MyEntity entity = service.build(subjectImportDTO);
return entity;
}
现在,URL 被找到,被调用,在后端工作,并准备好 return 一个实体......但是我从 curl 或火狐 REST 客户端。我认为如果我们甚至无法找到 REST 端点开始,就会产生 404 错误,所以这是我的另一个问题。