programing

Spring Boot + Spring Security 어플리케이션에서 CORS를 설정하는 방법

showcode 2023. 3. 26. 11:56
반응형

Spring Boot + Spring Security 어플리케이션에서 CORS를 설정하는 방법

Spring Security와 Cors Support가 있는 Spring Boot를 사용합니다.

다음 코드를 실행하면

url = 'http://localhost:5000/api/token'
xmlhttp = new XMLHttpRequest
xmlhttp.onreadystatechange = ->
    if xmlhttp.readyState is 4
        console.log xmlhttp.status
xmlhttp.open "GET", url, true
# xmlhttp.setRequestHeader "X-Requested-With", "XMLHttpRequest"
xmlhttp.setRequestHeader 'Authorization', 'Basic ' + btoa 'a:a'
do xmlhttp.send

그 결과 얻을 수 있다

200

다음과 같은 잘못된 자격 증명을 사용하여 테스트하는 경우

url = 'http://localhost:5000/api/token'
xmlhttp = new XMLHttpRequest
xmlhttp.onreadystatechange = ->
    if xmlhttp.readyState is 4
        console.log xmlhttp.status
xmlhttp.open "GET", url, true
# xmlhttp.setRequestHeader "X-Requested-With", "XMLHttpRequest"
xmlhttp.setRequestHeader 'Authorization', 'Basic ' + btoa 'a:aa'
do xmlhttp.send

401(스프링 보안에서 잘못된 인증에 대한 표준 코드)을 받는 대신

0

다음 브라우저 알림이 표시됩니다.

GET http://localhost:5000/api/token

XMLHttpRequest는 http://localhost:5000을 로드할 수 없습니다.요청된 리소스에 'Access-Control-Allow-Origin' 헤더가 없습니다.따라서 오리진 'http://localhost:3000'은 액세스가 허용되지 않습니다.응답은 HTTP 상태 코드 401입니다.

서버 응답으로부터 유용한 http 상태 코드를 필요로 하는 프런트 엔드 코드를 개발하고 있습니다.나는 0보다 더 유용한 것이 필요하다.응답 본문도 비어 있습니다.설정이 잘못된 것인지 소프트웨어 버그인지, 어디에 크롬(arch Linux 사용)인지 스프링 보안인지 알 수 없습니다.

스프링 구성:

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

@RestController
@RequestMapping("api")
public class Controller {
    @RequestMapping("token")
    @CrossOrigin
    Map<String, String> token(HttpSession session) {
        return Collections.singletonMap("token", session.getId());
    }
}

@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("a").password("a").roles("USER");
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
                .anyRequest().authenticated()
                .and().httpBasic();
    }
}

모든 것을 컬로 테스트하면 CORS 지원이 필요 없기 때문에 OPTION으로 CORS를 시뮬레이트해 본 결과도 OK였습니다.

