CORS dengan spring-boot dan angularjs tidak berfungsi

87

Saya mencoba memanggil titik akhir REST pada satu aplikasi (aplikasi spring-boot) dari yang lain (angularjs). Aplikasi berjalan di host dan port berikut.

  • Aplikasi REST, menggunakan spring boot, http://localhost:8080
  • Aplikasi HTML, menggunakan angularjs, http://localhost:50029

Saya juga menggunakan spring-securitydengan aplikasi spring-boot. Dari aplikasi HTML, saya dapat mengautentikasi ke aplikasi REST, tetapi setelah itu, saya masih tidak dapat mengakses titik akhir REST. Misalnya, saya memiliki layanan angularjs yang didefinisikan sebagai berikut.

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;
}]);

Pengontrol angularjs terlihat seperti berikut.

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!');
            });
    };
}]);

Saat panggilan ke http://localhost:8080/api/admin/isloggedin, saya mendapatkan 401 Unauthorized.

Di sisi aplikasi REST, saya memiliki filter CORS yang terlihat seperti berikut.

@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 { }
}

Konfigurasi keamanan pegas saya terlihat seperti berikut ini.

@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);
    }
}

Semua yang dilakukan penangan adalah menuliskan tanggapan JSON seperti {success: true}berdasarkan apakah pengguna masuk, gagal mengautentikasi, atau keluar. The RestAuthenticationEntryPointterlihat seperti berikut.

@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");
    }

}

Adakah ide tentang apa yang saya lewatkan atau lakukan salah?

Jane Wayne
sumber
Saya kira Anda perlu membawa otentikasi juga, seperti token atau sesuatu. Anda memiliki 2 server. Apakah Anda melihat tutorial itu? spring.io/guides/tutorials/spring-security-and-angular-js
Gokhan Oner
@GokhanOner Bagaimana cara saya melakukan otentikasi? Itu mungkin bagian yang hilang dari masalah ini. Juga, ya, saya telah melalui tutorial tersebut dan tidak berpikir mereka selaras dengan pendekatan saya. Dua bagian pertama berurusan dengan otentikasi Http-Basic, kemudian bagian ketiga berurusan dengan Redis (saya tidak ingin atau berencana untuk mendapatkannya sebagai ketergantungan), dan kemudian tutorial terakhir adalah tentang API Gatewaydengan awan musim semi, yang saya pikir berlebihan .
Jane Wayne
Saya kira Anda dapat melakukannya tanpa redis, itu hanya penyimpanan cache nilai-kunci. Anda perlu menyimpan otentikasi dan token CSRF di toko, mungkin di dalam peta dengan cepat. Hal utama di sini adalah kunci otentikasi. lihat contoh: github.com/dsyer/spring-security-angular/tree/master/… dan halaman dengan "server sumber daya". Anda akan melihat beberapa biji tambahan ditentukan, urutan filter CORS juga penting. Dan beberapa alat penyangga. perubahan juga diperlukan.
Gokhan Oner
Oke, saya melakukan riset singkat. Yang Anda butuhkan, untuk menyingkirkan Redis, adalah membuat kacang springSessionRepositoryFilter, lihat github.com/spring-projects/spring-session/blob/1.0.0.RC1/… , dan juga kacang sessionRepository dan kacang ini, alih-alih RedisOperationsSessionRepository, Anda bisa menggunakan MapSessionRepository, yang juga ada dalam sesi musim semi. Dan kemudian ikuti contohnya.
Gokhan Oner

Jawaban:

104
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() {
}

}

Tidak perlu lebih mendefinisikan filter ini cukup tambahkan kelas ini. Spring akan memindai dan menambahkannya untuk Anda. SimpleCORSFilter. Berikut adalah contohnya: spring-enable-cors

abosancic
sumber
Beberapa pertanyaan. 1) Di mana saya harus meletakkan konstanta string HEADERSdan X_REDIRECT_LOCATION_HEADER? 2) Apakah baris request.getRequestURL());salah ketik atau salin / tempel? 3) Mengapa Anda tidak memeriksa OPTIONSdan melanjutkan dengan rantai filter?
Jane Wayne
2
Tapi itu memblokir untuk mengeksekusi AuthenticationEntryPoint .. Harap
pandu
1
Terima kasih banyak, itu sangat membantu saya dalam perjuangan saya untuk mendapatkan musim semi dan bara untuk bekerja bersama. Bergembiralah teman!
Tomasz Szymanek
FindBugs tidak suka menyetel parameter header dengan: request.getHeader("Origin")seperti yang ditunjukkan di atas karena pemisahan respons HTTP
Glenn
3
Jika ada filter lain dalam aplikasi Anda, filter ini harus diutamakan dengan memberi anotasi pada filter dengan @Order(Ordered.HIGHEST_PRECEDENCE) .
Shafiul
44

