>  기사  >  Java  >  교차 도메인 액세스를 허용하도록 SpringBoot에서 교차 도메인 필터를 구성하는 방법

교차 도메인 액세스를 허용하도록 SpringBoot에서 교차 도메인 필터를 구성하는 방법

王林
王林앞으로
2023-05-10 15:52:271486검색

SpringBoot 교차 도메인 필터 구성은 교차 도메인 액세스를 허용합니다.

교차 도메인 요청

리소스가 리소스 자체가 있는 서버가 아닌 다른 도메인이나 포트에서 리소스를 요청하면 리소스는 교차 도메인 HTTP 요청을 시작합니다. .

보안상의 이유로 브라우저는 스크립트 내에서 시작된 교차 출처 HTTP 요청을 제한합니다. 예를 들어 XMLHttpRequest와 Fetch API는 동일한 원본 정책을 따릅니다. 이는 CORS 헤더가 사용되지 않는 한 이러한 API를 사용하는 웹 애플리케이션은 애플리케이션이 로드된 동일한 도메인에서만 HTTP 리소스를 요청할 수 있음을 의미합니다.

문제 배경

프런트 엔드에 "Access-Control-Allow-Origin" 문제가 표시되는 경우

XMLHttpRequest는 http://xxxxxxxxxx/를 로드할 수 없습니다. 'Access-Control-Allow-Origin' 헤더가 없습니다. 요청된 리소스이므로 원본 'null'은 액세스가 허용되지 않습니다.

교차 도메인 필터

그런 다음 교차 도메인 액세스를 허용하려면 SpringBoot2에서 교차 도메인 필터를 구성해야 합니다.

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

크로스 도메인 기능 개선

크로스 도메인 주소 표시가 필요한 경우 문제 해결을 위해 액세스 소스 인쇄문을 추가할 수도 있습니다

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

크로스 도메인 권한이 필요한 경우 소스를 확인할 수 있습니다

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

SpringBoot 크로스 도메인 설정( CORS)

1. 크로스 도메인이란 무엇인가요?

요청 URL의 프로토콜, 도메인 이름, 포트가 다른 경우 크로스 도메인입니다. 브라우저의 동일 출처 정책의 제한으로 인해 도메인 간 문제가 발생합니다.

  • 동일 출처: 요청 URL의 프로토콜, 도메인 이름, 포트가 동일합니다. 이는 동일한 출처(동일 도메인)임을 의미합니다.

  • 동일 출처 정책: 동일 출처 정책(Same Origin Policy)은 브라우저의 핵심이자 가장 기본적인 보안 기능입니다. 동일 출처 정책은 원본이 아닌 출처(동일 도메인)의 콘텐츠가 상호 작용하는 것을 방지합니다.

동일 출처 정책 제한:

  • 원본이 아닌 웹페이지의 쿠키, LocalStorage 및 IndexedDB를 읽을 수 없습니다.

  • 원본이 아닌 웹페이지의 DOM에 액세스할 수 없습니다

  • Un 읽을 수 있다 원본이 아닌 웹페이지 AJAX 요청을 보낼 주소

브라우저의 동일 출처 정책은 일반적으로 도메인 간 요청을 제한하는 두 가지 방법이 있습니다.

  • 브라우저는 도메인 간 요청을 제한합니다.

  • Cross-domain 요청이 가능합니다. 정상적으로 시작되었으나, 반환된 결과가 브라우저에 의해 가로채어졌습니다.

일반적으로 브라우저는 두 번째 방식으로 도메인 간 요청을 제한합니다. 즉, 요청이 서버에 도달하여 데이터베이스의 데이터에 대해 작동했을 수 있지만 반환된 결과가 브라우저에 의해 차단되었습니다. 반환 결과를 얻을 수 없습니다. 이는 실패한 요청이지만 데이터베이스의 데이터에 영향을 미칠 수 있습니다.

