ホームページ  >  記事  >  Java  >  Springboot が CORS クロスドメインの問題を解決する方法は何ですか?

Springboot が CORS クロスドメインの問題を解決する方法は何ですか?

王林
王林転載
2023-05-13 16:55:061457ブラウズ

1. WebMvcConfigurer インターフェイスを実装します

@Configuration
public class WebConfig implements WebMvcConfigurer {
    /**
     * 添加跨域支持
     */
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        // 允许跨域访问的路径  '/**'表示应用的所有方法
        registry.addMapping("/**")
            // 允许跨域访问的来源 '*'表示所有域名来源
            .allowedOriginPatterns("*")
            // .allowedOrigins("*") // 允许跨域访问的来源 SpringBoot2.4.0之前的版本
            // 允许跨域请求的方法  '*'表示所有
            .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE", "OPTIONS")
            // 是否允许发送cookie true-允许 false-不允许 默认false。对服务器有特殊要求的请求,比如请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json,这个值只能设为true
            .allowCredentials(true)
            // 预检间隔时间1小时,单位为秒。指定本次预检请求的有效期,在有效期间,不用发出另一条预检请求。
            // 浏览器发出CORS简单请求,只需要在头信息之中增加一个Origin字段
            // 浏览器发出CORS非简单请求,会在正式通信之前,增加一次OPTIONS查询请求,称为"预检"请求(preflight)。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。
            .maxAge(3600)
            // 允许跨域请求可携带的header,'*'表所有header头。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定
            .allowedHeaders("*");
    }
}

2. フィルター filter メソッドを実装します

@WebFilter
@Configuration
public class CorsFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        chain.doFilter(req, res);
    }
}

3. アノテーション @CrossOrigin

@CrossOrigin(originPatterns = "*", allowCredentials = "true")

@CrossOrigin は、メソッドだけでなく、クラスでも構成可能です。

4. 実践的な戦闘

2 つの通常の SpringBoot プロジェクト A と B を作成します。A はポート 8081 で構成され、ポート B はポート 8082 で構成されます。

A の resource/static ディレクトリに HTML ファイルindex.html を作成します。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
 
<!-- jquery库可百度jquery cdn -->
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<script>
    function btnClick() {
        $.get(&#39;http://localhost:8082/hello/hello&#39;, function (msg) {
            $("#app").html(msg);
        });
    }
 
    function btnClick2() {
        $.post(&#39;http://localhost:8082/hello/hello&#39;, function (msg) {
            $("#app").html(msg);
        });
    }
</script>
 
<body>
 
<div id="app"></div>
<input type="button" onclick="btnClick()" value="get_button">
<input type="button" onclick="btnClick2()" value="post_button">
 
</body>
</html>

B は 2 つの Web インターフェイスを提供します。

@RestController
@RequestMapping("/hello")
public class HelloController {
    // @CrossOrigin(originPatterns = "*", allowCredentials = "true")
    @GetMapping("/hello")
    public String hello() {
        System.out.println("get hello");
        return "get hello";
    }
 
    // @CrossOrigin(originPatterns = "*", allowCredentials = "true")
    @PostMapping("/hello")
    public String hello2() {
        System.out.println("post hello");
        return "post hello";
    }
}

A サービスと B サービスをそれぞれ開始します。ブラウザはA の Index.html を選択してボタンをクリックすると、ブラウザ コンソールに次のエラーが報告されます: http://localhost:8081/index.html

Access to XMLHttpRequest at ' http:オリジン 'http://localhost:8081' からの //localhost:8082/hello/hello' は CORS ポリシーによってブロックされました: 要求されたリソースに 'Access-Control-Allow-Origin' ヘッダーが存在しません。

Springboot が CORS クロスドメインの問題を解決する方法は何ですか?

プロジェクト B に方法 1 を使用し、クロスドメイン サポートを追加し、再起動してボタンをもう一度クリックすると、通常どおりアクセスでき、応答ヘッダーにクロスドメイン サポートが追加されていることを確認します。情報:

Springboot が CORS クロスドメインの問題を解決する方法は何ですか?

##5. クロスドメイン Cookie

Chrome 51 以降、CSRF 攻撃とユーザー追跡を防ぐために、新しい属性 SameSite がブラウザの Cookie に追加されました。 。

SameSite 可能な値: Strict、Lax、None。

Strict は最も厳格で、サードパーティ Cookie を完全に禁止します。クロスサイトの場合、いかなる状況でも Cookie は送信されません。つまり、現在の Web ページの URL がリクエストのターゲットと一致する場合にのみ、Cookie が取得されます。

緩いルールはわずかに緩和されており、ターゲット URL に移動する Get リクエストを除いて、ほとんどの場合、サードパーティ Cookie は送信されません。ターゲット URL に移動する GET リクエストには、リンク、プリロード リクエスト、GET フォームの 3 つのケースのみが含まれます。

Web サイトは、SameSite 属性を明示的にオフにして、None に設定することを選択できます。ただし、前提条件として、Secure 属性が同時に設定されている必要があります (Cookie は HTTPS プロトコル経由でのみ送信できます)。そうでないと無効になります。

SpringBoot 2.6 以降

利用可能な構成はオンラインで見つけることができます (ただし、個人テストは無効です!):

server.servlet.session.cookie.same-site=none
server.servlet.session.cookie.secure=true

SpringBoot 2.6 以下のバージョン

Tomcat をサーバーとして使用する場合は、次の設定を通じてセッション Cookie の SameSite 属性を設定できます (個人テストは機能しません)。

server.servlet.session.cookie.secure=true
@Configuration
public class TomcatCookieConfig {
    @Bean
    public TomcatContextCustomizer sameSiteCookiesConfig() {
        return context -> {
            final Rfc6265CookieProcessor cookieProcessor = new Rfc6265CookieProcessor();
            // SameSite
            cookieProcessor.setSameSiteCookies(SameSiteCookies.NONE.getValue());
            context.setCookieProcessor(cookieProcessor);
        };
    }
}

Spring-Session を使用している場合は、次の構成を使用して Cookie の SameSite 属性を設定できます。

        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-core</artifactId>
        </dependency>
@Configuration
public class SpringSessionConfiguration {
    @Bean
    public CookieSerializer cookieSerializer() {
        DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();
        // Strict-严格模式 Lax-松懈模式 None-无
        cookieSerializer.setSameSite("None");
        cookieSerializer.setUseSecureCookie(true);
        return cookieSerializer;
    }
}

私自身の解決策

@Configuration
public class CookieConfig {
    private static String domain;
 
    @Value("${domain}")
    public void setDomain(String domain) {
        CookieConfig.domain = domain;
    }
 
    public static HttpCookie generateHttpCookie(String name, String value) {
        return ResponseCookie.from(name, value)
            .domain(domain)
            // cookie跨域设置
            .sameSite("None")
            // 在https下传输,配合sameSite=None使用
            .secure(true)
            .path("/")
            // 有效期24小时
            .maxAge(60 * 60 * 24)
            .build();
    }
}
    @GetMapping("/hello")
    public String hello(HttpServletResponse response) {
        HttpCookie cookie2 = CookieConfig.generateHttpCookie("age", "18");
        response.addHeader(HttpHeaders.SET_COOKIE, cookie2.toString());
        HttpCookie cookie3 = CookieConfig.generateHttpCookie("id", "77");
        response.addHeader(HttpHeaders.SET_COOKIE, cookie3.toString());
        System.out.println("get hello");
        return "get hello";
    }

以上がSpringboot が CORS クロスドメインの問題を解決する方法は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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