Spring security - 403 статус ответа на вызов ОПЦИИ - PullRequest
0 голосов
/ 21 апреля 2020

У меня есть сервер, размещенный на Heroku, и интерфейс на Netlify. Когда я вызываю конечную точку на бэкенде, она отправляет предварительные опции, но дает статус 403. Я действительно искал решение, но оно все еще не работает.

Я хочу иметь возможность вызывать "/authenticate" конечную точку с "POST" методом с телом от FE до BE.

Конфигурация безопасности Spring ( просто методы настройки)

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
    ...

    @Override
    public void configure(WebSecurity web) throws Exception
    {
        web.ignoring()
                .antMatchers(HttpMethod.POST, "/authenticate", "/register")
                .antMatchers(HttpMethod.GET, "/token")
                .antMatchers("/h2-console/**")
                .antMatchers("/v2/api-docs",
                "/configuration/ui",
                "/swagger-resources/**",
                "/configuration/security",
                "/swagger-ui.html",
                "/webjars/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception
    {

        http
                .cors()
                .and()
                .csrf().disable()
                .authorizeRequests()
                .antMatchers(HttpMethod.OPTIONS, "/authenticate").permitAll()
                .antMatchers(HttpMethod.GET, "/user-data").authenticated()
                .anyRequest().authenticated()
                .and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        http.addFilterBefore(new JwtFilter(), UsernamePasswordAuthenticationFilter.class);
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();

        configuration.setAllowedOrigins(List.of(<MY-URL>));
        configuration.setAllowedHeaders(List.of("*"));
        configuration.setMaxAge(Long.valueOf(3600));
        configuration.setAllowedMethods(Arrays.asList("GET","POST", "OPTIONS"));
        configuration.setAllowCredentials(true);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);

        return source;
    }
}

и вызов из FE

var req = new XMLHttpRequest();
    req.open('POST', API_URL + '/authenticate', true);
    req.setRequestHeader("Content-Type", "application/json");
    req.withCredentials = true;
    req.onreadystatechange = function (aEvt) {
        if (req.readyState === 4) {
            if(req.status === 200) {
                console.log(req.responseText);
                isAuthenticationSucessful = true;
            }
            else
                console.log("Error loading site");
        }
    };

    req.send(JSON.stringify({username, password}));

Инструменты разработчика браузера:

Reason: CORS header 'Access-Control-Allow-Origin' missing
Reason: CORS request did not succeed

1 Ответ

0 голосов
/ 23 апреля 2020

TL; DR

Убедитесь, что в setAllowedOrigins("https://myrul.com") у вас нет трейлинг-листа sh или у вас точно такой же источник, что и ваш браузер.

Если ваша конечная точка находится в web.ignoring(..., удалите ее отсюда и вставьте (с моим примером конечной точки) http.authorizeRequests().antMatchers("/authenticate").permitAll()

(web и http в соответствии с моим кодом)

длиннее

Итак, как я сказал в своем комментарии, одна вещь, которая заставляет его работать неправильно, это установка setAllowedOrigins("https://myrul.com/") в corsConfigurationSource. Обратите внимание, что тянущийся sla sh.

Но я заметил в dev-tools, что браузер отправляет исходный заголовок так: Origin: https://myrul.com без завершающего sla sh. Чтобы это работало, я должен изменить разрешенное происхождение на правильное происхождение, например: setAllowedOrigins("https://myrul.com") (без конечного sla sh). Это позволяет браузеру отправлять запросы на сервер и получать 200 ответов, но браузер не принимает ответ от сервера, потому что CORS.

Следующее, что у меня есть конечная точка в web.ignoring("/authenticate")..., и в соответствии с этим вопрос Конфигурация Spring Security - HttpSecurity против WebSecurity этот оператор предотвращает цепочку фильтра Spring Security, где он должен заголовок Access-Control-Allow-Origin, который сообщает браузеру, что он может принять ответ. MDN Access-Control-Allow-Origin

Таким образом, ответом для этого было перенести мою конечную точку с web.ignoring("/authenticate") до http.authorizeRequests().antMatchers("/authenticate").permitAll().

Но это создает еще одну проблему, то есть go теперь будет фильтровать цепочку и мой пользовательский фильтр http.addFilterBefore(new JwtFilter()..., поэтому убедитесь, что вы применили пользовательские фильтры к вашим потребностям.

...