解决跨域(CORS)问题

前后端分离项目,如何解决跨域问题

跨域资源共享(CORS)是前后端分离项目很常见的问题,本文主要介绍当SpringBoot应用整合SpringSecurity以后如何解决该问题。

什么是跨域问题

CORS全称Cross-Origin Resource Sharing,意为跨域资源共享。当一个资源去访问另一个不同域名或者同域名不同端口的资源时,就会发出跨域请求。如果此时另一个资源不允许其进行跨域资源访问,那么访问的那个资源就会遇到跨域问题。

跨域问题演示及解决

我们使用mall项目的源代码来演示一下跨域问题。此时前端代码运行在8090端口上,后端代码运行在8080端口上,由于其域名都是localhost,但是前端和后端运行端口不一致,此时前端访问后端接口时,就会产生跨域问题。

点击前端登录按钮

此时发现调用登录接口时出现跨域问题。

覆盖默认的CorsFilter来解决该问题

添加GlobalCorsConfig配置文件来允许跨域访问。

package com.macro.mall.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;
/**
* 全局跨域配置
* Created by macro on 2019/7/27.
*/
@Configuration
public class GlobalCorsConfig {
/**
* 允许跨域调用的过滤器
*/
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
//允许所有域名进行跨域调用
config.addAllowedOrigin("*");
//允许跨越发送cookie
config.setAllowCredentials(true);
//放行全部原始头信息
config.addAllowedHeader("*");
//允许所有请求方法跨域调用
config.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}

或者使用这个配置类

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "DELETE", "PUT", "PATCH")
.maxAge(3600);
}
}

重新运行代码,点击登录按钮

发现需要登录认证的/admin/info接口的OPTIONS请求无法通过认证,那是因为复杂的跨越请求需要先进行一次OPTIONS请求进行预检,我们的应用整合了SpringSecurity,对OPTIONS请求并没有放开登录认证。

设置SpringSecurity允许OPTIONS请求访问

在SecurityConfig类的configure(HttpSecurity httpSecurity)方法中添加如下代码。

.antMatchers(HttpMethod.OPTIONS)//跨域请求会先进行一次options请求
.permitAll()

重新运行代码,点击登录按钮

发现已经可以正常访问。

一次完整的跨域请求

先发起一次OPTIONS请求进行预检

  • 请求头信息:
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: POST
Origin: http://localhost:8090
Referer: http://localhost:8090/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36
  • 响应头信息:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Headers: content-type
Access-Control-Allow-Methods: POST
Access-Control-Allow-Origin: http://localhost:8090
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Length: 0
Date: Sat, 27 Jul 2019 13:40:32 GMT
Expires: 0
Pragma: no-cache
Vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
  • 请求成功返回状态码为200

发起真实的跨域请求

  • 请求头信息:
Accept: application/json, text/plain
Content-Type: application/json;charset=UTF-8
Origin: http://localhost:8090
Referer: http://localhost:8090/
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36
{username: "admin", password: "123456"}
password: "123456"
username: "admin"
  • 响应头信息:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: http://localhost:8090
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Content-Type: application/json;charset=UTF-8
Date: Sat, 27 Jul 2019 13:40:32 GMT
Expires: 0
Pragma: no-cache
Transfer-Encoding: chunked
Vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 1; mode=block
  • 请求成功返回状态码为200
全部评论
m了一会学学
点赞 回复 分享
发布于 2023-03-08 16:42 四川
感谢分享,学习学习
点赞 回复 分享
发布于 2023-03-08 16:30 山东

相关推荐