$ curl -v localhost:5000/api/token -H "Authorization: Basic YTpha"
*   Trying ::1...
* Connected to localhost (::1) port 5000 (#0)
> GET /api/token HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.48.0
> Accept: */*
> Authorization: Basic YTpha
> 
< HTTP/1.1 200 OK
< Server: Apache-Coyote/1.1
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Access-Control-Allow-Origin: http://localhost:3000
< Access-Control-Allow-Methods: POST,GET,OPTIONS,DELETE
< Access-Control-Max-Age: 3600
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Headers: Origin,Accept,X-Requested-    With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization
< x-auth-token: 58e4cca9-7719-46c8-9180-2fc16aec8dff
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Sun, 01 May 2016 16:15:44 GMT
< 
* Connection #0 to host localhost left intact
{"token":"58e4cca9-7719-46c8-9180-2fc16aec8dff"}

잘못된 자격 정보가 있는 경우:

$ curl -v localhost:5000/api/token -H "Authorization: Basic YTp"
*   Trying ::1...
* Connected to localhost (::1) port 5000 (#0)
> GET /api/token HTTP/1.1
> Host: localhost:5000
> User-Agent: curl/7.48.0
> Accept: */*
> Authorization: Basic YTp
> 
< HTTP/1.1 401 Unauthorized
< Server: Apache-Coyote/1.1
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< WWW-Authenticate: Basic realm="Realm"
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Sun, 01 May 2016 16:16:15 GMT
< 
* Connection #0 to host localhost left intact
{"timestamp":1462119375041,"status":401,"error":"Unauthorized","message":"Failed to decode basic authentication token","path":"/api/token"}

편집: 오해를 피하기 위해.1.3.3 스프링 부츠를 사용하고 있습니다.블로그 투고는 다음과 같습니다.

CORS 지원은 향후 Spring Boot 1.3 릴리즈에서 이용할 수 있으며, 이미 1.3.0 릴리즈에서 이용할 수 있습니다.BUILD-SNAPSHOT 빌드

Spring Boot 어플리케이션에서 컨트롤러 방식의 CORS 설정을 @CrossOrigin 주석과 함께 사용하는 경우 특별한 설정은 필요하지 않습니다.

글로벌 CORS 설정은 맞춤형 addCorsMappings(CorsRegistry) 메서드로 WebMvcConfigurer bean을 등록함으로써 정의할 수 있습니다.

글로벌 코르스 지원을 활성화하기 위해 아래 코드를 추가하였습니다.실제로 시도해 봤는데 결과는 똑같았습니다.최근에 다시 해봤는데 결과는 똑같아요.

@Configuration
public class MyConfiguration {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**");
            }
        };
    }
}

이 문제가 인가 프로세스 간의 방향 수정에서 비롯된다는 생각은 흥미롭습니다.이 충돌을 피하기 위해 리소스로 리다이렉트를 변경하는 방법은 무엇입니까?

편집:

내가 해결책에 더 가까운 것 같아.모든 요구에 Access-Control-Allow-Origin:*을 추가하여 문제없이 Cors를 지원하는 nodejs 서버에서 테스트했습니다.

Stefan Iselle이 이미 언급했듯이 봄철 보안은 CORS 헤더를 리다이렉트하거나 추가하지 않아 요청이 실패한 것 같습니다.따라서 스프링 보안은 인증을 확인하는 동안 적절한 헤더를 추가해야 합니다.

어떻게 하는지 아는 사람 있어요?

편집:

해결 방법을 찾았어요. 보기 흉하네요.회피책을 설명하는 스프링부트의 github 문제를 시작했습니다.https://github.com/spring-projects/spring-boot/issues/5834

Spring Security는 제가 쓴 이 블로그 투고에서 설명한 Spring MVC CORS 지원을 활용할 수 있게 되었습니다.

이 기능을 사용하려면 다음과 같이 스프링 보안 수준에서 CORS 지원을 명시적으로 활성화해야 합니다.그렇지 않으면 스프링 MVC에 도달하기 전에 스프링 보안에 의해 CORS 지원 요청이 차단될 수 있습니다.

레벨을 사용하고 있는 는, 「」를 참조해 주세요.@CrossOrigin하면 Spring 설정 Security CORS」)을할 수 있습니다.

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and()...
    }
}

글로벌는, CORS 를 할 수 .CorsConfigurationSource§:

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and()...
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", new CorsConfiguration().applyPermitDefaultValues());
        return source;
    }
}

이 접근법은 이전에 권장된 필터 기반 접근법보다 우선합니다.

자세한 내용은 Spring Security 문서의 전용 CORS 섹션에서 확인할 수 있습니다.

JDK 8+ 를 사용하는 경우는, 1 행의 람다 솔루션이 있습니다.

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.cors().configurationSource(request -> new CorsConfiguration().applyPermitDefaultValues());
}

스프링 부츠 2.3에서의 CORS 해결 방법 2.3+

요약

만약 당신이 이 CORS 문제에 직면해 있다면 걱정하지 마세요.이는 모든 백엔드 개발자가 프런트엔드 마이크로서비스와 처음으로 통합하려고 할 때 공통적으로 발생하는 문제입니다.브라우저가 사용자의 안전을 위해 엄격하게 적용하고 있는 일종의 보안 정책이며, 이것이 당신이 Postman/Swagger 또는 cURL을 통해 API를 시도했을 때 직면하지 않는 이유입니다.

