我正在尝试在Spring中激活CSRF cookie。所以我有以下课程:
SecurityAdapter.java
@Configuration
@EnableWebSecurity
public class SecurityAdapter extends WebSecurityConfigurerAdapter
{
@Override
protected void configure(HttpSecurity http)
throws Exception
{
http
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}
}
由于我正在尝试实现REST Web服务(没有HTML或任何东西),我认为对服务器的第一个请求应该是GET,因为其他请求类型将需要XSRF-TOKEN
而我们不需要还有。
因此,当我发送GET请求时,我希望收到一些cookie作为回应(毕竟我一直是个好孩子!)。但我没有得到任何。
以下是项目文件的其余部分:
的pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>4.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>4.1.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>4.1.1.RELEASE</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
DemoApplication.java
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication
{
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
Controller.Java
package com.example;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class Controller
{
@RequestMapping(value = "/first", method = RequestMethod.GET)
public ResponseEntity get()
{
return ResponseEntity.ok("first");
}
@RequestMapping(value = "/second", method = RequestMethod.POST)
public ResponseEntity post()
{
return ResponseEntity.ok("second");
}
}
当我调用second
方法(当然是在POST方法中)时,我得到:
{
"timestamp": 1481500256460,
"status": 403,
"error": "Forbidden",
"message": "Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-XSRF-TOKEN'.",
"path": "/second"
}
但是当我调用GET中的first
方法时,我没有使用任何cookie并调用second
方法!
我在这里错过了什么?
答案 0 :(得分:2)
我测试了您的代码,我在Cookie中获得了csrf
令牌。我在Chrome浏览器中验证了GET方法并检查了Cookie标签。存在XSRF-TOKEN,由服务返回。为了打印服务返回的csrf标记,我在Controller中修改了first
方法,如下所示。请测试一下。
@RequestMapping(value = "/first", method = RequestMethod.GET)
public ResponseEntity get(HttpServletRequest request)
{
CsrfToken token = (CsrfToken) request.getAttribute("_csrf");
System.out.println(token.getHeaderName()+" = "+token.getToken());
return ResponseEntity.ok("first");
}
还有一件事。在使用Spring Boot时,您应该使用spring-boot-starter-security
,而不是单独的Spring Security依赖项。 pom.xml
中的依赖关系应如下所示。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>