使用 Spring Security 时出现意外的 403 错误

Posted

技术标签:

【中文标题】使用 Spring Security 时出现意外的 403 错误【英文标题】:Unexpected 403 error when using Spring Security 【发布时间】:2021-04-05 15:43:54 【问题描述】:

这里我有一个表单的 html 代码。用于创建事件的表单。它要求用户提供一些信息,然后他必须按下按钮 create 。

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org/">
<head th:replace="fragments :: head"></head>
<body class="container">

<nav th:replace="fragments :: header"></nav>

<form method="post">
    <div class="form-group">
        <label>Name
            <input th:field="$event.name" class="form-control">
        </label>
        <p class="error" th:errors="$event.name"></p>
    </div>
    <div class="form-group">
        <label>Description
            <input  th:field="$event.eventDetails.description" class="form-control">
        </label>
        <p class="error" th:errors="$event.eventDetails.description"></p>
    </div>
    <div class="form-group">
        <label>Contact Email
            <input  th:field="$event.eventDetails.contactEmail" class="form-control">
        </label>
        <p class="error" th:errors="$event.eventDetails.contactEmail"></p>
    </div>

    <div class="form-group">
        <label>Category
            <select th:field="$event.eventCategory">
                <option th:each="eventCategory : $categories"
                        th:value="$eventCategory.id"
                        th:text="$eventCategory.name"
                ></option>
            </select>
            <p class="error" th:errors="$event.eventCategory"></p>

        </label>
    </div>

    <div class="form-group">
        <input type="submit" value="Create" class="btn btn-success">
    </div>
</form>

</body>
</html>

这里有我的表单的 java 代码。


    @GetMapping("create")
    public String displayCreateEventForm(Model model)
        model.addAttribute("title", "Create Event");
        model.addAttribute(new Event());
        model.addAttribute("categories", eventCategoryRepository.findAll());
        return "events/create";
    

    @PostMapping("create")
    public String processCreateEventForm(@ModelAttribute @Valid Event newEvent, Errors errors, Model model)
        if (errors.hasErrors())
            model.addAttribute("title", "Create Event");
            return "events/create";
        
        eventRepository.save(newEvent);
        return "redirect:";
    

我不知道为什么按下按钮后它会给我一个错误,例如:

白标错误页面。 此应用程序没有 /error 的显式映射,因此您将其视为后备。

2020 年 12 月 29 日星期二 00:24:57 EET 出现意外错误(类型=禁止,状态=403)。禁止。

配置类


package com.example.demo.config;

import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;


@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter 

    @Autowired
    private UserService userService;

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http
                .authorizeRequests()
                .antMatchers(
                        "/registration**",
                        "/js/**",
                        "/css/**",
                        "/img/**",
                        "/webjars/**").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
                .logout()
                .invalidateHttpSession(true)
                .clearAuthentication(true)
                .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                .logoutSuccessUrl("/login?logout")
                .permitAll();
    

    @Bean
    public BCryptPasswordEncoder passwordEncoder() 
        return new BCryptPasswordEncoder();
    

    @Bean
    public DaoAuthenticationProvider authenticationProvider() 
        DaoAuthenticationProvider auth = new DaoAuthenticationProvider();
        auth.setUserDetailsService(userService);
        auth.setPasswordEncoder(passwordEncoder());
        return auth;
    

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception 
        auth.authenticationProvider(authenticationProvider());
    




【问题讨论】:

你使用 Spring Security 吗? 是的,我正在使用 Spring Security 所以发布你的@Configuration 课程 看来您保护了提交表单的端点并试图在未经授权的情况下访问它。仅在授权后允许表单或从 SecurityConfig 中删除其路径。 Spring 安全性要求所有的 post 请求默认都有 csrf。添加 csrf 参数(推荐)或禁用 csrf(不推荐)。见this。 【参考方案1】:

正如 @dan1st 在评论部分提到的,在使用 SpringSecurity 时,所有表单提交都需要CSRF(除非你禁用它)。要在表单中自动添加csrf token,一种简单的方法是使用百里香标签。一旦 thymeleaf 在表单中检测到其标签,它会在丢失时将 csrf 令牌添加到隐藏输入中。 这是一个例子

<form th:action="@'your_post_path'" method="POST" th:object="$yourModelAttributeEntity">
...
</form>

您可以添加其中一个或两个都添加

【讨论】:

好吧,酷。您可以将答案标记为正确答案,以帮助未来的读者

以上是关于使用 Spring Security 时出现意外的 403 错误的主要内容,如果未能解决你的问题,请参考以下文章

Groovy:使用 Grails 和 Spring 安全核心插件时出现意外令牌

使用 CorsFilter 和 spring security 时出现 Cors 错误

使用 Spring Security 实现 LDAP 身份验证时出现 Gradle 依赖关系错误

Spring Security:注销时出现 404

Spring Security + JWT |比较密码时出现假阴性

在 Grails 的 Spring Security Rest Plugin 中注销时出现 404