솔루션

  • 클라이언트 측 바이패스(개발만)

다음 솔루션은 개발 목적으로만 제공되므로 반드시 프로덕션 환경에서 이 CORS 문제를 영구적으로 해결해야 합니다.다음 브라우저 확장을 사용하여 브라우저 정책을 무시하여 CORS 오류가 발생해도 놀라지 않습니다.

  1. CORS 블록 해제 Firefox - Chrome
  2. CORS Everywhere Firefox
  • 실가동 솔루션

애플리케이션에는 다양한 방법으로 CORS 정책을 구성할 수 있으며, 이는 완전히 고객의 도입 아키텍처를 기반으로 합니다.예를 들어 어플리케이션이 리버스 프록시(Nginx 등), API 게이트웨이(Kong), 서비스 메쉬 사이드카 프록시(Embornetes NGINX Ingress 등)를 통해 공개되는 경우베스트 프랙티스는 엣지 레이어에서의 CORS 설정을 처리하는 것입니다.하위 레이어 헤더를 고려하지 않고 덮어쓰면 브라우저로부터 CORS 에러가 발생할 수 있기 때문입니다.엣지 레이어 구성에 도움이 되는 링크를 다음에 나타냅니다.

단, SprintBoot의 내장 웹 서버를 통해 API를 배포하고 공개하는 경우에는 다음 지침을 사용할 수 있습니다.

CORS를 글로벌하게 활성화하는 방법 - 스프링 부트 응용 프로그램

Web Security Config 를 실장하고 있지 않은 경우는, 다음의 순서를 간단하게 실행해 주세요.

  1. 다음 의존관계 [spring-boot-starter-security]를 pom.xml에 추가합니다.
<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-security</artifactId>
</dependency>
  1. WebSecurityConfig를 확장하는 새 클래스를 구성 패키지에 만듭니다(예: 'SecurityConfig")
  2. 작성된 파일에 다음 코드를 입력합니다.
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.web.cors.CorsConfiguration;

import java.util.List;

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
{


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowedHeaders(List.of("Authorization", "Cache-Control", "Content-Type"));
        corsConfiguration.setAllowedOrigins(List.of("*"));
        corsConfiguration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "PUT","OPTIONS","PATCH", "DELETE"));
        corsConfiguration.setAllowCredentials(true);
        corsConfiguration.setExposedHeaders(List.of("Authorization"));
        
        // You can customize the following part based on your project, it's only a sample
        http.authorizeRequests().antMatchers("/**").permitAll().anyRequest()
                .authenticated().and().csrf().disable().cors().configurationSource(request -> corsConfiguration);

    }
}
  1. 이제 필요에 따라 CORS 구성을 커스터마이즈해야 합니다.

    • set Allowed(허용)Headers->는 프론트 엔드 앱을 통해 백엔드 서비스에 송신할 수 있는 파라미터를 지정해야 합니다.예를 들어 베어러/기본 토큰 인가 방식을 사용하는 경우 "Authorization" 헤더를 통해 JWT-Token을 전달해야 합니다.따라서 백업에서 이 데이터를 적절하게 수용하는지 확인해야 하며, 이를 위해서는 "Authorization"을 Allowed-Headers 목록에 추가해야 합니다.

    • set Allowed Methods -> 프리플라이트 프로세스의 리스트에 OPTIONS 메서드를 넣는 것을 잊지 말아 주세요.걱정하지 마세요. 여기서 더 읽어보세요!

    • setAllowCredentials-> Authorization 헤더를 사용하는 경우 True로 설정합니다.

    • set Exposed(표시)[ Headers ]-> [ Response Headers ]를 통해 데이터를 반환할 경우 여기서 지정해야 합니다.예를 들어 일부 API는 Response Headers를 통해 성공/인증 후 Authorization 토큰을 반환하도록 설계되어 있습니다.따라서 그에 따라 관련 헤더를 공개해야 합니다.

    • set Allowed Origins - > 백엔드 응용 프로그램에 요구를 송신할 수 있는 도메인을 지정해야 합니다.예를 들어 애플리케이션이 https://penguin.com에서 호스트되고 API가 https://api.penguin.com에 있는 경우 "https://penguing.com"이 백엔드로 요청을 보낼 수 있도록 허용해야 합니다.또한 와일드카드(*)를 전달하여 모든 도메인이 백엔드로 요청을 전송할 수 있습니다.단, 퍼블릭 API를 제공하거나 운영 환경 이외의 환경에서 배포하는 경우를 제외하고는 "any"를 사용하지 않는 것이 좋습니다.

    CORS가 다른 플랫폼(즉 피싱 목적)에 의한 API의 오용을 방지할 수 있다고 생각하는 사람들에게는 중요한 오해가 있습니다.그렇지 않습니다. CORS 정책은 브라우저 기반 정책이며 프록시를 통해 쉽게 우회할 수 있기 때문에 오용 프로세스를 조금 더 어렵게 만들 뿐이지 면제되지는 않습니다.

  2. 애플리케이션 구축/실행, API 테스트 및 휴식 (CORS의 골칫거리는 누구나 알고 있습니다)