03-23 18:31
已编辑
中国农业大学 Java
Q: Redis 去重方案,是使用“用户 ID + 消息模板 ID”作为键吗?这里的模板 ID是指每个配置的模板类型拥有唯一 ID,还是说不同配置下 ID 会重复?Q:项目中使用的 Redis 架构模式是什么?是单节点、哨兵模式(Sentinel)还是集群模式(Cluster)Q:引入 Apollo 配置中心是为了解决什么问题Q: Kafka 部署时如何搭建生产环境和消费环境?具体的集群架构或部署方式是?Q:关于渠道业务,虽然目前数据量不大可能不需要限流,后续流量增大,如何设计限流策略Q:项目中的线程池具体用哪种方式创建或配置(例如通过 ThreadPoolExecutor 构造函数还是工具类)?Q:详细描述项目中使用线程池的整体逻辑流程,包括任务提交、执行以及后续处理的步骤Q:线程池的拒绝策略主要有哪几种Q:核心线程数(corePoolSize)在运行过程中是否可以动态减少Q:数据清洗过程中是否考虑过可能出现消息乱序或数据重复的问题?如果有,如何解决Q:使用的 MySQL 数据库中,单表的最大数据量大概达到多少Q:在数据库中添加索引的主要目的是什么Q:添加索引时,特定的规范或原则?具体的优化策略?Q:简要解释回表Q:对于一条包含 SELECT * FROM table WHERE condition ORDER BY ... LIMIT ... 的 SQL 语句,各个子句的执行顺序Q:如果是多表关联查询(涉及主表和子表),MySQL 底层是如何处理和执行这些连接操作的?Q:假设开发的一个接口响应时间长达一分钟,需要从哪些方面入手进行优化?简述优化思路。Q:结合您的开发经历,你认为引入大模型技术相比传统开发方式,主要在哪些方面提升了开发效率或系统能力Q:多场景对话支持中,系统如何实现不同场景之间的隔离与共享Q:主要使用了什么存储介质来保存对话的状态、记忆或中间数据
点赞 评论 收藏
分享
03-09 15:23
已编辑
蚌埠坦克学院 前端工程师
由于主包的拖延症,一直拖到了现在才写这篇帖子,因为觉得自己的去向一般,迟迟也没有动笔,突然在一个肝论文的深夜,看到自己写的暑期实习的帖子,决定还是提笔记录一下这段难忘的时光主包于9月初结束了在某互联网大厂的暑期实习,并没有成功转正其实在7月初就看出了端倪,并在8月上旬就开始复习并准备秋招,从8月中旬就猛猛加入面试大军了但是真的要提的一点是:传统开发已经不太推荐走了,不管是传统的前端还是后端,目前AI已成潮流,无论什么岗位都在问AI相关的知识,同时AI使得开发岗的工作效率大幅提高,一个人能干好几个人的活儿根据今年秋招的形式来看,不沾AI的传统开发岗位基本工资都开不高,而沾AI的AI infra、大模型算法,以及与大模型业务有关的应用开发,基础上下游业务不管是岗位数还是薪资比起往年都涨了很大一截,因此推荐后浪宝宝们(特别是学历里带9的),勇敢的加入ai的浪潮吧!互联网的offer如下:(1)京东:二轮面试+一轮HR,开奖大SP(2)Shopee:三轮面试+一轮HR,开奖大SP(3)钉钉:二轮面试+一轮HR,大白菜(4)高德:二轮面试+一轮HR,小SP(阿里今年给传统开发是真的开不起价)(5)阿里云:二轮面试+一轮HR,面试均通过,泡死了(很有可能是暑期拒过offer的原因)(6)滴滴:三轮面试+无HR,大SP(7)得物:两轮还是三轮我忘了,面试都过了,12月跑过来和我说原部门没有HC了让我换部门加面,寻思不会去,拒面了,就没开奖(8)字节系懂车帝:三轮面试+一轮HR,感觉已经给到他们那边的顶了,应该是SSP了(9)字节跳动:三轮面试+一轮HR,开奖大SP其余流程:小红书二面拒面OPPO三面拒面百度泡挂了阿里国际泡挂了小鹏HR面拒面值得一提的是腾讯,先是WXG捞我起来,不能从10月实习到毕业秒挂,接着又是CDG,面到三面了已经说到进来做什么了,秒挂,被IEG捞起来KPI面,面试官急的像要去投胎,然后又被WXG捞起来二面过,不约三面直接挂,腾讯你是要咋的?(怨气值MAX)在互联网结束后,又加入了国央企的面试行列,事实证明,即使双九+互联网实习,在目前国央企行列中依然啥也不是因为我主要投电网、银行总行+省公司、以及中证登、中金所、中债登、运营商等单位,根据今年观察到的情况,参加面试的大部分都是双九或2本9硕,且人手大厂实习,竞争可以说是非常的激烈,也许稳定对于这个高速变化的时代,可能真有一丝吸引力吧。。。我并不是一个很高精力的人,很容易累,抗压能力不好,在面试时候向面试官展示的喜欢新技术,其实不然,完全是一个不太喜欢写代码的人。。。在整个国央企求职周期中(10月-12月),主包在往返北京,上海,杭州,南京,广州等城市多次,交通和住宿合计花了一万元+的情况下一共就拿到两个offer,其中一个就是主包最终的去向(怕开盒就不说是哪家了)PS. 是的,主包在经过的反复地思考,权衡之后,最终还是选择了国企,根据大模型发展的速度,非常担心传统前后端开发,尤其是业务未来的行情,最终还是选择跑路国企了,也不知道这选择是否正确,但是确实是觉得传统前端开发很难吃到AI红利,还容易被取代,前途不甚光明了。当时也曾犹豫过,两边似乎都有自己想要的东西,羡慕互联网的高薪和自由,同时厌恶他的高压,担心传统前端开发未来的前景。选择国央企,其实也失去了很多东西,包括自由,高薪,看到身边的同学一毕业在互联网拿自己4-5倍的工资,以求得在时代浪潮中一时的稳定(未来稳不稳定也不好说,轻松也不一定轻松)归结到最后还是一个问题:你究竟想要什么样的生活?这篇帖子留给牛客社区的后浪们,希望大家都能在下一年的秋招中拿大包!也留给我自己,致敬我自己艰难且并不算太成功的求职之路,始于研二秋,终于研三冬,历经一年半载,付出无数日夜,八股文、算法题、项目背到厌烦。整个人在思想上也发生了很大的蜕变,是真正意义上的成长了。希望我工作后,回来看到这篇帖子时,也能够像现在的我看到暑期实习结束时的帖子时一样,还愿意动笔,写一点什么吧。“潺潺流水终于翻过了群山一座座。”碎碎念(主包失败的感情经历 and 秋招结束后的日本旅游之旅):在签完三方之后,和喜欢的师兄一起(没错,接前文,是暑期实习那会去哈尔滨找的那个)去了日本北海道和东京旅游,见到了完全不一样的世界,人生第一次出国,玩的特别特别开心,虽然不知道和我同行的他究竟玩的开不开心。我们12月下旬离开大陆,前往北海道,看过了小樽的雪,一起在《情书》的船见坂打卡,看小樽的海,在小樽邮局猛猛拍照,一起逛过了札幌的街道,在狸小路商店街疯狂shopping,在白色恋人公园打卡,也逛过北海道神宫和北海道大学,小傻瓜还能买错机票导致损失5000块。。。我聪明无比的师兄怎么会犯这种错误呢,但大部分时候还是觉得他好可爱喔(恋爱的酸臭味,好像我真的很久没有这么喜欢过一个人了)我们在25年的最后一天,看过了富士山,我常听陈奕迅的富士山下,不曾想他有一天真的能实现。即使“谁能凭爱意要富士山私有。”在26年的第一天起个大早,一起来到浅草寺祈福,去了心心念念的秋叶原(二次元圣地了属于是)也看了东京塔的夜景,去了传说的歌舞伎町。1月2日东京下了一场大雪,我站在雪里想,如果我们能一起看到该多好。后来我独自走了很多地方,去了涉谷,银座,逛了一直想去却没机会的梦校——东京大学。离开东京那天,一个人在日暮里散步,空荡的街道上,时间似乎也变得很慢,一切回归平静,我真的非常喜欢这样的生活。在日本的旅途就像一场永远也不会醒来的梦,虽然是听不懂的语言,不熟悉的交通,但是一切都充满新鲜感,让我感受到——我是真真切切的在“活着”。回国之后,在很多个瞬间,我总是会回忆起二人在日本的时光,原来思念是这样难熬的东西,它不会轰轰烈烈地出现,只会在某个夜晚、某个街角、某个熟悉的瞬间,突然把人拉回过去。我把浅草寺的签裱进了相框里,像是把那段时间小心地封存起来。我想留下些什么,证明我们真的曾经一起走过那段路。我无法留住离开的人,但回忆我会永远留在心底。原来有些相遇,真的不是为了一个结局,而是为了让我们在彼此的生命里留下些什么。“忘掉我跟你恩怨 樱花开了几转 东京之旅一早比一世遥远。”——谢谢你,再见了。
风起天阑_:我就说我们工科生是有文笔的
26届求职交流
点赞 评论 收藏
分享
评论
1
6
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务