5.跨域处理

简介: 本文介绍跨域问题及其解决方案。首先解析跨域的定义及产生原因,接着通过实例演示正常请求与跨域请求的区别,重点讲解CORS(跨域资源共享)机制,并提供三种解决方案:@CrossOrigin注解、全局配置WebMvcConfigurer和自定义Filter拦截器,最后附上完整示例代码地址,便于开发者快速实现跨域处理。

5.跨域处理

一、跨域背景
1.1 何为跨域?
Url的一般格式:
协议 + 域名(子域名 + 主域名) + 端口号 + 资源地址
示例:
https://www.dustyblog.cn:8080/say/Hello 是由
https + www + dustyblog.cn + 8080 + say/Hello
组成。
只要协议,子域名,主域名,端口号这四项组成部分中有一项不同,就可以认为是不同的域,不同的域之间互相访问资源,就被称之为跨域。
1.2 一次正常的请求
Controller层代码:
启动项目,测试请求
浏览器打开localhost:8080/demo/sayHello
可以打印出“hello world”
1.3 跨域测试
以Chrome为例:
打开任意网站,如:https://blog.csdn.net
按F12,打开【开发者工具】,在里面的【Console】可以直接输入js代码测试;
输入完后直接按回车键就可以返回结果:
该结果表明:该请求在https://blog.csdn.net域名下请求失败!
二、解决方案 - Cors跨域
2.1 Cors是什么
CORS全称为Cross Origin Resource Sharing(跨域资源共享), 每一个页面需要返回一个名为Access-Control-Allow-Origin的http头来允许外域的站点访问,你可以仅仅暴露有限的资源和有限的外域站点访问。
我们可以理解为:如果一个请求需要允许跨域访问,则需要在http头中设置Access-Control-Allow-Origin来决定需要允许哪些站点来访问。如假设需要允许https://www.dustyblog.c这个站点的请求跨域,则可以设置:
Access-Control-Allow-Origin:https://www.dustyblog.cn。
2.2 方案一:使用@CrossOrigin注解
2.2.1 在Controller上使用@CrossOrigin注解
该类下的所有接口都可以通过跨域访问
这里指定当前的CorsTest2Controller中所有的方法可以处理https://csdn.net域上的请求,这里可以测试一下:
https://blog.csdn.net页面打开调试窗口,输入(注意:这里请求地址是/demo2,请区别于1.2 案例中的/demo)
返回结果:
说明跨域成功!
换个域名测试一下看跨域是否还有效,在https://www.baidu.com按照上述方法测试一下,返回结果:
说明跨域失败!证明该方案成功指定了部分域名能跨域!
2.3 方案二:CORS全局配置-实现WebMvcConfigurer
新建跨域配置类:CorsConfig.java:

Java

运行代码复制代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

/**

* 跨域配置

*/

@Configuration

public class CorsConfig implements WebMvcConfigurer {

   @Bean

public WebMvcConfigurer corsConfigurer()

{

return new WebMvcConfigurer() {

           @Override

public void addCorsMappings(CorsRegistry registry) {

registry.addMapping("/**").

allowedOrigins("https://www.dustyblog.cn"). //允许跨域的域名,可以用*表示允许任何域名使用

allowedMethods("*"). //允许任何方法(post、get等)

               allowedHeaders("*"). //允许任何请求头

allowCredentials(true). //带上cookie信息

exposedHeaders(HttpHeaders.SET_COOKIE).maxAge(3600L); //maxAge(3600)表明在3600秒内,不需要再发送预检验请求,可以缓存该结果

}

};

}

}

测试,在允许访问的域名https://www.dustyblog.cn/控制台输入(注意,这里请求的是http://127.0.0.1:8080/demo3)

JavaScript

运行代码复制代码

1

2

3

4

5

6

7

8

9

var token= "LtSFVqKxvpS1nPARxS2lpUs2Q2IpGstidMrS8zMhNV3rT7RKnhLN6d2FFirkVEzVIeexgEHgI/PtnynGqjZlyGkJa4+zYIXxtDMoK/N+AB6wtsskYXereH3AR8kWErwIRvx+UOFveH3dgmdw1347SYjbL/ilGKX5xkoZCbfb1f0=,LZkg22zbNsUoHAgAUapeBn541X5OHUK7rLVNHsHWDM/BA4DCIP1f/3Bnu4GAElQU6cds/0fg9Li5cSPHe8pyhr1Ii/TNcUYxqHMf9bHyD6ugwOFTfvlmtp6RDopVrpG24RSjJbWy2kUOOjjk5uv6FUTmbrSTVoBEzAXYKZMM2m4=,R4QeD2psvrTr8tkBTjnnfUBw+YR4di+GToGjWYeR7qZk9hldUVLlZUsEEPWjtBpz+UURVmplIn5WM9Ge29ft5aS4oKDdPlIH8kWNIs9Y3r9TgH3MnSUTGrgayaNniY9Ji5wNZiZ9cE2CFzlxoyuZxOcSVfOxUw70ty0ukLVM/78=";