이런 일이 발생하는 것을 방지하기 위해 사양에서는 서버 데이터에 부작용이 있을 수 있는 이 HTTP 요청 방법에 대해 브라우저가 먼저 OPTIONS 방법을 사용하여 실행 전 요청을 시작하여 서버가 교차를 허용하는지 확인하도록 요구합니다. 도메인 요청: 허용되면 데이터가 포함된 실제 요청이 전송됩니다. 그렇지 않으면 데이터가 포함된 실제 요청이 전송되지 않습니다.

2. CORS(교차 도메인 리소스 공유)

원본이 아닌 콘텐츠가 상호 작용할 수 없는 문제를 해결하기 위한 현재 주류 솔루션은 CORS(교차 도메인 리소스 공유)입니다.

CORS(Cross-Origin Resource Sharing)는 브라우저의 요청이 동일한 소스에서 오는 경우에만 서버에서 데이터를 얻을 수 있다는 제한을 극복합니다.

CORS는 서버와 브라우저가 HTTP 프로토콜 위에 추가 HTTP 헤더 정보를 통해 도메인 간 리소스 공유를 협상한다는 데 동의합니다. 서버 측과 브라우저 모두 사양의 요구 사항을 준수해야 합니다.

CORS는 HTTP 교차 도메인 요청을 단순 요청과 비단순 요청의 두 가지 범주로 나눕니다. 다양한 요청은 다양한 정책에 따라 도메인 간 리소스 공유를 협상합니다.

1. 단순 요청

간단한 도메인 간 요청에 충족해야 하는 조건:

1. 요청 방법은 GET, HEAD 또는 POST입니다(POST의 경우 Content-Type 값은 application/x-여야 함). www-form-urlencoded, multipart/form-data, text/plain의 값)

2. 요청에 사용자 정의 HTTP 요청 헤더가 없습니다.

HTTP 헤더에는 다음 필드만 포함될 수 있습니다.

  • AcceptAccept

  • Accept-Language

  • Content-Language

  • DPR

  • Downlink

  • Save-Data

  • Viewport-Width

  • Width

  • Content-Type

Accept-Language

Content-Language

DPR

다운링크🎜🎜🎜🎜데이터 저장🎜🎜🎜🎜뷰포트 너비🎜🎜🎜🎜<code>Width🎜🎜🎜🎜Content-Type🎜🎜🎜🎜🎜위의 두 가지 사항이 충족되면 간단한 도메인 간 요청입니다. . 🎜🎜🎜간단한 도메인 간 요청의 경우 처리 방법은 다음과 같습니다. 🎜🎜1. 브라우저가 해야 할 일은 HTTP 요청 헤더에 Origin을 추가하고 JavaScript 스크립트가 있는 도메인을 입력한 후 리소스를 요청하는 것뿐입니다. 다른 도메인의 서버에서. 🎜
Origin: http://www.joker.com
🎜원본 필드는 이 요청이 어느 소스에서 왔는지 나타내는 데 사용됩니다(프로토콜 + 도메인 이름 + 포트). 서버는 이 값을 기반으로 요청에 대한 동의 여부를 결정합니다. 🎜🎜2. 서버는 간단한 도메인 간 요청을 받은 후 리소스 권한 구성에 따라 응답 헤더에 Access-Control-Allow-Origin을 추가합니다. 🎜

如果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 头中的 &#39;Access-Control-Allow-Credentials&#39; 字段值。
   */
  String allowCredentials() default "";
  /**
   * 该值的目的是减少浏览器预检请求/响应交互的数量。默认值1800s。设置了该值后,浏览器将在设置值的时间段内对该跨域请求不再发起预请求。
   * 该值对应的是是跨域请求Response头中的Access-Control-Max-Age字段值,表示预检请求响应的缓存持续的最大时间。
   */
  long maxAge() default -1;
}

위 내용은 교차 도메인 액세스를 허용하도록 SpringBoot에서 교차 도메인 필터를 구성하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제