Springboot整合web学习之CORS跨域相关学习整理
文章目录
一、什么是CORS跨域?
CORS 是一个W3C标准,全称是跨域资源共享(Cross-origin resource sharing)。
CORS 是一种基于 HTTP Header 的机制,该机制可以允许服务器除了它自己之外的其他域获取到非同源限制资源。服务器端配合浏览器实现 CORS 机制,可以突破浏览器对跨域资源访问的限制,实现跨域资源请求。
二、什么是跨域?
域=协议+域名+端口。
当一个请求的协议、域名、端口三者之前任意一个与当前界面不一致,就叫跨域。
三、为什么会出现跨域问题?
是因为浏览器的同源策略限制。同源策略是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。
同源策略作用就是会阻止一个域的javascript脚本和另外一个域的内容进行交互。
同源策略是一种安全限制。
四、非同源限制了哪些信息?
- 无法读取非同源网页的 Cookie、LocalStorage
- 无法接触非同源网页的DOM
- 无法向非同源地址发送AJAX请求
五、如何解决跨域?
- jsonp(平时工作不常用,不作了解)
- nginx反向代理(这里不做解释)
- CORS(跨域资源共享)
六、CORS提供header部分
Access-Control-Request-Method–指明请求方法
Access-Control-Request-Headers–指明请求携带字段
Access-Control-Allow-Origin–指明响应允许的域(CORS时必选,其他的都是可选),可以是一个或者多个
Access-Control-Allow-Credentials–如果为true,标识跨域请求携带cookie,此时Access-Control-Allow-Origin值不能设置为*,必须指明确。
Access-Control-Allow-Methods–指明响应方法
Access-Control-Allow-Headers–指明响应携带字段
Access-Control-Expose-Headers–指明响应哪些信息可以对外显示
Access-Control-Max-Age–指明响应时间
七、CORS跨域根本方法
解决方法就是在资源的头中加入Access-Control-Allow-Origin 指定你授权的域。
示例如下:
如www.aaa.com需要提取www.bbb.com的资源信息,就需要在www.bb.com服务端添加:
Access-Control-Allow-Origin: http://www.aaa.com
Access-Control-Allow-Credentials: true (可选,为true时会获取到cookie信息)
如www.bbb.com允许所有网站获取信息,则添加:
Access-Control-Allow-Origin: * ;
八、nginx如何添加?
add_header Access-Control-Allow-Origin *;
location /{
add_header Access-Control-Allow-Origin *;
}
重启服务即可。
九、java后台如何添加CORS?
- 自定义filter完成跨域(全局跨域,SpringMVC 3 及之前的版本)
- 手动设置响应头(局部跨域)
- 重写 WebMvcConfigurer(全局跨域,也可以匹配路径)
- 类或者方法名上使用@CrossOrigin注解(局部跨域)
- 返回新的CorsFilter
示例情况:本地起两个服务,
B服务:localhost:8081;
服务代码:
引入jquery.js,
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CORS跨域效果验证</title>
<script src="js/jquery/jquery.js"></script>
</head>
<body>
<div id="message"></div>
<input type="button" value="提交" onclick="submitData()"><br>
<input type="button" value="删除" onclick="deleteData()"><br>
<input type="button" value="局部跨域1" onclick="cors1()"><br>
<input type="button" value="局部跨域2" onclick="cors2()"><br>
<script>
function submitData() {
$.ajax({
url:'http://localhost:8080/api/hello',
type:'GET',
success:function (msg) {
$("#message").html(msg);
}
})
}
function deleteData() {
$.ajax({
url:'http://localhost:8080/api/demo',
type:'GET',
success:function (msg) {
$("#message").html(msg);
}
})
}
function cors1() {
$.ajax({
url:'http://localhost:8080/api/cors/1',
type:'GET',
success:function (msg) {
$("#message").html(msg);
}
})
}
function cors2() {
$.ajax({
url:'http://localhost:8080/api/cors/2',
type:'GET',
success:function (msg) {
$("#message").html(msg);
}
})
}
</script>
</body>
</html>
A服务:localhost:8080;
1、自定义filter完成跨域(全局跨域,SpringMVC 3 及之前的版本
/**
* FileName: MyCorsFilter
* Author: Administrator
* Date: 2021/2/22 16:54
* Description: 过滤器完成跨域设置
* History:
* <author> <time> <version> <desc>
* 作者姓名 修改时间 版本号 描述
*/
package com.yangxf.si.config.cors;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 〈SpringMVC3以及之前的版本通过如下方式完成CORS〉<br>
* 〈过滤器完成跨域设置〉
*
* @author Administrator
* @create 2021/2/22
* @since 1.0.0
*/
@Component
public class MyCorsFilter 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", "http://localhost:8081");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH");
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type,Token,Accept, Connection, User-Agent, Cookie");
response.setHeader("Access-Control-Max-Age", "3600");
System.out.println("设置跨域请求");
chain.doFilter(req, response);
}
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void destroy() {
}
}
2、手动设置响应头(局部跨域)
@RequestMapping("/")
public String demo(HttpServletResponse response) {
response.setHeader("Access-Control-Allow-Origin", "http://localhost:8081");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH");
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type,Token,Accept, Connection, User-Agent, Cookie");
response.setHeader("Access-Control-Max-Age", "3600");
System.out.println("设置跨域请求");
return "demo";
}
3、重写 WebMvcConfigurer
注:该方法使用的情况下,项目中不能有自定义拦截器,否则跨域配置将失效。
/**
* FileName: CorsConfig
* Author: Administrator
* Date: 2021/2/23 9:07
* Description: 重写 WebMvcConfigurer(全局跨域)
* History:
* <author> <time> <version> <desc>
* 作者姓名 修改时间 版本号 描述
*/
package com.yangxf.si.config.cors;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 〈一句话功能简述〉<br>
* 〈重写 WebMvcConfigurer(全局跨域)〉
*
* @author Administrator
* @create 2021/2/23
* @since 1.0.0
*/
@Configuration
public class CorsConfig implements WebMvcConfigurer {
/**
* 但是使用此方法配置之后再使用自定义拦截器时跨域相关配置就会失效。
*
* 原因是请求经过的先后顺序问题,当请求到来时会先进入拦截器中,而不是进入 Mapping 映射中,所以返回的头信息中并没有配置的跨域信息。浏览器就会报跨域异常。
* 不建议用
* @param registry
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/hello")
//是否发送Cookie
.allowCredentials(true)
.allowedOrigins("http://localhost:8081")
.allowedMethods(new String[]{"GET", "POST", "PUT", "DELETE"})
.allowedHeaders("*")
.maxAge(3600);
}
}
4、类或者方法名上使用@CrossOrigin注解(局部跨域,与3配置的路径无冲突)
当在类以及方法名上同时配置不同的域时,两个都可以跨域,不存在优先级情况,已验证。
/**
* FileName: CrossOriginController
* Author: Administrator
* Date: 2021/2/23 10:30
* Description: 局部跨域测试控制器
* History:
* <author> <time> <version> <desc>
* 作者姓名 修改时间 版本号 描述
*/
package com.yangxf.si.modules.business.controller.cors;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 〈一句话功能简述〉<br>
* 〈局部跨域测试控制器〉
*
* @author Adminitrator
* @create 2021/2/23
* @since 1.0.0
*/
@CrossOrigin("http://localhost:8081")
@RestController
public class CrossOriginController {
@GetMapping(value="/cors/1")
public String cors1(){
return "跨域测试1";
}
@CrossOrigin(value="http://localhost:8082")
@GetMapping(value="/cors/2")
public String cors2(){
return "跨域测试2";
}
}
5、返回新的CorsFilter
/**
* FileName: NewCorsFilter
* Author: Administrator
* Date: 2021/2/23 10:56
* Description: 返回新的 CorsFilter
* History:
* <author> <time> <version> <desc>
* 作者姓名 修改时间 版本号 描述
*/
package com.yangxf.si.config.cors;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
/**
* 〈一句话功能简述〉<br>
* 〈返回新的 CorsFilter〉
*
* @author Administrator
* @create 2021/2/23
* @since 1.0.0
*/
@Configuration
public class NewCorsFilter {
@Bean
public CorsFilter corsFilter() {
// 添加 CORS配置信息
CorsConfiguration config = new CorsConfiguration();
//放行域
config.addAllowedOrigin("*");
//是否发送 Cookie
config.setAllowCredentials(true);
//放行请求方式
config.addAllowedMethod("*");
//放行请求头部信息
config.addAllowedHeader("*");
//暴露头部信息--不能默认*
config.addExposedHeader(HttpHeaders.ACCEPT);
//映射路径
UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
corsConfigurationSource.registerCorsConfiguration("/**", config);
//返回新的CorsFilter
return new CorsFilter(corsConfigurationSource);
}
}