CORS với khởi động lò xo và anglejs không hoạt động


87

Tôi đang cố gắng gọi các điểm cuối REST trên một ứng dụng (ứng dụng khởi động mùa xuân) từ một ứng dụng khác (anglejs). Các ứng dụng đang chạy trên các máy chủ và cổng sau.

  • Ứng dụng REST, sử dụng khởi động mùa xuân, http://localhost:8080
  • Ứng dụng HTML, sử dụng anglejs, http://localhost:50029

Tôi cũng đang sử dụng spring-securityvới ứng dụng khởi động mùa xuân. Từ ứng dụng HTML, tôi có thể xác thực ứng dụng REST, nhưng sau đó, tôi vẫn không thể truy cập bất kỳ điểm cuối REST nào. Ví dụ, tôi có một dịch vụ anglejs được định nghĩa như sau.

adminServices.factory('AdminService', ['$resource', '$http', 'conf', function($resource, $http, conf) {
    var s = {};
    s.isAdminLoggedIn = function(data) {
        return $http({
            method: 'GET',
            url: 'http://localhost:8080/api/admin/isloggedin',
            withCredentials: true,
            headers: {
                'X-Requested-With': 'XMLHttpRequest'
            }
        });
    };
    s.login = function(username, password) {
        var u = 'username=' + encodeURI(username);
        var p = 'password=' + encodeURI(password);
        var r = 'remember_me=1';
        var data = u + '&' + p + '&' + r;

        return $http({
            method: 'POST',
            url: 'http://localhost:8080/login',
            data: data,
            headers: {'Content-Type': 'application/x-www-form-urlencoded'}
        });
    };
    return s;
}]);

Bộ điều khiển anglejs trông giống như sau.

adminControllers.controller('LoginController', ['$scope', '$http', 'AdminService', function($scope, $http, AdminService) {
    $scope.username = '';
    $scope.password = '';

    $scope.signIn = function() {
        AdminService.login($scope.username, $scope.password)
            .success(function(d,s) {
                if(d['success']) {
                    console.log('ok authenticated, call another REST endpoint');
                    AdminService.isAdminLoggedIn()
                        .success(function(d,s) {
                            console.log('i can access a protected REST endpoint after logging in');
                        })
                        .error(function(d, s) { 
                            console.log('huh, error checking to see if admin is logged in');
                            $scope.reset();
                        });
                } else {
                    console.log('bad credentials?');
                }
            })
            .error(function(d, s) {
                console.log('huh, error happened!');
            });
    };
}]);

Trong cuộc gọi đến http://localhost:8080/api/admin/isloggedin, tôi nhận được một 401 Unauthorized.

Về phía ứng dụng REST, tôi có một bộ lọc CORS trông giống như sau.

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

    @Override
    public void destroy() { }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;

        response.setHeader("Access-Control-Allow-Origin", "http://localhost:50029");
        response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "X-Requested-With, X-Auth-Token");
        response.setHeader("Access-Control-Allow-Credentials", "true");

        if(!"OPTIONS".equalsIgnoreCase(request.getMethod())) {
            chain.doFilter(req, res);
        }
    }

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

Cấu hình bảo mật mùa xuân của tôi trông giống như sau.

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private RestAuthenticationEntryPoint restAuthenticationEntryPoint;

    @Autowired
    private JsonAuthSuccessHandler jsonAuthSuccessHandler;

    @Autowired
    private JsonAuthFailureHandler jsonAuthFailureHandler;

    @Autowired
    private JsonLogoutSuccessHandler jsonLogoutSuccessHandler;

    @Autowired
    private AuthenticationProvider authenticationProvider;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private PersistentTokenRepository persistentTokenRepository;

    @Value("${rememberme.key}")
    private String rememberMeKey;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .exceptionHandling()
            .authenticationEntryPoint(restAuthenticationEntryPoint)
                .and()
            .authorizeRequests()
                .antMatchers("/api/admin/**").hasRole("ADMIN")
                .antMatchers("/", "/admin", "/css/**", "/js/**", "/fonts/**", "/api/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .successHandler(jsonAuthSuccessHandler)
                .failureHandler(jsonAuthFailureHandler)
                .permitAll()
                .and()
            .logout()
                .deleteCookies("remember-me", "JSESSIONID")
                .logoutSuccessHandler(jsonLogoutSuccessHandler)
                .permitAll()
                .and()
            .rememberMe()
                .userDetailsService(userDetailsService)
                .tokenRepository(persistentTokenRepository)
                .rememberMeCookieName("REMEMBER_ME")
                .rememberMeParameter("remember_me")
                .tokenValiditySeconds(1209600)
                .useSecureCookie(false)
                .key(rememberMeKey);
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .authenticationProvider(authenticationProvider);
    }
}

