5.跨域处理

简介: 本文介绍跨域问题及其解决方案。当协议、域名、端口任一不同时即产生跨域,浏览器因同源策略限制资源访问。通过CORS(跨域资源共享)可在服务端设置Access-Control-Allow-Origin等响应头,实现安全跨域。常用方案包括@CrossOrigin注解、WebMvcConfigurer全局配置及Filter拦截器方式,文中结合Spring Boot代码示例详细演示了各类实现方法。

一、跨域背景

1.1 何为跨域?

Url的一般格式:

协议 + 域名(子域名 + 主域名) + 端口号 + 资源地址

示例:

https://www.dustyblog.cn:8080/say/Hello 是由

https + www + dustyblog.cn + 8080 + say/Hello

组成。

只要协议,子域名,主域名,端口号这四项组成部分中有一项不同,就可以认为是不同的域,不同的域之间互相访问资源,就被称之为跨域。

1.2 一次正常的请求

  • Controller层代码:
@RequestMapping("/demo")
@RestController
public class CorsTestController {
    @GetMapping("/sayHello")
    public String sayHello() {
        return "hello world !";
    }
}
  • 启动项目,测试请求

浏览器打开localhost:8080/demo/sayHello

可以打印出“hello world”

1.3 跨域测试

以Chrome为例:

  • 打开任意网站,如:https://blog.csdn.net
  • 按F12,打开【开发者工具】,在里面的【Console】可以直接输入js代码测试;
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/demo/sayHello');
xhr.setRequestHeader("x-access-token",token);
xhr.send(null);
xhr.onload = function(e) {
    var xhr = e.target;
    console.log(xhr.responseText);
}
  • 输入完后直接按回车键就可以返回结果:
Access to XMLHttpRequest at 'http://127.0.0.1:8080/demo/sayHello' 
from origin 'https://blog.csdn.net' has been blocked by CORS policy: 
No 'Access-Control-Allow-Origin' header is present on the requested resource.

该结果表明:该请求在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注解

该类下的所有接口都可以通过跨域访问

@RequestMapping("/demo2")
@RestController
//@CrossOrigin //所有域名均可访问该类下所有接口
@CrossOrigin("https://blog.csdn.net") // 只有指定域名可以访问该类下所有接口
public class CorsTest2Controller {
    @GetMapping("/sayHello")
    public String sayHello() {
        return "hello world --- 2";
    }
}

这里指定当前的CorsTest2Controller中所有的方法可以处理https://csdn.net域上的请求,这里可以测试一下:

  • https://blog.csdn.net页面打开调试窗口,输入(注意:这里请求地址是/demo2,请区别于1.2 案例中的/demo)
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/demo2/sayHello');
xhr.setRequestHeader("x-access-token",token);
xhr.send(null);
xhr.onload = function(e) {
    var xhr = e.target;
    console.log(xhr.responseText);
}

返回结果:

ƒ (e) {
    var xhr = e.target;
    console.log(xhr.responseText);
}
VM156:8 hello world --- 2

说明跨域成功!

  • 换个域名测试一下看跨域是否还有效,在https://www.baidu.com按照上述方法测试一下,返回结果:
OPTIONS http://127.0.0.1:8080/demo2/sayHello 403
(anonymous)
Access to XMLHttpRequest at 'http://127.0.0.1:8080/demo2/sayHello' 
from origin 'http://www.cnblogs.com' has been blocked by CORS policy: 
Response to preflight request doesn't pass access control check: 
No 'Access-Control-Allow-Origin' header is present on the requested resource.

说明跨域失败!证明该方案成功指定了部分域名能跨域!

2.3 方案二:CORS全局配置-实现WebMvcConfigurer

  • 新建跨域配置类:CorsConfig.java:
/**
 * 跨域配置
 */
@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秒内,不需要再发送预检验请求,可以缓存该结果
            }
        };
    }
}
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);
}

输出结果

ƒ (e) {
    var xhr = e.target;
    console.log(xhr.responseText);
}
VM433:8 hello world --- 3

说明跨域成功,换个网址如https://www.baidu.com测试依旧出现需要跨域的错误提示,证明该配置正确,该方案测试通过。

2.3 拦截器实现

通过实现Fiter接口在请求中添加一些Header来解决跨域的问题

@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 示例代码


