如何解决Spring Boot Post请求中的403错误?

问题描述 投票:0回答:1

我正在 Spring Boot 中创建一个简单的项目,但在创建此 POST 请求时遇到一些困难。 基本上每次我尝试时都会出现 403 错误(有效负载是正确的,只有状态给我错误说它已关闭,因为我“没有访问权限”)。我什至尝试过 .permitAll() 但它仍然不起作用。

如图。 1 - 错误消息

一些代码:

//
// I have the following js code:
//
// 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);
});

//
// I also have the following 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);
    }
}

//
// Also this class:
//
@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
}

//
// And finally the following Spring Security configuration:
//
// 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();
}

我尝试修改POST js代码,也给每个人访问它的权限,但仍然不起作用。

我希望将 newEvent 发送到后端,然后将其保存在数据库中。

javascript spring-boot rest spring-mvc http-status-code-403
1个回答
0
投票

我成功解决了这个问题。本质上,这是因为 Spring Security 默认启用了 CSRF(跨站请求伪造)。我没有禁用它;相反,我利用 Thymeleaf 依赖项来检索令牌。

`// Dependency
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

// Create configuration for repository of CSRF Tokens
private CsrfTokenRepository csrfTokenRepository() {
    HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
    repository.setSessionAttributeName("_csrf");
    return repository;
}

// Add to .csrf to filterChain
.csrf(csrf -> csrf.csrfTokenRepository(csrfTokenRepository()));

// In HTML add
<meta name="_csrf" th:content="${_csrf.getToken()}" />
<meta name="_csrf_header" th:content="${_csrf.getHeaderName()}" />

// And add
const csrfToken = document.querySelector('meta[name="_csrf"]').getAttribute('content');
const csrfHeader = document.querySelector('meta[name="_csrf_header"]').getAttribute('content');

fetch('/api/events/add', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        [csrfHeader]: csrfToken // Include the CSRF token in the request header
    },
    body: JSON.stringify(newEvent)
})

// [...]`
© www.soinside.com 2019 - 2024. All rights reserved.