跨域请求
在当前页面请求与当前页面的协议、域名、端口号不同的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时,可正常访问。
在页面http://localhost:8000/crossorigin/index上,点击按钮“点击查看”,AJAX请求http://localhost:8001/crossorigin2/get时,浏览器返回状态CORS error,产生了跨域请求。
@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针对某些方法设置跨域。