Spring 安全 CSRF 403 禁止成功登录

Spring Security CSRF 403 Forbidden on successful login

我在 index.html 和 login.html 的基本 Thymeleaf 设置上使用 Spring 安全性,但是默认登录页面总是 returns 403 Forbidden when the credentials有效的。 (如预期的那样,当凭据不匹配时会出现 UI 错误)。

我认为这是因为 CSRF 令牌已作为 cookie (XSRF-TOKEN) 包含在对后端的每个请求中。我不想简单地禁用 CSRF,所以我尝试以几乎所有我可以在网上找到的方式将此令牌包含到 POST 请求中:

有什么想法吗?请求中的默认 Spring 安全 /login POST 端点期望什么?它如何期望 CSRF 令牌? 身份验证似乎有效,只是 CSRF 在成功登录时失败。还是完全是我遗漏的其他东西给了我 403 禁止?

提前致谢!!

我的设置

Spring启动版本:2.6.2

pom.xml 依赖项

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.xerial</groupId>
            <artifactId>sqlite-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>com.zsoltfabok</groupId>
            <artifactId>sqlite-dialect</artifactId>
            <version>1.0</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.hibernate.validator</groupId>
            <artifactId>hibernate-validator</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-thymeleaf</artifactId>
        </dependency>

index.html

<form th:action="@{/login}" method="post">
    <label for="username">Username</label>
    <input type="text" name="username" />
    <label for="password">Password</label>
    <input type="password" name="password" />
    <button type="submit">Submit</button>
<!-- there's also a hidden CSRF token generated automatically -->
</form>

WebSecurityConfigurerAdapter

@Configuration
@EnableGlobalAuthentication
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    // ...
    
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
            .antMatchers("/favicon.ico").anonymous()
            .antMatchers("/static/**").anonymous()
            .mvcMatchers("/", "/login", "/signup").anonymous()
            .anyRequest().authenticated()
            .and()
            .formLogin()
                .loginPage("/login")
                .defaultSuccessUrl("/")
            .and()
            .httpBasic()
            .and()
            .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
    }
    
}

WebMvcConfigurer

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/login").setViewName("login");
        registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
    }
    
}

控制器

@Controller
@RequestMapping("/")
public class WebController {

    @GetMapping
    public String index() {
        return "index";
    }
    
}

问题出在您的安全规则上。

.antMatchers("/favicon.ico").anonymous()
.antMatchers("/static/**").anonymous()
.mvcMatchers("/", "/login", "/signup").anonymous()

您将它们配置为 匿名 访问。这意味着尚未通过身份验证的人。它将阻止经过身份验证的用户访问这些 URL 中的任何一个(如果您禁用了匿名访问,则可以防止未经身份验证的用户访问)。

修复允许使用 permitAll() 而不是 anonymous() 的任何人访问。

.antMatchers("/favicon.ico").permitAll()
.antMatchers("/static/**").permitAll()
.mvcMatchers("/", "/login", "/signup").permitAll()