Spring Boot POST请求403权限错误排查与解决方法
问题:Spring Boot POST请求返回403无访问权限
我正在开发一个Spring Boot简易项目,但在创建POST请求时遇到问题:每次请求都会返回403错误(请求载荷payload正确,仅状态码异常,提示“无访问权限”)。我甚至尝试配置.permitAll(),但问题仍未解决。

相关代码
前端JS代码
// Creates a new event const newEvent = { id: null, title: title, start: start, end: end, allDay: allDay, backgroundColor: backgroundColor, textColor: textColor, extendedProps: { description: description, creator: creator } }; // Sends event to backend fetch('/api/events/add', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(newEvent) }) .then(response => { if (!response.ok) { throw new Error('Error saving the event.'); } return response.json(); }) .then(data => { // Add the event to the calendar newEvent.id = data.id; gereralCalendar.addEvent(newEvent); personalCalendar.addEvent(newEvent); }) .catch(error => { console.error('Error:', error); });
后端Controller
@RestController @RequestMapping("/api/events") public class EventRestController { @Autowired EventService eventService; @Autowired UserService userService; @GetMapping("/all") public List<EventDto> getAllEvents() { return eventService.findAllEvents(); } @GetMapping("/personal") public List<EventDto> getPersonalEvents(Principal principal) { return eventService.findEventsUser(principal.getName()); } @PostMapping("/add") public ResponseEntity<Event> createEvent(@RequestBody EventDto eventDto) { Event savedEvent = eventService.saveEvent(eventDto); return ResponseEntity.ok(savedEvent); } }
EventDto实体
@Getter @Setter public class EventDto { private int id; private String title; private Boolean allDay; private LocalDateTime start; private LocalDateTime end; private String backgroundColor; private String textColor; private ExtendedProps extendedProps; @Getter @Setter public static class ExtendedProps { private String description; private String creator; // Constructors } // Constructors }
Spring Security配置
// I HAVE TWO ROLES -> USER and ADMIN -> hierarchy = "ROLE_ADMIN > ROLE_USER" @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests((authorize) -> authorize .requestMatchers("/").permitAll() // nothing .requestMatchers("/index").permitAll() // index.html .requestMatchers("/home").hasRole("USER") // home.html .requestMatchers("/calendar").hasRole("USER") // events_calendar.html .requestMatchers("/register/**").hasRole("ADMIN") // register.html .requestMatchers("/api/events/all").hasRole("USER") // GET API .requestMatchers("/api/events/personal").hasRole("USER") // GET API .requestMatchers("/api/events/add").hasRole("USER") // POST API ) .formLogin( form -> form .loginPage("/login") .loginProcessingUrl("/login") .defaultSuccessUrl("/home") // home.html .permitAll() ) .logout( logout -> logout .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) .permitAll() ); return http.build(); }
问题排查与解决方案
1. CSRF防护拦截(最可能原因)
Spring Security默认开启CSRF防护,POST请求如果未携带CSRF令牌会被直接拦截返回403。当前配置未关闭CSRF,前端请求也未携带令牌。
- 临时调试方案(仅用于排查,生产环境禁用):
在Security配置中添加CSRF关闭逻辑:http.csrf(csrf -> csrf.disable()); - 生产环境正确方案:
- 通过模板引擎(如Thymeleaf)在页面注入CSRF令牌:
<meta name="_csrf" content="${_csrf.token}"/> <meta name="_csrf_header" content="${_csrf.headerName}"/> - 在fetch请求中携带令牌头:
const csrfToken = document.querySelector('meta[name="_csrf"]').content; const csrfHeader = document.querySelector('meta[name="_csrf_header"]').content; fetch('/api/events/add', { method: 'POST', headers: { 'Content-Type': 'application/json', [csrfHeader]: csrfToken }, body: JSON.stringify(newEvent) })
- 通过模板引擎(如Thymeleaf)在页面注入CSRF令牌:
2. 请求匹配与权限验证
- 检查
requestMatchers("/api/events/add").hasRole("USER")路径是否拼写正确,确保和前端请求路径完全一致。 hasRole("USER")会自动添加ROLE_前缀,确认你的用户角色实际为ROLE_USER(而非仅USER)。- 可临时修改权限配置为
.permitAll()测试是否为权限规则问题:.requestMatchers("/api/events/add").permitAll()
3. 用户认证状态确认
确保发起请求的用户已完成登录,且拥有USER角色。可在后端createEvent方法中打印Principal信息确认用户身份:
@PostMapping("/add") public ResponseEntity<Event> createEvent(@RequestBody EventDto eventDto, Principal principal) { System.out.println("当前登录用户:" + principal?.getName()); Event savedEvent = eventService.saveEvent(eventDto); return ResponseEntity.ok(savedEvent); }
4. 参数绑定验证
检查EventDto是否有无参构造函数,Spring需要无参构造函数完成JSON到对象的绑定。若绑定失败可能引发间接异常,可在方法中打印eventDto确认参数是否正确接收。
内容的提问来源于stack exchange,提问作者Diogo Freire
相关产品推荐
相关产品推荐

