【发布时间】:2021-09-04 08:59:24
【问题描述】:
我使用 SSM 框架开发了一个演示网站,并使用 spring.security 进行身份验证。我可以使用 post 请求登录网站并使用 get 请求获取数据。但是,我无法使用发布请求添加数据。它总是被禁止的。如果 CSRF 被禁用,就可以了。我尝试了以下方法,它们都不起作用。
- 将“X-CSRF-TOKEN:CSRF 值”添加到标题中。
- 将“_csrf:CSRF 值”添加到标题中。
- 将 _csrf 添加到发布请求正文。
那么如何在启用 CSRF 的情况下使发布请求工作?另外,我不确定是否需要使用不同的帖子重新生成 CSRF 令牌。奇怪的是,登录帖子请求有效。
-
application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai spring.datasource.username=root spring.datasource.password=123456 mybatis.mapper-locations=classpath:mybatis/*.xml spring.security.user.name=root spring.security.user.password=123456 debug=true -
安全配置
@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .anyRequest().authenticated() .and() .formLogin().permitAll(); } } -
用户控制器
@RestController @RequestMapping("/rest/users") public class UserController { @Autowired private UserMapper userMapper; @PostMapping public void add(@RequestBody User user){ userMapper.add(user); } @GetMapping public List<User> getAll(){ return userMapper.findAll(); } } -
卷曲脚本
#!/usr/bin/env bash host=192.168.44.109:8080 remote=http://${host} login=${remote}/login users=${remote}/rest/users/ csrf=$( \ curl --url ${login} -L -c cookie.txt 2>&1 \ |grep _csrf \ |sed 's/^.*value="\(.*\)".*$/\1/' \ ) echo "before login, csrf=${csrf}" curl --url ${login} -L -b cookie.txt -c cookie.txt -i \ -d "username=root&password=123456&_csrf=${csrf}" curl --url ${users} -L -b cookie.txt -v \ -H "Content-Type: application/json" \ -H "X-CSRF-Token: ${csrf}" \ -H "x-csrf-token: ${csrf}" \ -H "_csrf: ${csrf}" \ -d "{\"name\": \"name2\"}" rm -f cookie.txt -
脚本输出
before login, csrf=6d7b2d7b-f9aa-4463-ad9b-468082df4d74 HTTP/1.1 302 Set-Cookie: JSESSIONID=D728694163DEEC78DDBC8869DC54C870; Path=/; HttpOnly X-Content-Type-Options: nosniff X-XSS-Protection: 1; mode=block Cache-Control: no-cache, no-store, max-age=0, must-revalidate Pragma: no-cache Expires: 0 X-Frame-Options: DENY Location: http://192.168.44.109:8080/ Content-Length: 0 Date: Sun, 20 Jun 2021 11:05:52 GMT HTTP/1.1 200 Vary: Origin Vary: Access-Control-Request-Method Vary: Access-Control-Request-Headers X-Content-Type-Options: nosniff X-XSS-Protection: 1; mode=block Cache-Control: no-cache, no-store, max-age=0, must-revalidate Pragma: no-cache Expires: 0 X-Frame-Options: DENY Content-Type: application/hal+json Transfer-Encoding: chunked Date: Sun, 20 Jun 2021 11:05:52 GMT { "_links" : { "profile" : { "href" : "http://192.168.44.109:8080/profile" } } }* Trying 192.168.44.109... * TCP_NODELAY set * Connected to 192.168.44.109 (192.168.44.109) port 8080 (#0) > POST /rest/users/ HTTP/1.1 > Host: 192.168.44.109:8080 > User-Agent: curl/7.64.1 > Accept: */* > Cookie: JSESSIONID=D728694163DEEC78DDBC8869DC54C870 > Content-Type: application/json > X-CSRF-Token: 6d7b2d7b-f9aa-4463-ad9b-468082df4d74 > x-csrf-token: 6d7b2d7b-f9aa-4463-ad9b-468082df4d74 > _csrf: 6d7b2d7b-f9aa-4463-ad9b-468082df4d74 > Content-Length: 17 > * upload completely sent off: 17 out of 17 bytes < HTTP/1.1 403 < X-Content-Type-Options: nosniff < X-XSS-Protection: 1; mode=block < Cache-Control: no-cache, no-store, max-age=0, must-revalidate < Pragma: no-cache < Expires: 0 < X-Frame-Options: DENY < Content-Type: application/json < Transfer-Encoding: chunked < Date: Sun, 20 Jun 2021 11:05:52 GMT < * Connection #0 to host 192.168.44.109 left intact {"timestamp":"2021-06-20T11:05:52.540+00:00","status":403,"error":"Forbidden","message":"","path":"/rest/users/"}* Closing connection 0
【问题讨论】:
标签: curl spring-security csrf csrf-token