Tất cả những gì trình xử lý đang làm là viết ra một phản hồi JSON giống như {success: true}dựa trên việc người dùng đã đăng nhập, không xác thực được hay đã đăng xuất. Hình RestAuthenticationEntryPointnhư sau.

@Component
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {

    @Override
    public void commence(HttpServletRequest req, HttpServletResponse resp, AuthenticationException ex)
            throws IOException, ServletException {
        resp.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
    }

}

Bất kỳ ý tưởng về những gì tôi đang thiếu hoặc làm sai?


Tôi cho rằng bạn cũng cần phải thực hiện xác thực, như mã thông báo hoặc thứ gì đó. Bạn có 2 máy chủ. Bạn đã xem hướng dẫn đó chưa? spring.io/guides/tutorials/spring-security-and-angular-js
Gokhan Oner,

@GokhanOner Làm cách nào để thực hiện xác thực? Đó có lẽ là mảnh ghép còn thiếu cho vấn đề này. Ngoài ra, vâng, tôi đã xem qua những hướng dẫn đó và không nghĩ rằng chúng phù hợp với cách tiếp cận của tôi. Hai phần đầu tiên xử lý xác thực Http-Basic, sau đó phần thứ ba xử lý Redis (tôi không muốn hoặc có kế hoạch lấy đó làm phụ thuộc), và sau đó, hướng dẫn cuối cùng là về API Gatewayđám mây mùa xuân, mà tôi nghĩ là quá mức cần thiết .
Jane Wayne

Tôi cho rằng bạn có thể làm điều đó mà không cần redis, nó chỉ là một kho lưu trữ khóa-giá trị bộ nhớ cache. Bạn cần lưu trữ xác thực và mã thông báo CSRF trên một cửa hàng, có thể có bản đồ bên trong một cách nhanh chóng. Điều quan trọng ở đây là khóa xác thực. xem ví dụ: github.com/dsyer/spring-security-angular/tree/master/… và trang có "máy chủ tài nguyên". Bạn sẽ thấy một số hạt bổ sung được xác định, thứ tự của bộ lọc CORS cũng quan trọng. Và một số chỗ dựa. thay đổi cũng cần thiết.
Gokhan Oner

Ok, tôi đã nghiên cứu nhanh. Tất cả những gì bạn cần, để thoát khỏi Redis, là đóng một bean springSessionRepositoryFilter, xem github.com/spring-projects/spring-session/blob/1.0.0.RC1/… , cũng như bean sessionRepository và trong bean này, thay vì RedisOperationsSessionRepository, bạn có thể sử dụng MapSessionRepository, cũng có trong Spring-session. Và sau đó làm theo ví dụ.
Gokhan Oner,

Câu trả lời:


102
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class SimpleCORSFilter implements Filter {

private final Logger log = LoggerFactory.getLogger(SimpleCORSFilter.class);

public SimpleCORSFilter() {
    log.info("SimpleCORSFilter init");
}

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

    HttpServletRequest request = (HttpServletRequest) req;
    HttpServletResponse response = (HttpServletResponse) res;

    response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
    response.setHeader("Access-Control-Allow-Credentials", "true");
    response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me");

    chain.doFilter(req, res);
}

@Override
public void init(FilterConfig filterConfig) {
}

@Override
public void destroy() {
}

}

Không cần xác định thêm bộ lọc này chỉ cần thêm lớp này. Spring sẽ được quét và thêm nó cho bạn. Bộ lọc đơn giản. Đây là ví dụ: spring-enable-cors


Một số câu hỏi. 1) Tôi phải đặt các hằng số chuỗi ở đâu HEADERSX_REDIRECT_LOCATION_HEADER? 2) Dòng request.getRequestURL());có lỗi đánh máy hoặc sao chép / dán không? 3) Tại sao bạn không kiểm tra OPTIONSvà đơn giản là tiếp tục với chuỗi bộ lọc?
Jane Wayne

