ホームページ  >  記事  >  Java  >  SpringBoot でクロスドメイン フィルターを構成してクロスドメイン アクセスを許可する方法

SpringBoot でクロスドメイン フィルターを構成してクロスドメイン アクセスを許可する方法

王林
王林転載
2023-05-10 15:52:271549ブラウズ

SpringBoot クロスドメイン フィルター構成により、クロスドメイン アクセスが可能になります

クロスドメイン リクエスト

リソース自体が存在するサーバーとは異なるドメインまたはポートからリソースがリクエストされた場合、リソース クロスドメイン HTTP リクエストが開始されます。

セキュリティ上の理由から、ブラウザはスクリプト内から開始されるクロスオリジン HTTP リクエストを制限しています。たとえば、XMLHttpRequest と Fetch API は同じオリジン ポリシーに従います。これは、CORS ヘッダーが使用されない限り、これらの API を使用する Web アプリケーションは、アプリケーションが読み込まれるのと同じドメインからのみ HTTP リソースを要求できることを意味します。

問題の背景

フロントエンドが「Access-Control-Allow-Origin」を要求する場合問題

XMLHttpRequest は http://xxxxxxxxxx/ を読み込めません。いいえ ' Access-Control-Allow-Origin' ヘッダーが要求されたリソースに存在します。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() {}  
}

クロスドメイン機能の改善

クロスドメイン アドレスを表示する必要がある場合は、トラブルシューティングのためにアクセス元の print ステートメントを追加することもできます。

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

Ifクロスドメイン権限が必要です。ソースは決定できます

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 のプロトコル、ドメイン名、ポートが同じ場合、同じオリジン (同じドメイン) を意味します。

  • 同一生成元ポリシー: 同一生成元ポリシー (同一生成元ポリシー) は規約であり、ブラウザの中核で最も基本的なセキュリティ機能です。同一オリジン ポリシーは、オリジナル以外のオリジン (同じドメイン) からのコンテンツが相互作用することを防ぎます。

同一オリジンポリシーの制限:

  • オリジナル以外の Web の Cookie、LocalStorage、IndexedDB を読み取ることができませんページ

  • オリジナル以外の Web ページの DOM にアクセスできません

  • #オリジナル以外のアドレスに AJAX リクエストを送信できません

ブラウザの同一オリジン ポリシーは、クロスドメイン リクエストを制限します。これを制限するには、通常 2 つの方法があります:

  • ブラウザクロスドメイン リクエストを制限します。

  • クロスドメイン リクエストは通常​​どおり開始できますが、返された結果はブラウザによってインターセプトされます。

一般に、ブラウザは 2 番目の方法でクロスドメイン リクエストを制限します。これは、リクエストがサーバーに到達し、データベース内のデータを操作した可能性がありますが、結果が返されたことを意味します。ブラウザによってインターセプトされると、戻り結果を取得できなくなります。これは失敗したリクエストですが、データベース内のデータに影響を与える可能性があります。

これを防ぐために、仕様では、サーバー データに副作用をもたらす可能性があるこの HTTP リクエスト メソッドについて、ブラウザはまず OPTIONS メソッドを使用してプリフライト リクエストを開始し、サーバーがクロスドメインリクエスト: 許可されている場合、データを含む実際のリクエストが送信されますが、許可されていない場合、データを含む実際のリクエストはブロックされます。

2. クロスドメイン リソース共有 (CORS)

オリジナル以外のコンテンツが操作できない問題を解決するための、現在の主流のソリューションは次のとおりです: CORS (クロスドメイン リソース共有) 。

CORS と呼ばれるクロスオリジン リソース共有 (Cross-origin Resource Sharing) は、ブラウザーによって発行されたリクエストが同じオリジンから来た場合にのみサーバーからデータを取得できるという制限を突破します。

CORS は、サーバーとブラウザーが HTTP プロトコル上の追加の HTTP ヘッダー情報を通じてクロスドメイン リソース共有をネゴシエートすることに同意します。サーバー側とブラウザーの両方が仕様の要件に準拠する必要があります。

CORS は、HTTP クロスドメイン リクエストを単純なリクエストと単純でないリクエストの 2 つのカテゴリに分割します。異なるリクエストは、異なるポリシーに従ってクロスドメイン リソース共有をネゴシエートします。

1. 単純なリクエスト
単純なクロスドメインリクエストで満たす必要がある条件:

1. リクエストメソッドは GET、HEAD、または POST (POST の場合、 Content-Type の値は、application/x-www-form-urlencoded、multipart/form-data、text/plain の間の値である必要があります);

2. リクエストにはカスタム HTTP リクエスト ヘッダーがありません。 。

HTTP ヘッダーには次のフィールドのみを含めることができます:

  • Accept

  • Accept -Language

  • ##Content-Language

  • ##DPR
  • ダウンリンク
  • データの保存
  • ビューポート-Width
  • Width
  • Content-Type
  • 上記の 2 点を満たす単純なクロスドメイン リクエストです。

単純なクロスドメインリクエストの場合、処理方法は次のとおりです: 1. ブラウザが行う必要があるのは、HTTP リクエストヘッダーに Origin を追加し、 JavaScript スクリプトが配置されているドメインを選択し、それを他のドメインのサーバー要求リソースに追加します。

Origin: http://www.joker.com

Origin フィールドは、このリクエストの送信元 (プロトコル ドメイン名ポート) を示すために使用されます。サーバーは、この値に基づいてリクエストに同意するかどうかを決定します。

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

以上がSpringBoot でクロスドメイン フィルターを構成してクロスドメイン アクセスを許可する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はyisu.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。