相关文章
|
4月前
|
Kubernetes 容器 Perl
kubernetes-1.34.2 二级制快速安装部署
kubenetes-1.34.2 二进制安装包,其他版本同样可以使用,包含etcd,kube-apiserver,kube-controller-manager,kube-scheduler,kubelet,containerd,coredns,metric-server的证书、配置文件,启动脚本。其中还包括证书的生成脚本、kubeconfig的生成脚本,同时包含了二进制可执行文件,本安装包已经包含了二进制文件,制作好的证书和安装包,可以直接拷贝到安装目录进行安装,也可以重新执行:make_install_package.sh 重新生成。该项目是为了配合k8s-1.34.2二进制的安装。
1041 2
|
SQL 关系型数据库 MySQL
Docker 部署离线版 Nginx 镜像容器,Tomcat 镜像容器,Mariadb 镜像容器
Docker 部署离线版 Nginx 镜像容器,Tomcat 镜像容器,Mariadb 镜像容器
3581 0
Docker 部署离线版 Nginx 镜像容器,Tomcat 镜像容器,Mariadb 镜像容器
|
17天前
|
机器学习/深度学习 人工智能 编解码
抽烟行为检测数据集(约3000张图片已标注)| YOLO训练数据集 AI视觉检测
本数据集含约3000张多场景抽烟行为图像,YOLO格式标注(单类“smoke”),覆盖室内外、不同光照与人群姿态,支持YOLOv5/v8直接训练。适用于智慧安防、禁烟监管及AI行为识别研究,助力实时检测与自动告警。
抽烟行为检测数据集(约3000张图片已标注)| YOLO训练数据集 AI视觉检测
|
4月前
|
运维 Kubernetes NoSQL
【k8s-1.34.2安装部署】九.k8s管理平台xkube安装部署
xkube是一款永久免费、无功能限制的云原生Kubernetes多集群管理工具,支持PC端与APP端,提供集群管理、运维监控、CI/CD发布等功能,助力企业实现跨集群统一管理与自动化运维。
458 3
【k8s-1.34.2安装部署】九.k8s管理平台xkube安装部署
|
4月前
|
Kubernetes 负载均衡 网络协议
【k8s-1.34.2安装部署】一.系统初始化及k8s集群规划
k8s1.34.2的安装总体没什么变化,主要在于结合最新版本的containerd、gateway Api、istio、cilium进行安装,新版本的一些软件和旧的存在一些区别。本章节主要是通过搭建最新版的k8s集群,并搭建gateway Api来进行一些[xkube](https://gitee.com/eeenet/xkube)开发环境的调试和部署,现将整个k8s1.34.2的安装过程进行记录。
1053 22
|
5月前
|
供应链 安全 数据可视化
2025年MES系统厂商排名揭晓:深度解析头部企业如何破解生产数智化难题
树根科技MES系统以“软件+咨询”模式深度融合精益生产与数智化技术,依托根云平台实现设备互联、数据集成与流程固化。其微服务架构支持灵活配置,覆盖计划、生产、质量、仓储等全场景,助力企业提升交付率、缩短周期、实现全流程追溯,为中大型离散制造企业提供高适配、可扩展的智能工厂解决方案。
268 2
|
16天前
|
人工智能 弹性计算 安全
OpenClaw从0到1精通指南:7个必装Skill/5000+精选库、全平台部署、阿里云千问/Coding Plan API配置与问题排查
OpenClaw的核心价值在于Skill生态与灵活部署能力,7个必装Skill覆盖安全、检索、进化、主动、更新等基础能力,5000+精选库满足垂直场景需求。2026年阿里云与本地全平台部署流程成熟,搭配阿里云千问API与免费Coding Plan API,可快速搭建兼顾隐私、效率、成本的AI代理环境。无论个人效率提升还是团队协作,本文提供的命令、配置、排查方案均可直接落地使用,真正实现AI代理自主化、稳定化、高效化。
1048 1
|
4月前
|
运维 网络协议 安全
Netcat:网络瑞士军刀(Linux小白也能轻松上手的网络调试利器)
来源:https://www.vps5.cn/ 教程Netcat(nc)是Linux下强大的网络工具,被誉为“网络瑞士军刀”,支持端口扫描、文件传输、远程通信等。本文详解其安装与基础用法,如端口检测、搭建聊天服务器和文件收发,并提醒明文传输风险,适合初学者快速入门网络调试。
|
4月前
|
负载均衡 应用服务中间件 Nacos
Nacos配置中心
本文详细介绍Nacos作为配置中心的实现原理与实战应用,涵盖配置管理、热更新、共享配置及优先级规则,并演示集群搭建与高可用部署,提升微服务架构下配置的动态管理能力。
|
4月前
|
SpringCloudAlibaba Java Nacos
SpringCloud概述
Spring Cloud是微服务的统一解决方案,具备约定大于配置、组件丰富、开箱即用等特点。通过整合Netflix与Alibaba生态,形成完整技术栈,其中Spring Cloud Alibaba因Nacos、Sentinel等优秀组件成为主流选择。