2
Nhưng nó chặn thực thi AuthenticationEntryPoint .. Vui lòng hướng dẫn
Pra_A 22/09/15

1
Cảm ơn bạn rất nhiều, nó đã giúp tôi tuyệt vời trong cuộc đấu tranh của tôi để có được mùa xuân và than hồng để làm việc cùng nhau. Cổ vũ người bạn đời!
Tomasz Szymanek

FindBugs không thích đặt thông số tiêu đề với: request.getHeader("Origin")như được hiển thị ở trên vì phân tách phản hồi HTTP
Glenn

3
Nếu có các bộ lọc khác trong ứng dụng của bạn, bộ lọc này cần được ưu tiên cao nhất bằng cách chú thích bộ lọc bằng @Order(Ordered.HIGHEST_PRECEDENCE) .
Shafiul

43

Tôi đã từng rơi vào tình huống tương tự. Sau khi thực hiện nghiên cứu và thử nghiệm, đây là phát hiện của tôi:

  1. Với Spring Boot, cách được khuyến nghị để kích hoạt CORS toàn cầu là khai báo trong Spring MVC và kết hợp với @CrossOrigincấu hình chi tiết như:

    @Configuration
    public class CorsConfig {
    
        @Bean
        public WebMvcConfigurer corsConfigurer() {
            return new WebMvcConfigurerAdapter() {
                @Override
                public void addCorsMappings(CorsRegistry registry) {
                    registry.addMapping("/**").allowedMethods("GET", "POST", "PUT", "DELETE").allowedOrigins("*")
                            .allowedHeaders("*");
                }
            };
        }
    }
    
  2. Bây giờ, vì bạn đang sử dụng Spring Security, bạn cũng phải bật CORS ở cấp Spring Security để cho phép nó tận dụng cấu hình được xác định ở cấp Spring MVC là:

    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.cors().and()...
        }
    }
    

    Đây là hướng dẫn rất hay giải thích hỗ trợ CORS trong Spring MVC framework.


3
up nó hoạt động với thay đổi này http .csrf () .disable () .cors () .and ()
marti_

1
@Osgux tốt khi biết rằng :) kể từ khi tôi đang sử dụng JWT cho phép và họ được an toàn CSRF, tôi đã không đưa rằng có .. đừng quên upvote nếu nó giúp :)
Yogen Rai

vâng, tôi đã thêm +1 = D
marti_

@ Hủy bỏ vấn đề bạn gặp phải là gì?
Yogen Rai

Không tải được <địa chỉ nghỉ ngơi của tôi>: Phản hồi cho yêu cầu preflight không vượt qua kiểm tra kiểm soát truy cập: Không có tiêu đề 'Access-Control-Allow-Origin' có trên tài nguyên được yêu cầu. Nguồn gốc ' localhost: 8090 ' do đó không được phép truy cập.
Marcel

22

Nếu bạn muốn bật CORS mà không cần sử dụng bộ lọc hoặc không có tệp cấu hình, chỉ cần thêm

@CrossOrigin

lên đầu bộ điều khiển của bạn và nó hoạt động.


4
Những rủi ro bảo mật khi thực hiện theo cách tiếp cận này là gì?
Balaji Vignesh

Làm việc cho tôi, tôi đã cố gắng thêm tiêu đề trực tiếp để phản hồi nhưng nó không hoạt động vì không xử lý preflight. Tôi nghĩ rằng điều này không được bảo mật nhưng có thể được sử dụng là một số ứng dụng nội bộ.
amisiuryk

Đã làm cho tôi. giải pháp khá tiện dụng cho ứng dụng nội bộ.
Ajay Kumar

8

Để xây dựng các câu trả lời khác ở trên, trong trường hợp bạn có ứng dụng dịch vụ Spring boot REST (không phải Spring MVC) với bảo mật Spring, thì việc kích hoạt CORS thông qua bảo mật Spring là đủ (nếu bạn sử dụng Spring MVC thì có thể sử dụng WebMvcConfigurerbean như Yogen đã đề cập con đường để đi vì bảo mật mùa xuân sẽ ủy quyền cho định nghĩa CORS được đề cập trong đó)

Vì vậy, bạn cần có một cấu hình bảo mật thực hiện những việc sau:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
    //other http security config
    http.cors().configurationSource(corsConfigurationSource());
}