Saya pernah mengalami situasi serupa. Setelah melakukan penelitian dan pengujian, berikut temuan saya:

  1. Dengan Spring Boot, cara yang disarankan untuk mengaktifkan CORS global adalah dengan mendeklarasikan di dalam Spring MVC dan dikombinasikan dengan @CrossOriginkonfigurasi halus sebagai:

    @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. Sekarang, karena Anda menggunakan Spring Security, Anda harus mengaktifkan CORS pada level Spring Security juga untuk memungkinkannya memanfaatkan konfigurasi yang ditentukan pada level Spring MVC sebagai:

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

    Berikut adalah tutorial yang sangat bagus yang menjelaskan dukungan CORS dalam kerangka MVC Spring.

Yogen Rai
sumber
3
up itu berfungsi dengan perubahan ini http .csrf () .disable () .cors () .and ()
marti_
1
@Osgux senang mendengarnya :) karena saya menggunakan JWT untuk otorisasi dan mereka aman csrf, saya tidak menaruhnya di sana .. jangan lupa untuk upvote jika membantu :)
Yogen Rai
ya saya menambahkan +1 = D
marti_
@Marcel masalah apa yang kamu dapatkan?
Yogen Rai
Gagal memuat <alamat istirahat saya>: Tanggapan untuk permintaan preflight tidak lolos pemeriksaan kontrol akses: Tidak ada header 'Access-Control-Allow-Origin' pada sumber yang diminta. Asal ' localhost: 8090 ' tidak diizinkan akses.
Marcel
22

Jika Anda ingin mengaktifkan CORS tanpa menggunakan filter atau tanpa file konfigurasi, tambahkan saja

@CrossOrigin

ke bagian atas pengontrol Anda dan berfungsi.

Eduardo Dennis
sumber
4
Apa risiko keamanan dengan mengikuti pendekatan ini?
Balaji Vignesh
Berhasil untuk saya, saya mencoba menambahkan tajuk langsung ke respons tetapi tidak berhasil karena preflight tidak ditangani. Saya pikir ini tidak diamankan tetapi mungkin digunakan adalah beberapa aplikasi internal.
amisiuryk
Bekerja untuk saya. solusi yang cukup berguna untuk aplikasi internal.
Ajay Kumar
8

Untuk membangun jawaban lain di atas, jika Anda memiliki aplikasi layanan Spring boot REST (bukan Spring MVC) dengan keamanan Spring, maka mengaktifkan CORS melalui keamanan Spring sudah cukup (jika Anda menggunakan Spring MVC maka gunakan WebMvcConfigurer kacang seperti yang disebutkan oleh Yogen dapat cara untuk pergi karena keamanan Spring akan mendelegasikan definisi CORS yang disebutkan di dalamnya)

Jadi, Anda perlu memiliki konfigurasi keamanan yang melakukan hal berikut:

@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;
}

}

Tautan ini memiliki lebih banyak informasi tentang hal yang sama: https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#cors

catatan:

  1. Mengaktifkan CORS untuk semua asal (*) untuk aplikasi yang di-deploy prod mungkin tidak selalu merupakan ide yang baik.
  2. CSRF dapat diaktifkan melalui kustomisasi Spring HttpSecurity tanpa masalah apa pun
  3. Jika Anda mengaktifkan otentikasi di aplikasi dengan Spring (melalui UserDetailsServicemisalnya) maka configuration.setAllowCredentials(true);harus ditambahkan

Diuji untuk Spring boot 2.0.0.RELEASE (yaitu Spring 5.0.4.RELEASE dan Spring security 5.0.3.RELEASE)

Deepak
sumber
Ini memecahkan masalah saya. Menjadi baru di Spring dan Spring Boot, saya menyadari saya tidak membangun dengan Sring MVC. Saya memiliki Klien Vue.js. Jawaban lain tampaknya untuk Spring MVC, tetapi jawaban ini cocok dengan otentikasi dan otorisasi saya yang sudah diterapkan.
jaletechs
Hai @jaletechs, saya juga menggunakan nuxtJs (kerangka kerja vuejs) tetapi ketika mengatur cookie, itu tidak berfungsi. akankah Anda berbaik hati membantu dalam hal ini.
KAmit
6

Saya menggunakan spring boot 2.1.0dan apa yang berhasil bagi saya adalah

A. Tambahkan pemetaan kors dengan:

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

B. Tambahkan konfigurasi di bawah ini ke my HttpSecurityfor spring security

.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;
    }
})