var xhr = new XMLHttpRequest();

xhr.open('GET', 'http://127.0.0.1:8080/demo3/sayHello');

xhr.setRequestHeader("x-access-token",token);

xhr.send(null);

xhr.onload = function(e) {

var xhr = e.target;

console.log(xhr.responseText);

}

输出结果

JavaScript

运行代码复制代码

1

2

3

4

5

ƒ (e) {

var xhr = e.target;

console.log(xhr.responseText);

}

VM433:8 hello world --- 3

说明跨域成功,换个网址如https://www.baidu.com测试依旧出现需要跨域的错误提示,证明该配置正确,该方案测试通过。
2.3 拦截器实现
通过实现Fiter接口在请求中添加一些Header来解决跨域的问题

Java

运行代码复制代码

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

@Component

public class CorsFilter implements Filter {

   @Override

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

throws IOException, ServletException {

HttpServletResponse res = (HttpServletResponse) response;

res.addHeader("Access-Control-Allow-Credentials", "true");

res.addHeader("Access-Control-Allow-Origin", "*");

res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");

res.addHeader("Access-Control-Allow-Headers", "Content-Type,X-CAF-Authorization-Token,sessionToken,X-TOKEN");

if (((HttpServletRequest) request).getMethod().equals("OPTIONS")) {

response.getWriter().println("ok");

return;

}

chain.doFilter(request, response);

}

   @Override

public void destroy() {

}

   @Override

public void init(FilterConfig filterConfig) throws ServletException {

}

}

三、更多
3.1 源码地址
Github 示例代码

相关文章
|
前端开发 Java 应用服务中间件
解决跨域问题的8种方法,含网关、Nginx和SpringBoot~
解决跨域问题的8种方法,含网关、Nginx和SpringBoot~
3536 0
解决跨域问题的8种方法,含网关、Nginx和SpringBoot~
|
3月前
|
运维 安全 Linux
Linux网络telnet命令详解(小白也能轻松掌握的远程连接与端口测试指南)
本文介绍Linux中telnet命令的使用方法,重点讲解如何通过telnet测试网络端口连通性。尽管telnet因明文传输已不推荐用于远程登录,但在排查服务状态、验证端口开放等方面仍具实用价值。教程涵盖安装、基本语法、实战示例及安全建议,适合初学者快速掌握这一轻量级网络调试工具。
|
9月前
|
SQL 关系型数据库 MySQL
MySQL探索:详解WITH AS语法的使用。
总的来说,MySQL的 `WITH AS`语法就如同我们路途中的导航设备,能帮助我们更好地组织和简化查询, 增强了我们和数据沟通的能力,使得复杂问题变得可控且更有趣。不论是在森林深处,还是在数据的海洋中,都能找到自己想要的路途和方向。
1517 12
|
6月前
|
数据采集 监控 数据管理
数据管理最容易混淆的3个概念:元数据、数据元、元模型
本文深入解析数据领域三大核心概念:“元数据”“数据元”“元模型”,从定义、用途到实际应用,清晰区分三者区别。元数据是“数据的说明书”,描述数据来源与使用方式;数据元是“最小数据单元”的标准,确保数据统一与规范;元模型是“模型的设计规则”,指导模型合理构建。三者相辅相成,是数据治理不可或缺的基础。掌握它们,助你提升数据管理效率,避免踩坑。
|
12月前
|
存储 IDE Java
java设置栈内存大小
在Java应用中合理设置栈内存大小是确保程序稳定性和性能的重要措施。通过JVM参数 `-Xss`,可以灵活调整栈内存大小,以适应不同的应用场景。本文介绍了设置栈内存大小的方法、应用场景和注意事项,希望能帮助开发者更好地管理Java应用的内存资源。
674 4
Linux系统如何查看版本信息,内核、发行版、cpu、所有版本
Linux系统如何查看版本信息,内核、发行版、cpu、所有版本
754 10
|
XML JSON Java
通过 Feign 进行文件上传
通过 Feign 进行文件上传
1049 7
|
存储 设计模式 前端开发
什么是SpringMVC?简单好理解!什么是应用分层?SpringMVC与应用分层的关系? 什么是三层架构?SpringMVC与三层架构的关系?
文章解释了SpringMVC的概念和各部分功能,探讨了应用分层的原因和具体实施的三层架构,以及SpringMVC与三层架构之间的关系和联系。
827 1
什么是SpringMVC?简单好理解!什么是应用分层?SpringMVC与应用分层的关系? 什么是三层架构?SpringMVC与三层架构的关系?
|
监控 Java 开发者
什么是 Spring Boot?
什么是 Spring Boot?
3144 6
|
XML Java 数据格式
Spring IOC—基于XML配置和管理Bean 万字详解(通俗易懂)
Spring 第二节 IOC—基于XML配置和管理Bean 万字详解!。
1284 5