Rumah  >  Artikel  >  Java  >  Cara mengkonfigurasi penapis merentas domain dalam SpringBoot untuk membenarkan akses merentas domain

Cara mengkonfigurasi penapis merentas domain dalam SpringBoot untuk membenarkan akses merentas domain

王林
王林ke hadapan
2023-05-10 15:52:271490semak imbas

Konfigurasi penapis merentas domain SpringBoot membenarkan akses merentas domain

Permintaan merentas domain

Apabila sumber diminta daripada domain atau port yang berbeza daripada pelayan tempat sumber itu sendiri berada, sumber Permintaan HTTP merentas domain akan dimulakan.

Atas sebab keselamatan, penyemak imbas mengehadkan permintaan HTTP silang asal yang dimulakan dari dalam skrip. Contohnya, XMLHttpRequest dan API Ambil mengikut dasar asal yang sama. Ini bermakna aplikasi web yang menggunakan API ini hanya boleh meminta sumber HTTP daripada domain yang sama tempat aplikasi dimuatkan, melainkan pengepala CORS digunakan.

Latar belakang masalah

Jika bahagian hadapan menggesa masalah "Access-Control-Allow-Origin"

XMLHttpRequest tidak boleh memuatkan http://xxxxxxxxx/ No Pengepala 'Access- Control-Allow-Origin' terdapat pada sumber yang diminta 'null' tidak dibenarkan akses.

Penapis merentas domain

Kemudian anda perlu konfigurasi merentas domain dalam Penapis SpringBoot2 membenarkan akses merentas domain.

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.springframework.stereotype.Component;
@Component  
public class CorsFilter implements Filter {  
    @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", "*");  
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT, GET");  
        response.setHeader("Access-Control-Max-Age", "3600");  
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with");  
        chain.doFilter(req, res);  
    }  
    @Override
    public void init(FilterConfig filterConfig) {}  
    @Override
    public void destroy() {}  
}

Peningkatan fungsi merentas domain

Jika anda perlu memaparkan alamat merentas domain, anda juga boleh menambah kenyataan cetakan sumber akses untuk menyelesaikan masalah

String curOrigin = request.getHeader("Origin");
System.out.println("###跨域过滤器->当前访问来源->"+curOrigin+"###");

Jika anda perlukan kebenaran merentas domain, Anda boleh menentukan sumber

String curOrigin = request.getHeader("Origin");
System.out.println("###跨域过滤器->当前访问来源->"+curOrigin+"###");  
if(curOrigin.indexOf("127.0.0.1:8080")>-1){
    response.setHeader("Access-Control-Allow-Origin", "*");
}

Tetapan rentas domain (CORS) SpringBoot

1 Apakah itu merentas domain

Protokol, nama domain, dan port URL permintaan adalah berbeza Iaitu merentas domain. Masalah merentas domain berlaku disebabkan oleh sekatan dalam dasar asal yang sama penyemak imbas.

  • Asal yang sama: Protokol, nama domain dan port URL permintaan adalah sama, yang bermaksud asal yang sama (domain yang sama).

  • Dasar asal yang sama: Dasar asal yang sama (Dasar asal yang sama) ialah konvensyen Ia adalah teras dan fungsi keselamatan paling asas bagi penyemak imbas. Dasar asal yang sama menghalang kandungan daripada asal bukan asal (domain yang sama) daripada berinteraksi.

Sekatan dasar yang sama asal:

  • Tidak boleh membaca Cookie, LocalStorage dan IndexedDB bukan asal yang sama halaman web

  • Tidak dapat menghubungi DOM halaman web bukan asal

  • Tidak dapat menghantar permintaan AJAX ke alamat bukan asal

Dasar asal yang sama penyemak imbas akan menyekat permintaan merentas domain secara umumnya terdapat dua cara untuk menyekat:

  • Pelayar. mengehadkan permintaan merentas domain;

  • Permintaan merentas domain boleh dimulakan seperti biasa, tetapi hasil yang dikembalikan dipintas oleh penyemak imbas.

Secara amnya, penyemak imbas mengehadkan permintaan merentas domain dengan cara kedua, yang bermaksud permintaan itu telah sampai ke pelayan dan mungkin telah beroperasi pada data dalam pangkalan data, tetapi hasilnya dikembalikan Jika ia dipintas oleh penyemak imbas, maka kami tidak akan dapat mendapatkan hasil pemulangan Ini adalah permintaan yang gagal, tetapi ia mungkin memberi kesan kepada data dalam pangkalan data.

