网站首页 > 技术文章 正文
做Web开发,经常会遇到跨域问题,小伙伴们在面试中,也经常被问到。这不,又有一位工作3年的小伙伴被问到这样一道题,说前后端分离后,如果解决跨域问题。
今天,我给大家分享一下我的理解。
这个问题也有很多小伙伴单独问过我,很多小伙伴知道如何解决跨域问题,但是却说不清楚跨域到底是怎么产生的。所以,回答跨域解决方案之前,我们先来介绍一下跨域产生的原因。
1、产生原因
因为一般的浏览器都有一个安全机制,叫做同源策略限制。所谓同源策略就是指用户输入的URL中包含的协议、域名、端口都完全相同。也就是说,我们使用浏览器访问网页时,必须符合同源策略的请求才能访问。如果有一项不同,浏览器会觉得有安全风险,就不想让你使用这个接口的数据。
比如,在http://localhost:8080/index 页面中,用Ajax访问https://localhost:8081/index.json接口数据的时候,这两个URL的协议和端口不相同,也就是不同源,这就产生了跨域访问。当然,浏览器还是会将这个请求发送到后台服务器,但是,浏览器不会接收服务器响应结果。
举个更通俗的例子,就好比你去肯德基点餐,非要点一碗兰州拉面,店员虽然很鄙视你,但他还是会打电话问一下兰州拉面馆问一下,兰州拉面馆说不给肯德基供货。所以,你没有吃到兰州拉面。这其中,有个反常的操作,就是虽然你点的兰州拉面,但是肯德基店员还是帮你打电话问了,是拉面馆不给肯德基供货的,如果拉面馆说给肯德基供货而且把面送过来了,那么你就能吃到兰州拉面了。
这个案例中,店员就相当于是浏览器,肯德基呢就相当于当前看到的网页,兰州拉面馆就是相当于后台服务的接口。肯德基和兰州拉面不是同一个老板,相当于是不同源。拉州拉面就是你想要的接口数据。
但如果使用Postman等开发工具进行交互是不会出现跨域问题的,这是浏览器特有的限制。
其实,跨域问题也并不是前后端分离后才有的,后端开发的程序员一般都遇到过跨域问题。只是前后端分离开发以后,前端开发体现跨域问题更加明显了,经常要找后端开发人员来解决。
2、预检请求
为了支持跨域访问,浏览器设置了预检机制。也就是说在发出跨域请求时, 浏览器会自动发出一个查询请求,称为预检请求, 用来确认目标资源是否支持跨域。
如果请求要满足以下条件,浏览器才不会发送预检请求:
1、请求方法是GET 、PosT .HEAD其中任意一个
2、请求头中包含Accept、Accept-Language、Content-Language、Content-Type、DPR、Downlink、Save-Data、Viewport.Width、Width字段。
3、Content-Type的值是text/plain 、multipart/form-data ,application/x-ww-form-urlencoded 中任意一个。
但是,在实际项目开发中,我们请求的Content-Type一般是是text/html、application/json等格式,或者使用自定义请求头,都会触发预检请求。
浏览器获取到预检请求的响应结果之后,判断服务器如果授权允许访问这个资源,就会再次请求真正的URL,如果不允许就会报这样一个错。
has been blocked by CORS policy : No 'Access-contro1-A11ow-Origin' header is present on the requested resource.
3、如何解决
我们可以利用浏览器的预检机制。
我只需要在后端服务添加CORS策略的配置就可以解决跨域问题。CORS全称是Cross Origin Resource Sharing,翻译过来叫做跨域资源共享。具体解决方案,有以下4种:
1)、如果是普通的Web项目,只需要在服务的根目录下添加一个crossdomain.xml文件即可。文件格式如下:
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.adobe.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<site-control permitted-cross-domain-policies="all"/>
<allow-access-from domain="*"/>
<allow-access-from domain="*"/>
<allow-http-request-headers-from domain="*" headers="*"/>
</cross-domain-policy>
当然,使用这种方式不够灵活,在授权过度的情况下,会存在一些安全隐患。
2)、如果是Spring项目的话,可以添加一个处理跨域的过滤器或者拦截器。如代码所示:
public class CorsFilter 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", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
chain.doFilter(req, res);
}
}
3)、如果是Spring Boot项目的话,只需要在方法上添加@CrossOrigin注解即可,如代码所示:
@GetMapping("/list")
@CrossOrigin
public List<String> list(){
...
}
如果需要支持跨域的方法非常多情况下,可以添加过滤器,比Spring更简洁,如代码所示:
@Configuration
public class CorsConfig {
@Bean
public CorsFilter corsFilter(){
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**",corsConfiguration);
return new CorsFilter(source);
}
}
4)、Spring Boot项目还有一种更方便的方式,可以实现WebMvcConfigurer接口来实现跨域支持,如代码所示:
@Configuration
public class CorsConfiguration implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowed0riginPatterns( "*")
.allowedMethods("GET","POST","PUT","DELETE","HEAD","OPTIONS")
.allowCredentials(true)I
.maxAge(3600)
.allowedHeaders("*");l
}
}
只需要重写addCorsMapping() 方法就可以了。
以上就是对Java Web跨域问题的解决方案。
我是被编程耽误的文艺Tom,如果我的分享对你有帮助,请动动手指分享给更多的人。关注我,面试不再难!
最后,7/8/9月份资料文档已整理,包含如下↓(还在持续更新中!):
①100道最新大厂经典面试题解析资料文档!
②15万+字Java面试题解析和配套答案!
③从应届生到高级开发都适用的简历模板!
④从入门到精通的架构师学习路线图!
⑤还有各种技术流程图,路径图!
有需要的 Si 我 “666”拿!
- 上一篇: 九种跨域方式实现原理(完整版) 跨域实现的几种方式
- 下一篇: 配置跨域后,框架帮我们做了什么?
猜你喜欢
- 2024-10-12 渗透测试XSS跨站攻击检测手法 xss跨站攻击类型
- 2024-10-12 e起学丨WEB安全渗透测试基础知识(六)
- 2024-10-12 全面整合才是王道,美军挑战打造全领域联合指管系统
- 2024-10-12 想送林动避雷针是什么梗 出自武动乾坤之英雄出少年
- 2024-10-12 文件上传漏洞是什么?这么通俗易懂的讲解真的很难得!
- 2024-10-12 Web渗透测试攻防之浅述信息收集 app渗透信息收集
- 2024-10-12 交易所安全测试(十一)丨安全审计指南
- 2024-10-12 Mutual Mean-Teaching:为无监督学习提供更鲁棒的伪标签
- 2024-10-12 配置跨域后,框架帮我们做了什么?
- 2024-10-12 九种跨域方式实现原理(完整版) 跨域实现的几种方式
你 发表评论:
欢迎- 最近发表
-
- 在 Spring Boot 项目中使用 activiti
- 开箱即用-activiti流程引擎(active 流程引擎)
- 在springBoot项目中整合使用activiti
- activiti中的网关是干什么的?(activiti包含网关)
- SpringBoot集成工作流Activiti(完整源码和配套文档)
- Activiti工作流介绍及使用(activiti工作流会签)
- SpringBoot集成工作流Activiti(实际项目演示)
- activiti工作流引擎(activiti工作流引擎怎么用)
- 工作流Activiti初体验及在数据库中生成的表
- Activiti工作流浅析(activiti6.0工作流引擎深度解析)
- 标签列表
-
- oraclesql优化 (66)
- 类的加载机制 (75)
- feignclient (62)
- 一致性hash算法 (71)
- dockfile (66)
- 锁机制 (57)
- javaresponse (60)
- 查看hive版本 (59)
- phpworkerman (57)
- spark算子 (58)
- vue双向绑定的原理 (68)
- springbootget请求 (58)
- docker网络三种模式 (67)
- spring控制反转 (71)
- data:image/jpeg (69)
- base64 (69)
- java分页 (64)
- kibanadocker (60)
- qabstracttablemodel (62)
- java生成pdf文件 (69)
- deletelater (62)
- com.aspose.words (58)
- android.mk (62)
- qopengl (73)
- epoch_millis (61)
本文暂时没有评论,来添加一个吧(●'◡'●)