LINUX.ORG.RU

Работа CORS в Spring-Security

 , ,


0

2

Я пытаюсь сделать запрос из клиентского приожения (react), с localhost:5173. Запрос содержит заголовок с JWT «Authorization».

В результате я получаю ошибку похожую на CORS. А еще на бэкенде в AuthenticationTokenFilter при получении заголовка с авторизацией получаю null. При этом через postman все работает нормально.

Изображения из вкладки Network:

https://i.stack.imgur.com/px7TF.png

https://i.stack.imgur.com/KZkaW.png

Код:

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
@RequiredArgsConstructor
public class SecurityConfig {

    private final AuthenticationTokenFilter authenticationTokenFilter;
    private final AuthenticationConfiguration authConfig;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .csrf(AbstractHttpConfigurer::disable)
                .authorizeHttpRequests(authorize -> authorize
                        .requestMatchers("/public").permitAll()
                        .requestMatchers("/login").permitAll()
                        .anyRequest().authenticated()
                )
//                .csrf((csrf) -> csrf.disable()) this I try too
                .addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
        return http.build();
    }


    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(ImmutableList.of("*"));
        configuration.setAllowedMethods(ImmutableList.of("HEAD", "GET", "POST", "PUT", "DELETE", "PATCH"));
        configuration.setAllowedHeaders(ImmutableList.of("Authorization", "Cache-Control", "Content-Type", "authorization", "content-type", "x-auth-token"));
        configuration.setExposedHeaders(Arrays.asList("x-auth-token"));
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}
@RequiredArgsConstructor
@Configurati
public class AuthenticationTokenFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        Integer userId = getUserIdByTokenFromVK(token);
        if (userId != null) {
            Set<GrantedAuthority> authorities = new HashSet<>();
            authorities.add(new SimpleGrantedAuthority("ROLE_USER"));

            User user = new User();
            user.setVkId(userId);
            user.setJwt(token);

            UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(user, null, authorities);
            SecurityContextHolder.getContext().setAuthentication(auth);
        }
        filterChain.doFilter(request, response);
    }

    private Integer getUserIdByTokenFromVK(String token) {
        String serviceToken = "484f88ba2b2c616503ffd3f4gsd3243f43grefsrgb923815d";
        String apiVersion = "5.154"; 
        CloseableHttpClient httpClient = HttpClients.createDefault();
        String url = "https://api.vk.com/method/secure.checkToken?access_token=" + serviceToken +
                "&token=" + token +
                "&v=" + apiVersion;
        HttpGet httpGet = new HttpGet(url);
        try {
            HttpResponse response = httpClient.execute(httpGet);
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                String responseString = EntityUtils.toString(entity);;
                ObjectMapper objectMapper = new ObjectMapper();
                VKResponse vkResponse = objectMapper.readValue(responseString, VKResponse.class);

                if (vkResponse.getResponse() != null) {
                    return vkResponse.getResponse().getUserId();
                } else if (vkResponse.getError() != null) {
                    Integer errorCode = vkResponse.getError().getErrorCode();
                    String errorMsg = vkResponse.getError().getErrorMsg();
                    System.out.println("Error Code: " + errorCode);
                    System.out.println("Error Message: " + errorMsg);
                    return null;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                httpClient.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
//                .allowedOrigins("http://localhost:8080", "http://localhost:3000", "http://localhost:5173", "http://localhost:3001", "*")
                .allowedMethods("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH")
                .allowedHeaders("Authorization", "Cache-Control", "Content-Type");
//                .allowedHeaders("*")
//                .allowCredentials(true);
    }

    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("POST");
        config.addAllowedMethod("GET");
        config.addAllowedMethod("DELETE");
        config.addAllowedMethod("PUT");
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }
}

В результате я получаю ошибку похожую на CORS.

может это метод OPTIONS т.е. preflight request посылаемый браузером перед запросом что-бы получить инфо о возможностях сервера возвращает ошибку?

Syncro ★★★★★
()