대체 솔루션

다음 링크를 사용할 수 있습니다.

Spring.io | RESTful Web Service에 대한 크로스 오리진 요구 활성화

Bealdung | 봄과 함께 CORS

스프링 시큐리티를 사용하고 있는 경우는, 다음의 조작을 실시해, CORS 요구가 최초로 처리되도록 합니다.

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            // by default uses a Bean by the name of corsConfigurationSource
            .cors().and()
            ...
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("https://example.com"));
        configuration.setAllowedMethods(Arrays.asList("GET","POST"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

상세한 것에 대하여는, 「Spring 4.2.x CORS」를 참조해 주세요.

Spring Security를 사용하지 않으면 다음과 같이 동작합니다.

@Bean
public WebMvcConfigurer corsConfigurer() {
    return new WebMvcConfigurer() {
        @Override
        public void addCorsMappings(CorsRegistry registry) {
            registry.addMapping("/**")
                    .allowedOrigins("*")
                    .allowedMethods("GET", "PUT", "POST", "PATCH", "DELETE", "OPTIONS");
        }
    };
}

크로스 오리진 보호는 브라우저의 기능입니다.당신의 예상대로 컬은 CORS를 신경 쓰지 않습니다.따라서 컬링은 성공하지만 브라우저 요청은 성공적이지 않습니다.

잘못된 credential을 사용하여 브라우저 요청을 전송하면 spring은 클라이언트를 로그인 페이지로 전송하려고 합니다.이 응답(로그인 페이지 제외)에는 'Access-Control-Allow-Origin' 헤더가 포함되어 있지 않으며 브라우저는 설명에 따라 반응합니다.

이 로그인 응답에 대한 haeder를 포함하도록 spring을 설정해야 합니다.또, 에러 페이지등의 다른 응답에도 사용할 수 있습니다.

이것은 다음과 같이 실행할 수 있습니다.

    @Configuration
    @EnableWebMvc
    public class WebConfig extends WebMvcConfigurerAdapter {

            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/api/**")
                    .allowedOrigins("http://domain2.com")
                    .allowedMethods("PUT", "DELETE")
                    .allowedHeaders("header1", "header2", "header3")
                    .exposedHeaders("header1", "header2")
                    .allowCredentials(false).maxAge(3600);
            }
     }

이것은 봄철 코르스 받침 틀에서 베낀 것입니다.

먼저 다음과 같은 모든 리소스에 대한 cors 매핑을 추가합니다.

registry.addMapping("/**")

또한 모든 메서드헤더를 허용합니다.일단 작동하면 다시 필요한 최소값으로 줄이기 시작할 수 있습니다.

릴리스 4.2에서는, CORS 의 설정이 변경되는 것에 주의해 주세요.

이 방법으로 문제가 해결되지 않으면 실패한 Ajax 요청에서 받은 응답을 게시합니다.

@Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**").allowedOrigins("*").allowedMethods("*");
            }
        };
    }
// CorsConfig.java file
@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("http://localhost:3000")
                .allowCredentials(true);
    }
}

2021년 시점에서는 이것이 가장 간단한 해결책일 수 있으며, 별도의 클래스를 생성하기만 하면 됩니다.

그게 다예요.

Spring-Boot, Spring-Security 및 Java 기반 구성을 위한 간단한 솔루션을 찾았습니다.

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.cors().configurationSource(new CorsConfigurationSource() {
            @Override
            public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
                return new CorsConfiguration().applyPermitDefaultValues();
            }
        });
    }
}

서버 상태를 반환하는 메시드에서도 같은 문제가 발생했습니다.애플리케이션이 복수의 서버에 전개되고 있다.그래서 제가 찾은 가장 쉬운 건

@CrossOrigin(origins = "*")
@RequestMapping(value="/schedulerActive")
public String isSchedulerActive(){
  //code goes here
}

하지 않지만 .allowCredentials그럴 수 있어요.

나는 이 문제를 다음과 같이 해결했다.

@Bean
CorsConfigurationSource corsConfigurationSource() {
    CorsConfiguration configuration = new CorsConfiguration();
    configuration.setAllowedOrigins(Arrays.asList("*"));
    configuration.setAllowCredentials(true);
    configuration.setAllowedHeaders(Arrays.asList("Access-Control-Allow-Headers","Access-Control-Allow-Origin","Access-Control-Request-Method", "Access-Control-Request-Headers","Origin","Cache-Control", "Content-Type", "Authorization"));
    configuration.setAllowedMethods(Arrays.asList("DELETE", "GET", "POST", "PATCH", "PUT"));
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);
    return source;
}

`

이 문제는 다음과 같이 해결했습니다.

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

    @Configuration
    public class CORSFilter extends CorsFilter {

        public CORSFilter(CorsConfigurationSource source) {
            super((CorsConfigurationSource) source);
        }

        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
                throws ServletException, IOException {

            response.addHeader("Access-Control-Allow-Headers",
                    "Access-Control-Allow-Origin, Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
            if (response.getHeader("Access-Control-Allow-Origin") == null)
                response.addHeader("Access-Control-Allow-Origin", "*");
            filterChain.doFilter(request, response);
        }

    }

또, 다음과 같이 합니다.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

    @Configuration
    public class RestConfig {

        @Bean
        public CORSFilter corsFilter() {
            CorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            CorsConfiguration config = new CorsConfiguration();
            config.addAllowedOrigin("http://localhost:4200");
            config.addAllowedMethod(HttpMethod.DELETE);
            config.addAllowedMethod(HttpMethod.GET);
            config.addAllowedMethod(HttpMethod.OPTIONS);
            config.addAllowedMethod(HttpMethod.PUT);
            config.addAllowedMethod(HttpMethod.POST);
            ((UrlBasedCorsConfigurationSource) source).registerCorsConfiguration("/**", config);
            return new CORSFilter(source);
        }
    }

코르스는 골칫거리일 수 있지만, 이 간단한 코드만 있으면 당신은 코르스뿐입니다!!!지정된 방법으로

@CrossOrigin(origins="*")// in this line add your url and thats is all for spring boot side
    @GetMapping("/some")
    public String index() {
        return "pawned cors!!!!";
    }

봄 부츠 2.0.2의 매력처럼

Axios, Spring Boot, Spring Security 인증에 큰 문제가 있었습니다.

사용 중인 스프링 부트의 버전과 스프링 보안에 유의하십시오.

스프링 부트: 1.5.10 스프링: 4.3.14 스프링 보안 4.2.4

주석 기반 Java 구성을 사용하여 이 문제를 해결하기 위해 다음 클래스를 만들었습니다.

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {

        auth.inMemoryAuthentication()
                .withUser("youruser").password("yourpassword")
                .authorities("ROLE_USER");
    }

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

        http.cors().and().
                authorizeRequests()
                .requestMatchers(CorsUtils:: isPreFlightRequest).permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .httpBasic()
                .realmName("Biometrix");

        http.csrf().disable();

    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowCredentials(true);
        configuration.setAllowedHeaders(Arrays.asList("Authorization"));
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("*"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

Axios의 주요 특징 중 하나는 API가 인증을 필요로 할 때 OPTIONS 요청과 함께 Authorization 헤더를 보내는 것입니다.허용된 헤더 설정에 Authorization을 포함하지 않으면 OPTIONS 요청(Pre Flight 요청이라고도 함)이 실패하고 Axios가 오류를 보고합니다.

보시는 바와 같이 심플하고 적절한 설정을 몇 가지 사용하면 Spring Boot를 사용한CORS 설정은 매우 간단합니다.

작업은 단일 클래스로만 완료할 수 있습니다. 클래스 경로에 이 항목을 추가하십시오.

정도면 스프링 부츠나 스프링 보안에 충분해:

        @Component
        @Order(Ordered.HIGHEST_PRECEDENCE)
        public class MyCorsFilterConfig implements Filter {

            @Override
            public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
                final HttpServletResponse response = (HttpServletResponse) res;
                response.setHeader("Access-Control-Allow-Origin", "*");
                response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
                response.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, enctype");
                response.setHeader("Access-Control-Max-Age", "3600");
                if (HttpMethod.OPTIONS.name().equalsIgnoreCase(((HttpServletRequest) req).getMethod())) {
                    response.setStatus(HttpServletResponse.SC_OK);
                } else {
                    chain.doFilter(req, res);
                }
            }

            @Override
            public void destroy() {
            }

            @Override
            public void init(FilterConfig config) throws ServletException {
            }


        }

javascript CORS에서 발생한 오류를 많이 찾아본 결과, 이 케이스에서 찾은 유일한 우아한 해결책은 Spring만의 클래스 org.springframework의 코르스를 구성하는 것이었습니다.web.web.discloss.를 참조해 주세요.Cors Configuration.Cors Configuration()

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().configurationSource(request -> new CorsConfiguration().applyPermitDefaultValues());
    }
// https://docs.spring.io/spring-boot/docs/2.4.2/reference/htmlsingle/#boot-features-cors
@Configuration
public class MyConfiguration {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(final CorsRegistry registry) {
                registry.addMapping("/**").allowedMethods("*").allowedHeaders("*");
            }
        };
    }
}

스프링 보안을 사용하는 경우 다음을 추가로 설정합니다.

// https://docs.spring.io/spring-security/site/docs/5.4.2/reference/html5/#cors
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

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

        // if Spring MVC is on classpath and no CorsConfigurationSource is provided,
        // Spring Security will use CORS configuration provided to Spring MVC
        http.cors(Customizer.withDefaults());
    }
}

속성 구성용

# ENDPOINTS CORS CONFIGURATION (EndpointCorsProperties)
endpoints.cors.allow-credentials= # Set whether credentials are supported. When not set, credentials are not supported.
endpoints.cors.allowed-headers= # Comma-separated list of headers to allow in a request. '*' allows all headers.
endpoints.cors.allowed-methods=GET # Comma-separated list of methods to allow. '*' allows all methods.
endpoints.cors.allowed-origins= # Comma-separated list of origins to allow. '*' allows all origins. When not set, CORS support is disabled.
endpoints.cors.exposed-headers= # Comma-separated list of headers to include in a response.
endpoints.cors.max-age=1800 # How long, in seconds, the response from a pre-flight request can be cached by clients.

코틀린 용액

...
http.cors().configurationSource {
  CorsConfiguration().applyPermitDefaultValues()
}
...

Webflux용 솔루션(Reactive) Spring Boot은 구글이 이 문제를 'Reactive'로 검색했을 때 가장 높은 결과 중 하나로 표시되기 때문입니다.스프링 부트 버전 2.2.2 사용

@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
  return http.cors().and().build();
}

@Bean
public CorsWebFilter corsFilter() {
  CorsConfiguration config = new CorsConfiguration();

  config.applyPermitDefaultValues();

  config.addAllowedHeader("Authorization");

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

  return new CorsWebFilter(source);
}

완전한 예로서 커스텀 인증 매니저와 연동하는 셋업(이 경우는 JWT 인증)을 들 수 있습니다.https://gist.github.com/FiredLight/d973968cbd837048987ab2385ba6b38f 를 참조해 주세요.

주의:new CorsConfiguration().applyPermitDefaultValues()GET, POST 및 HEAD 메서드만 사용할 수 있습니다.PUT 또는 DELETE를 찾는 경우 다음과 같이 수동으로 메서드를 설정해야 합니다.마지막으로 PUT, PATCH 및 DELETE 메서드를 사전에 실행하는 데 필요한 OPTIONS 메서드를 잊지 마십시오(그렇지 않으면 CORS 오류가 계속 발생합니다).

import static org.springframework.web.cors.CorsConfiguration.ALL;

@Bean
CorsConfigurationSource corsConfigurationSource() {
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowedMethods(Arrays.asList(
            HttpMethod.GET.name(),
            HttpMethod.POST.name(),
            HttpMethod.DELETE.name(),
            HttpMethod.PUT.name(),
            HttpMethod.HEAD.name(),
            HttpMethod.POST.name(),
            HttpMethod.OPTIONS.name()
    ));
    config.setAllowedHeaders(Collections.singletonList(ALL));
    config.setAllowedOrigins(Collections.singletonList(ALL));
    config.setMaxAge(1800L);
    source.registerCorsConfiguration("/**", config);
    return source;
}

클래스 구현 WebMvcConfigr에서는 메서드 addCorsMappings를 덮어쓸 필요가 있습니다.

public class WebMvcConfig implements WebMvcConfigurer {

    private final long MAX_AGE_SECS;


    @Value("${appConfig.cors.allowedOrigins}")
    private String[] allowedOrigins;

    public WebMvcConfig() {
        MAX_AGE_SECS = 3600;
    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
        .allowedOrigins(allowedOrigins)
        .allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS")
        .allowedHeaders("*")
        .allowCredentials(true)
        .maxAge(MAX_AGE_SECS);
    }
}
 

특히 다음 방법을 검토할 필요가 있습니다.configure( HttpSecurity httpSecurity )

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter 
{
    @Autowired
    private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;

    @Autowired
    private UserDetailsService jwtUserDetailsService;

    @Autowired
    private JwtRequestFilter jwtRequestFilter;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        // configure AuthenticationManager so that it knows from where to load
        // user for matching credentials
        // Use BCryptPasswordEncoder
        auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedOrigins("*")
        .allowedMethods("HEAD", "GET", "PUT", "POST",
        "DELETE", "PATCH").allowedHeaders("*");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        
        http
        .cors()
        .and()
        .csrf().disable()
        .authorizeRequests()
        .antMatchers(HttpMethod.GET,"/images/**").permitAll()
        .antMatchers(HttpMethod.POST,"/api/login").permitAll()
        .antMatchers(HttpMethod.POST,"/api/user").permitAll()
        .and()
        .authorizeRequests().anyRequest().authenticated()
        .and()
        .exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint)
        .and()
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class); // Add our custom JWT security filter
        UsernamePasswordAuthenticationFilter.class);
    }
    
    @Override
      protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.cors().configurationSource(request -> {
          var cors = new CorsConfiguration();
          cors.setAllowedOrigins(List.of("http://localhost:4200", "http://127.0.0.1:80", "http://example.com"));
          cors.setAllowedMethods(List.of("GET","POST", "PUT", "DELETE", "OPTIONS"));
          cors.setAllowedHeaders(List.of("*"));
          return cors;
        }).and()...
      }
    }

언급URL : https://stackoverflow.com/questions/36968963/how-to-configure-cors-in-a-spring-boot-spring-security-application

반응형