Untuk mengelakkan perkara ini daripada berlaku, spesifikasi memerlukan untuk kaedah permintaan HTTP ini yang mungkin mempunyai kesan sampingan pada data pelayan, penyemak imbas mesti terlebih dahulu menggunakan kaedah OPTIONS untuk memulakan permintaan pra-penerbangan untuk mengetahui sama ada pelayan membenarkan permintaan merentas domain: Jika dibenarkan, permintaan sebenar dengan data akan dihantar jika tidak, permintaan sebenar dengan data akan disekat.

2. Perkongsian sumber merentas domain (CORS)

Untuk menyelesaikan masalah kandungan bukan asal tidak dapat berinteraksi, penyelesaian arus perdana ialah: CORS (perkongsian sumber merentas domain) .

Perkongsian Sumber Rentas Asal (CORS), dirujuk sebagai CORS, menerobos had bahawa permintaan yang dibuat oleh penyemak imbas hanya boleh mendapatkan data daripada pelayan jika ia datang dari asal yang sama.

CORS bersetuju bahawa pelayan dan penyemak imbas merundingkan perkongsian sumber merentas domain melalui beberapa maklumat pengepala HTTP tambahan di atas protokol HTTP. Kedua-dua bahagian pelayan dan pelayar mesti mematuhi keperluan dalam spesifikasi.

CORS membahagikan permintaan merentas domain HTTP kepada dua kategori, permintaan ringkas dan permintaan bukan ringkas Permintaan berbeza merundingkan perkongsian sumber merentas domain mengikut dasar yang berbeza.

1. Permintaan ringkas

Syarat yang perlu dipenuhi untuk permintaan merentas domain yang mudah:

1. nilai Jenis Kandungan Mestilah nilai antara aplikasi/x-www-form-urlencoded, multipart/form-data, text/plain);

2 .

Pengepala HTTP hanya boleh mengandungi medan berikut:

  • Accept

  • Accept-Language

  • Content-Language

  • DPR

  • Downlink

  • Save-Data

  • Viewport-Width

  • Width

  • Content-Type

Permintaan merentas domain yang ringkas ialah permintaan merentas domain yang mudah jika dua mata di atas dipenuhi.

Untuk permintaan merentas domain yang mudah, kaedah pemprosesan adalah seperti berikut:

1 Apa yang perlu dilakukan oleh penyemak imbas ialah menambahkan Origin pada pengepala permintaan HTTP, isikan domain tempat skrip JavaScript terletak, dan tambahkannya pada Pelayan dalam sumber permintaan domain lain.

Origin: http://www.joker.com

Medan Asal digunakan untuk menunjukkan sumber mana permintaan ini datang (protokol + nama domain + port). Pelayan memutuskan sama ada untuk bersetuju menerima permintaan berdasarkan nilai ini.

2. Selepas pelayan menerima permintaan merentas domain yang mudah, ia menambah Access-Control-Allow-Origin pada pengepala respons mengikut konfigurasi kebenaran sumber.

如果Origin指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。 但这个响应头信息没有包含Access-Control-Allow-Origin字段,浏览器就知道该域名不在许可范围内。

如果Origin指定的域名在许可范围内,服务器返回的响应,会多出几个头信息字段:

Access-Control-Allow-Origin: http://www.joker.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: My-Token
  • Access-Control-Allow-Origin:该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*值,表示接受任意域名的请求。

  • Access-Control-Allow-Credentials: 该字段是可选的。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。

  • Access-Control-Expose-Headers:该字段是可选的。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。

3.浏览器收到响应后,通过获取响应头中的Access-Control-Allow-Origin字段,来判断如果当前域已经得到授权,则将结果返回给JavaScript。否则浏览器忽略此次响应。

2. 非简单请求

非简单跨域请求需满足的条件:

  • 除GET、HEAD和POST(Content-Type的值是:application/x-www-form-urlencoded、multipart/form-data、text/plain中的一个值)以外的其他HTTP方法

  • 如:PUT、DELETE、TRACE、PATCH、POST(Content-Type的值是:application/json)。

  • 请求中有自定义HTTP头部。

以上两点只要至少满足其中一点就是非简单跨域请求。

对于非简单跨域请求,处理方式如下:

1.浏览器在发送真实HTTP请求之前先发送一个OPTIONS的预检请求,检测服务器端是否支持真实请求进行跨域资源访问。

真实请求的信息在OPTIONS请求中通过请求头中的Access-Control-Request-Method和Access-Control-Request-Headers字段来描述。此外与简单跨域请求一样,请求头中也会有Origin字段。

Origin: http://www.joker.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Header1,Header2
  • Origin:必须字段,用于指定请求源。

  • Access-Control-Request-Method:必须字段,用于描述真实请求的方法(PUT、DELETE等)。

  • Access-Control-Request-Headers:指定真实请求会额外发送的请求头字段信息。

2.服务器端接到预检请求后,会检查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段,检验是否允许跨源请求。