//This can be customized as required
CorsConfigurationSource corsConfigurationSource() {
    CorsConfiguration configuration = new CorsConfiguration();
    List<String> allowOrigins = Arrays.asList("*");
    configuration.setAllowedOrigins(allowOrigins);
    configuration.setAllowedMethods(singletonList("*"));
    configuration.setAllowedHeaders(singletonList("*"));
    //in case authentication is enabled this flag MUST be set, otherwise CORS requests will fail
    configuration.setAllowCredentials(true);
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);
    return source;
}

}

Liên kết này có nhiều thông tin tương tự: https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#cors

Ghi chú:

  1. Bật CORS cho tất cả các nguồn gốc (*) cho một ứng dụng được triển khai trước có thể không phải lúc nào cũng là một ý kiến ​​hay.
  2. CSRF có thể được kích hoạt thông qua tùy chỉnh Spring HttpSecurity mà không gặp bất kỳ sự cố nào
  3. Trong trường hợp bạn đã bật xác thực trong ứng dụng với Spring ( UserDetailsServiceví dụ: thông qua một ví dụ) thì configuration.setAllowCredentials(true);phải thêm

Đã kiểm tra khởi động Spring 2.0.0.RELEASE (tức là Spring 5.0.4.RELEASE và Spring security 5.0.3.RELEASE)


Điều này đã giải quyết vấn đề của tôi. Mới làm quen với Spring và Spring Boot, tôi nhận ra rằng mình không xây dựng bằng Sring MVC. Tôi đã có một Khách hàng Vue.js. Các câu trả lời khác dường như dành cho Spring MVC, nhưng câu trả lời này phù hợp với xác thực và ủy quyền đã được triển khai của tôi.
jaletechs

Xin chào @jaletechs, tôi cũng đang sử dụng nuxtJs (một khung vuejs) nhưng khi nói đến thiết lập cookie, nó không hoạt động. bạn có thể đủ tốt để giúp đỡ về điều này.
KAmit

6

Tôi đang sử dụng spring boot 2.1.0và những gì hiệu quả với tôi là

A. Thêm ánh xạ cors bằng cách:

@Configuration
public class Config implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedOrigins("*");
    }
}

B. Thêm cấu hình bên dưới vào của tôi HttpSecurityđể bảo mật mùa xuân

.cors().configurationSource(new CorsConfigurationSource() {

    @Override
    public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowedHeaders(Collections.singletonList("*"));
        config.setAllowedMethods(Collections.singletonList("*"));
        config.addAllowedOrigin("*");
        config.setAllowCredentials(true);
        return config;
    }
})

Ngoài ra trong trường hợp có proxy Zuul, bạn có thể sử dụng INSTEAD OF A và B này (chỉ cần sử dụng HttpSecurity.cors()để kích hoạt nó trong bảo mật Spring):

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

trả về CorsFilter mới (nguồn); không lỗi constructor như vậy
Aadam

@Aadam Bạn có đang sử dụng cùng một phiên bản khởi động mùa xuân như tôi không?
tháng 9,

2.1.5 đang được sử dụng
Aadam

@Aadam Đó có thể là lý do không may.
tháng 9

@Aadam Hãy đảm bảo rằng bạn đang sử dụng CorsFilter từ org.springframework.web.filter.CorsFilter. Tôi đã gặp vấn đề tương tự khi vô tình sử dụng nó từ các gói catalina.
tháng 9,

5

Điều này phù hợp với tôi:

@Configuration
public class MyConfig extends WebSecurityConfigurerAdapter  {
   //...
   @Override
   protected void configure(HttpSecurity http) throws Exception {

       //...         

       http.cors().configurationSource(new CorsConfigurationSource() {

        @Override
        public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
            CorsConfiguration config = new CorsConfiguration();
            config.setAllowedHeaders(Collections.singletonList("*"));
            config.setAllowedMethods(Collections.singletonList("*"));
            config.addAllowedOrigin("*");
            config.setAllowCredentials(true);
            return config;
        }
      });

      //...

   }

   //...

}

Mặc dù mã này có thể trả lời câu hỏi, nhưng việc cung cấp thêm ngữ cảnh liên quan đến lý do và / hoặc cách mã này trả lời câu hỏi sẽ cải thiện giá trị lâu dài của nó.
Adriano Martins

1
Trong trường hợp xác thực được kích hoạt thông qua bảo mật Spring, thì config.setAllowCredentials (true); PHẢI đặt nếu không các yêu cầu CORS vẫn sẽ không thành công
Deepak

2

Đối với tôi, điều duy nhất hoạt động 100% khi sử dụng bảo mật mùa xuân là bỏ qua tất cả các lông tơ bổ sung của bộ lọc bổ sung và đậu và bất kỳ "phép thuật" gián tiếp nào mà mọi người liên tục đề xuất rằng nó hiệu quả với họ nhưng không phải với tôi.

Thay vào đó, chỉ cần buộc nó phải viết các tiêu đề bạn cần với một cách đơn giản StaticHeadersWriter:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

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

        http
            // your security config here
            .authorizeRequests()
            .antMatchers(HttpMethod.TRACE, "/**").denyAll()
            .antMatchers("/admin/**").authenticated()
            .anyRequest().permitAll()
            .and().httpBasic()
            .and().headers().frameOptions().disable()
            .and().csrf().disable()
            .headers()
            // the headers you want here. This solved all my CORS problems! 
            .addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Origin", "*"))
            .addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Methods", "POST, GET"))
            .addHeaderWriter(new StaticHeadersWriter("Access-Control-Max-Age", "3600"))
            .addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Credentials", "true"))
            .addHeaderWriter(new StaticHeadersWriter("Access-Control-Allow-Headers", "Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization"));
    }
}

Đây là cách trực tiếp và rõ ràng nhất mà tôi thấy để làm điều đó. Hy vọng nó sẽ giúp một ai đó.


1

Bước 1

Bằng cách chú thích bộ điều khiển bằng @CrossOriginchú thích sẽ cho phép các cấu hình CORS.

@CrossOrigin
@RestController
public class SampleController { 
  .....
}

Bước 2

Spring đã có CorsFilter mặc dù Bạn chỉ có thể đăng ký CorsFilter của riêng mình dưới dạng bean để cung cấp cấu hình của riêng bạn như sau.

@Bean
public CorsFilter corsFilter() {
    final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    final CorsConfiguration config = new CorsConfiguration();
    config.setAllowedOrigins(Collections.singletonList("http://localhost:3000")); // Provide list of origins if you want multiple origins
    config.setAllowedHeaders(Arrays.asList("Origin", "Content-Type", "Accept"));
    config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "OPTIONS", "DELETE", "PATCH"));
    config.setAllowCredentials(true);
    source.registerCorsConfiguration("/**", config);
    return new CorsFilter(source);
}

0

kiểm tra cái này:

@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
    ...
            .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
    ...
}

Mặc dù mã này có thể trả lời câu hỏi, nhưng việc cung cấp thêm ngữ cảnh liên quan đến lý do và / hoặc cách mã này trả lời câu hỏi sẽ cải thiện giá trị lâu dài của nó.
rollstuhlfahrer

0

Mở rộng lớp WebSecurityConfigurerAdapter và ghi đè phương thức config () trong lớp @EnableWebSecurity của bạn sẽ hoạt động: Dưới đây là lớp mẫu

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

         http
        .csrf().disable()
        .exceptionHandling();
         http.headers().cacheControl();

        @Override
        public CorsConfiguration getCorsConfiguration(final HttpServletRequest request) {
            return new CorsConfiguration().applyPermitDefaultValues();
        }
    });
   }
}

0

Nếu ban đầu chương trình của bạn không sử dụng bảo mật mùa xuân và không đủ khả năng thay đổi mã, thì việc tạo proxy ngược đơn giản có thể thực hiện thủ thuật. Trong trường hợp của tôi, tôi đã sử dụng Nginx với cấu hình sau:

http {
  server {
    listen 9090;
    location / {
      if ($request_method = 'OPTIONS') {
      add_header 'Access-Control-Allow-Origin' '*';
      add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
      #
      # Custom headers and headers various browsers *should* be OK with but aren't
      #
      add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
      #
      # Tell client that this pre-flight info is valid for 20 days
      #
      add_header 'Access-Control-Max-Age' 1728000;
      add_header 'Content-Type' 'text/plain; charset=utf-8';
      add_header 'Content-Length' 0;
      return 204;
      }
      if ($request_method = 'POST') {
      add_header 'Access-Control-Allow-Origin' '*';
      add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
      add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
      add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
      }
      if ($request_method = 'GET') {
      add_header 'Access-Control-Allow-Origin' '*';
      add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
      add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
      add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
      }

      proxy_pass http://localhost:8080;
    }
  }
}