Juga dalam kasus proxy Zuul Anda dapat menggunakan ini BUKAN A dan B (cukup gunakan HttpSecurity.cors()untuk mengaktifkannya di keamanan 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);
}
Sep GH
sumber
return baru CorsFilter (source); bukan kesalahan konstruktor seperti itu
Aadam
@ Aadam Apakah Anda menggunakan versi boot musim semi yang sama seperti yang saya lakukan?
Sep GH
2.1.5 sedang digunakan
Aadam
@Aadam Pastikan Anda menggunakan CorsFilter dari org.springframework.web.filter.CorsFilter. Saya memiliki masalah yang sama ketika saya menggunakannya dari paket katalina secara tidak sengaja.
Sep GH
5

Ini bekerja untuk saya:

@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;
        }
      });

      //...

   }

   //...

}
Renan Polisciuc
sumber
Meskipun kode ini dapat menjawab pertanyaan, memberikan konteks tambahan tentang mengapa dan / atau bagaimana kode ini menjawab pertanyaan tersebut meningkatkan nilai jangka panjangnya.
Adriano Martins
1
Jika otentikasi diaktifkan melalui keamanan Spring, maka config.setAllowCredentials (true); HARUS diletakkan jika tidak permintaan CORS masih akan gagal
Deepak
2

Bagi saya, satu-satunya hal yang berhasil 100% saat pengaman pegas digunakan adalah melewatkan semua bulu tambahan dari filter dan kacang tambahan dan "sihir" tidak langsung apa pun yang terus disarankan orang yang berhasil untuk mereka tetapi tidak untuk saya.

Alih-alih memaksanya untuk menulis header yang Anda butuhkan dengan polos 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"));
    }
}

Ini adalah cara paling langsung dan eksplisit yang saya temukan untuk melakukannya. Semoga bisa membantu seseorang.

Jeronimo Backes
sumber
1

Inilah yang berhasil bagi saya.

@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);
    }

}
Dennis Crissman II
sumber
1

Langkah 1

Dengan memberi anotasi, pengontrol dengan @CrossOriginanotasi akan memungkinkan konfigurasi CORS.

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

Langkah 2

Spring sudah memiliki CorsFilter meskipun Anda bisa mendaftarkan CorsFilter Anda sendiri sebagai kacang untuk menyediakan konfigurasi Anda sendiri sebagai berikut.

@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);
}
Saveendra Ekanayake
sumber
0

Periksa ini:

@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
    ...
            .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
    ...
}
yibourkelidrissi
sumber
Meskipun kode ini dapat menjawab pertanyaan, memberikan konteks tambahan tentang mengapa dan / atau bagaimana kode ini menjawab pertanyaan tersebut meningkatkan nilai jangka panjangnya.
rollstuhlfahrer
0

Memperluas kelas WebSecurityConfigurerAdapter dan mengganti metode configure () di kelas @EnableWebSecurity Anda akan berfungsi: Di ​​bawah ini adalah kelas contoh

@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();
        }
    });
   }
}
keyRen
sumber
0

Jika awalnya program Anda tidak menggunakan keamanan pegas dan tidak mampu membayar perubahan kode, membuat proxy balik sederhana dapat membantu. Dalam kasus saya, saya menggunakan Nginx dengan konfigurasi berikut:

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;
    }
  }
}

Program saya mendengarkan : 8080 .

REF: CORS di Nginx

Orvyl
sumber
0

Jawaban ini menyalin jawaban @abosancic tetapi menambahkan keamanan ekstra untuk menghindari eksploitasi CORS .

Tip 1: Jangan mencerminkan Origin yang masuk apa adanya tanpa memeriksa daftar host yang diizinkan untuk mengakses.

Kiat 2: Izinkan permintaan yang memiliki kredensial hanya untuk host yang masuk daftar putih.

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;
        }
    }
}
Shailesh Pratapwar
sumber
0

Di aplikasi Spring Boot kami, kami telah menyiapkan CorsConfigurationSource seperti ini.

Urutan penambahan allowedOrignspertama dan kemudian pengaturan applyPermitDefaultValues()membiarkan Spring mengatur nilai default untuk header yang diizinkan, header yang diekspos, metode yang diizinkan, dll. Jadi kita tidak perlu menentukannya.

    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);
    }
Temui Shah
sumber
0

Buat saja satu kelas seperti, semuanya akan baik-baik saja dengan ini:

        @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 {
            }
        }
Imranmadbar
sumber
0

Inilah yang berhasil bagi saya untuk menonaktifkan CORS antara Spring boot dan 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);
    }
}

Saya harus mengubah konfigurasi Keamanan juga seperti di bawah ini:

        @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());
        }
Gil Nz
sumber