如果不允许该跨域请求,会返回一个正常的HTTP回应,但这个响应头信息没有包含Access-Control-Allow-Origin字段,浏览器就知道该域名不在许可范围内。

如果允许该跨域请求,就会在响应头中放入Access-Control-Allow-Origin、Access-Control-Allow-Methods和Access-Control-Allow-Headers,分别表示允许跨域资源请求的域、请求方法和请求头。此外,服务器端还可以在响应头中放入Access-Control-Max-Age,允许浏览器在指定时间内,无需再发送预检请求进行协商,直接用本次协商结果即可。

Access-Control-Allow-Origin: http://www.joker.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: Header1,Header2,Header3
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 1728000
  • Access-Control-Allow-Methods:该字段必需,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次"预检"请求。

  • Access-Control-Allow-Headers:如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在"预检"中请求的字段。

  • Access-Control-Allow-Credentials: 该字段与简单请求时的含义相同。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。

  • Access-Control-Max-Age: 该字段可选,用来指定本次预检请求的有效期,单位为秒。上面结果中,有效期是20天(1728000秒),即允许缓存该条回应1728000秒(即20天),在此期间,不用发出另一条预检请求。

浏览器根据OPTIONS请求返回的结果来决定是否继续发送真实的请求进行跨域资源访问。这个过程对真实请求的调用者来说是透明的。

三、SpringBoot设置CORS

SpringBoot设置CORS的的本质都是通过设置响应头信息来告诉前端该请求是否支持跨域。

SpringBoot设置CORS的方式主要有以下三种。

1. 配置过滤器CorsFilter

@Configuration
public class CorsConfig {
    
    @Bean
    CorsFilter corsFilter() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("*"));
        configuration.setAllowedHeaders(Arrays.asList("*"));
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return new CorsFilter(source);
    }
}

2. 实现接口WebMvcConfigurer

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

3. 使用注解@CrossOrigin

@CrossOrigin注解可以用在类或者方法上

用在控制器类上,表示 该类的所有方法都允许跨域

@RestController
@CrossOrigin
public class TestController {
    
    @GetMapping("test")
    public String test() {
        return "success";
    }
}

用在控制器方法上,表示该方法都允许跨域

@RestController
public class TestController {
    @CrossOrigin
    @GetMapping("test")
    public String test() {
        return "success";
    }
}

@CrossOrigin注解源码

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CrossOrigin {
  
  /**
   * 这origins和value是一样的
   * 允许来源域名的列表,例如 www.baidu.com,匹配的域名是跨域预请求Response头中的Access-Control-Aloow_origin字段值。
   * 不设置确切值时默认支持所有域名跨域访问。
   */
  @AliasFor("origins")
  String[] value() default {};
  @AliasFor("value")
  String[] origins() default {};
  /**
   * 高版本下Spring2.4.4使用originPatterns而不是value和origins
   */
  String[] originPatterns() default {};
  /**
   * 跨域请求中允许的请求头中的字段类型, 该值对应跨域预请求Response头中的Access-Control-Allow-Headers字段值。
   * 不设置确切值默认支持所有的header字段(Cache-Controller、Content-Language、Content-Type、Expires、Last-Modified、Pragma)跨域访问
   */
  String[] allowedHeaders() default {};
  /**
   * 跨域请求请求头中允许携带的除Cache-Controller、Content-Language、Content-Type、Expires、Last-Modified、Pragma这六个基本字段之外的其他字段信息,
   * 对应的是跨域请求Response头中的Access-control-Expose-Headers字段值
   */
  String[] exposedHeaders() default {};
  /**
   * 跨域HTTP请求中支持的HTTP请求类型(GET、POST...),
   * 不指定确切值时默认与 Controller 方法中的 methods 字段保持一致。
   */
  RequestMethod[] methods() default {};
  /**
   * 浏览器是否将本域名下的cookie信息携带至跨域服务器中。默认携带至跨域服务器中,但要实现cookie共享还需要前端在AJAX请求中打开withCredentials属性。
   * 该值对应的是是跨域请求 Response 头中的 'Access-Control-Allow-Credentials' 字段值。
   */
  String allowCredentials() default "";
  /**
   * 该值的目的是减少浏览器预检请求/响应交互的数量。默认值1800s。设置了该值后,浏览器将在设置值的时间段内对该跨域请求不再发起预请求。
   * 该值对应的是是跨域请求Response头中的Access-Control-Max-Age字段值,表示预检请求响应的缓存持续的最大时间。
   */
  long maxAge() default -1;
}

Atas ialah kandungan terperinci Cara mengkonfigurasi penapis merentas domain dalam SpringBoot untuk membenarkan akses merentas domain. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam