CROS解决AJAX请求跨域

跨域请求

在当前页面请求与当前页面的协议、域名、端口号不同的url,即为跨域请求。

测试项目

新建一个Springboot项目crossorigin,pom.xml文件内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.1</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>crossorigin</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>crossorigin</name>
    <description>CrossOrigin project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

application.properties文件内容如下

server.port=8000
server.servlet.context-path=/crossorigin

spring.freemarker.template-loader-path=classpath:/templates/
spring.freemarker.suffix=.html

新建一个index.html文件放在classpath:/templates/index.html,内容如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.0.js"></script>
</head>
<body>
<div>Hello World</div>
<button onclick="test()">点击这里</button>

</body>
</html>
<script type="text/javascript">
    function test(){
        $.ajax({
            url: 'http://localhost:8001/crossorigin2/get',
            type: 'post',
            data: '',
            success: function(o) {
                alert(o);
            }
        })
    }
</script>

新建PageController,内容如下:

package com.example.crossorigin.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@RequestMapping("/")
@Controller
public class PageController {

    @RequestMapping("index")
    public String index(){
        return "index";
    }

    @ResponseBody
    @RequestMapping("get")
    public String get(){
        return "abc";
    }
}

启动项目

修改配置文件application.properties文件的server.port和server.servlet.context-path,启动两次。项目情况如下:

port context-path
8000 /crossorigin
8001 /crossorigin2

测试

在页面http://localhost:8001/crossorigin2/index上,点击按钮“点击查看”,AJAX请求http://localhost:8001/crossorigin2/get时,可正常访问。
CROS解决AJAX请求跨域
在页面http://localhost:8000/crossorigin/index上,点击按钮“点击查看”,AJAX请求http://localhost:8001/crossorigin2/get时,浏览器返回状态CORS error,产生了跨域请求。
CROS解决AJAX请求跨域

@CrossOrigin解决跨域

在get方法上加入@CrossOrigin后,重新启动项目,重复测试操作,可以看到两个页面都可以正常访问http://localhost:8001/crossorigin2/get。

	@CrossOrigin
    @ResponseBody
    @RequestMapping("get")
    public String get(){
        return "abc";
    }

@CrossOrigin可以加在某个具体方法上,支持单个方法跨域;也可以加在Controller上,支持Controller内所有方法跨域。
@CrossOrigin(“域名1”,“域名2”),支持设定的域名跨域。

携带Cookie跨域请求

AJAX请求时如果携带cookie,修改index.html的AJAX请求,重复测试操作。测试结果和未使用@CrossOrigin一致。

function test(){
        $.ajax({
            url: 'http://localhost:8001/crossorigin2/get',
            type: 'post',
            data: '',
            xhrFields: {
                withCredentials: true  //解决跨服务传递时不传递cookie的问题,允许携带证书
            },
            success: function(o) {
                alert(o);
            }
        })
    }

当AJAX请求携带cookie时,使用@CrossOrigin不能实现跨域,必须设置全局CorsFilter。

package com.example.crossorigin.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class CrossOriginConfig {

    @Bean
    public CorsFilter corsFilter(){
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOriginPattern("*");
        config.setAllowCredentials(true);
        config.addAllowedMethod("*");
        config.addAllowedHeader("*");
        UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
        configSource.registerCorsConfiguration("/**", config);
        return new CorsFilter(configSource);
    }
}

重复测试操作,可以看到两个页面都可以正常访问http://localhost:8001/crossorigin2/get。

总结

跨域请求携带cookie时,必须配置全局CorsFilter;跨域请求不携带cookie时,可以使用@CrossOrigin针对某些方法设置跨域。

上一篇:Vue - 基础(4)


下一篇:java笔记:Ajax-用户名是否已被注册