Chương trình của tôi đã nghe : 8080 .

REF: CORS trên Nginx


0

Đây là những gì làm việc cho tôi.

@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

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

        http.cors();
    }

}

@Configuration
public class WebConfiguration implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry
            .addMapping("/**")
            .allowedMethods("*")
            .allowedHeaders("*")
            .allowedOrigins("*")
            .allowCredentials(true);
    }

}

0

Câu trả lời này sao chép câu trả lời @abosancic nhưng bổ sung thêm độ an toàn để tránh bị CORS khai thác .

Mẹo 1: Không phản ánh Nguồn gốc đến mà không kiểm tra danh sách các máy chủ được phép truy cập.

Mẹo 2: Chỉ cho phép yêu cầu đã xác thực cho các máy chủ có trong danh sách cho phép.

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

@Component
public class SimpleCORSFilter implements Filter {

    private final Logger log = LoggerFactory.getLogger(SimpleCORSFilter.class);

    private List<String> allowedOrigins;

    public SimpleCORSFilter() {
        log.info("SimpleCORSFilter init");
        allowedOrigins = new ArrayList<>();
        allowedOrigins.add("https://mysafeorigin.com");
        allowedOrigins.add("https://itrustthissite.com");
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        String allowedOrigin = getOriginToAllow(request.getHeader("Origin"));

        if(allowedOrigin != null) {
            response.setHeader("Access-Control-Allow-Origin", allowedOrigin);
            response.setHeader("Access-Control-Allow-Credentials", "true");
        }

        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me");

        chain.doFilter(req, res);
    }

    @Override
    public void init(FilterConfig filterConfig) {
    }

    @Override
    public void destroy() {
    }

    public String getOriginToAllow(String incomingOrigin) {
        if(allowedOrigins.contains(incomingOrigin.toLowerCase())) {
            return incomingOrigin;
        } else {
            return null;
        }
    }
}

0

Trong ứng dụng Spring Boot, chúng tôi đã thiết lập CorsConfigurationSource như thế này.

Trình tự thêm allowedOrignsđầu tiên và sau đó thiết lập applyPermitDefaultValues()hãy để Spring thiết lập giá trị mặc định cho các tiêu đề được phép, tiêu đề hiển thị, phương thức được phép, v.v. để chúng ta không phải chỉ định chúng.

    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("http://localhost:8084"));
        configuration.applyPermitDefaultValues();

        UrlBasedCorsConfigurationSource configurationSource = new UrlBasedCorsConfigurationSource();
        configurationSource.registerCorsConfiguration("/**", configuration);
        return configurationSource;
    }
    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.authorizeRequests()
                .antMatchers("/api/**")
                .access("@authProvider.validateApiKey(request)")
                .anyRequest().authenticated()
                .and().cors()
                .and().csrf().disable()
                .httpBasic().authenticationEntryPoint(authenticationEntryPoint);

        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

0

Chỉ cần Tạo một lớp duy nhất như thế, mọi thứ sẽ ổn với điều này:

        @Component
        @Order(Ordered.HIGHEST_PRECEDENCE)
        public class MyCorsConfig 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 {
            }
        }

0

Đây là những gì đã làm việc cho tôi để vô hiệu hóa CORS giữa Spring boot và React

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    /**
     * Overriding the CORS configuration to exposed required header for ussd to work
     *
     * @param registry CorsRegistry
     */

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("*")
                .allowedMethods("*")
                .allowedHeaders("*")
                .allowCredentials(true)
                .maxAge(4800);
    }
}

Tôi đã phải sửa đổi cấu hình Bảo mật cũng như bên dưới:

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable()
                    .cors().configurationSource(new CorsConfigurationSource() {

                @Override
                public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
                    CorsConfiguration config = new CorsConfiguration();
                    config.setAllowedHeaders(Collections.singletonList("*"));
                    config.setAllowedMethods(Collections.singletonList("*"));
                    config.addAllowedOrigin("*");
                    config.setAllowCredentials(true);
                    return config;
                }
            }).and()
                    .antMatcher("/api/**")
                    .authorizeRequests()
                    .anyRequest().authenticated()
                    .and().httpBasic()
                    .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                    .and().exceptionHandling().accessDeniedHandler(apiAccessDeniedHandler());
        }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.