搞定所有的跨域请求问题

转载自  搞定所有的跨域请求问题

网上各种跨域教程,各种实践,各种问答,除了简单的 jsonp 以外,很多说 CORS 的都是行不通的,老是缺那么一两个关键的配置。本文只想解决问题,所有的代码经过亲自实践。

本文解决跨域中的 get、post、data、cookie 等这些问题。

本文只会说 get 请求和 post 请求,读者请把 post 请求理解成除 get 请求外的所有其他请求方式。

JSONP

jsonp 的原理很简单,利用了【前端请求静态资源的时候不存在跨域问题】这个思路。

但是 只支持 get,只支持 get,只支持 get

注意一点,既然这个方法叫 jsonp,后端数据一定要使用 json 数据,不能随便的搞个字符串什么的,不然你会觉得结果莫名其妙的。

前端 jQuery 写法

$.ajax({type: "get",url: baseUrl + "/jsonp/get",dataType: "jsonp",success: function(response) {$("#response").val(JSON.stringify(response));}
});

dataType: "jsonp"。除了这个,其他配置和普通的请求是一样的。

后端 SpringMVC 配置

如果你也使用 SpringMVC,那么配置一个 jsonp 的 Advice 就可以了,这样我们写的每一个 Controller 方法就完全不需要考虑客户端到底是不是 jsonp 请求了,Spring 会自动做相应的处理。

@ControllerAdvice
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {public JsonpAdvice(){// 这样如果请求中带 callback 参数,Spring 就知道这个是 jsonp 的请求了super("callback");}
}

以上写法要求 SpringMVC 版本不低于 3.2,低于 3.2 的我只能说,你们该升级了。

后端非 SpringMVC 配置

以前刚工作的时候,Struts2 还红遍天,几年的光景,SpringMVC 就基本统治下来了国内市场。

偷懒一下,这里贴个伪代码吧,在我们的方法返回前端之前调一下 wrap 方法:

public Object wrap(HttpServletRequest request){String callback = request.getParameter("callback");if(StringUtils.isBlank(callback)){return result;} else {return callback+"("+JSON.toJSONString(result)+")";}
}

CORS

Cross-Origin Resource Sharing

毕竟 jsonp 只支持 get 请求,肯定不能满足我们的所有的请求需要,所以才需要搬出 CORS。

国内的 web 开发者还是比较苦逼的,用户死不升级浏览器,老板还死要开发者做兼容。

CORS 支持以下浏览器,目前来看,浏览器的问题已经越来越不重要了,连淘宝都不支持 IE7 了~

  • Chrome 3+
  • Firefox 3.5+
  • Opera 12+
  • Safari 4+
  • Internet Explorer 8+

前端 jQuery 写法

直接看代码吧:

$.ajax({type: "POST",url: baseUrl + "/jsonp/post",dataType: 'json',crossDomain: true,xhrFields: {withCredentials: true},data: {name: "name_from_frontend"},success: function (response) {console.log(response)// 返回的 json 数据$("#response").val(JSON.stringify(response));}
});

dataType: "json",这里是 json,不是 jsonp,不是 jsonp,不是 jsonp。

crossDomain: true,这里代表使用跨域请求

xhrFields: {withCredentials: true},这样配置就可以把 cookie 带过去了,不然我们连 session 都没法维护,很多人都栽在这里。当然,如果你没有这个需求,也就不需要配置这个了。

后端 SpringMVC 配置

对于大部分的 web 项目,一般都会有 mvc 相关的配置类,此类继承自 WebMvcConfigurerAdapter。如果你也使用 SpringMVC 4.2 以上的版本的话,直接像下面这样添加这个方法就可以了:

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {@Overridepublic void addCorsMappings(CorsRegistry registry) {registry.addMapping("/**/*").allowedOrigins("*");}
}

如果很不幸你的项目中 SpringMVC 版本低于 4.2,那么需要「曲线救国」一下:

public class CrossDomainFilter extends OncePerRequestFilter {@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {response.addHeader("Access-Control-Allow-Origin", "*");// 如果提示 * 不行,请往下看response.addHeader("Access-Control-Allow-Credentials", "true");response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");response.addHeader("Access-Control-Allow-Headers", "Content-Type");filterChain.doFilter(request, response);}
}

在 web.xml 中配置下 filter:

<filter><filter-name>CrossDomainFilter</filter-name><filter-class>com.javadoop.filters.CrossDomainFilter</filter-class>
</filter>
<filter-mapping><filter-name>CrossDomainFilter</filter-name><url-pattern>/*</url-pattern>
</filter-mapping>

有很多项目用 shiro 的,也可以通过配置 shiro 过滤器的方式,这里就不介绍了。

注意了,我说的是很笼统的配置,对于大部分项目是可以这么笼统地配置的。文中类似 “*” 这种配置读者应该都能知道怎么配。

如果读者发现浏览器提示不能用 ‘*’ 符号,那读者可以在上面的 filter 中根据 request 对象拿到请求头中的 referer(request.getHeader("referer")),然后动态地设置 "Access-Control-Allow-Origin":

String referer = request.getHeader("referer");
if (StringUtils.isNotBlank(referer)) {URL url = new URL(referer);String origin = url.getProtocol() + "://" + url.getHost();response.addHeader("Access-Control-Allow-Origin", origin);
} else {response.addHeader("Access-Control-Allow-Origin", "*");
}

2018-04-28:今天终于知道为什么有时候会提示我们 * 不支持了,原来是只要前端写了 withCredentials: true 那么浏览器就会提示这个,一种办法就是这里说的使用动态构造 origin 的方式,另一种办法就是跨域不传 cookie,让前端把 cookie 要传的信息(如 sessionId/accessKey) 放到 header 中或者直接写在 request 的参数里。

前端非 jQuery 写法

jQuery 一招鲜吃遍天的日子是彻底不在了,这里就说说如果不使用 jQuery 的话,怎么解决 post 跨域的问题。大部分的 js 库都会提供相应的方案的,大家直接找相应的文档看看就知道怎么用了。

来一段原生 js 介绍下:

function createCORSRequest(method, url) {var xhr = new XMLHttpRequest();if ("withCredentials" in xhr) {// 如果有 withCredentials 这个属性,那么可以肯定是 XMLHTTPRequest2 对象。看第三个参数xhr.open(method, url, true);} else if (typeof XDomainRequest != "undefined") {// 此对象是 IE 用来跨域请求的xhr = new XDomainRequest();xhr.open(method, url);} else {// 如果是这样,很不幸,浏览器不支持 CORSxhr = null;}return xhr;
}var xhr = createCORSRequest('GET', url);
if (!xhr) {throw new Error('CORS not supported');
}

其中,Chrome,Firefox,Opera,Safari 这些「程序员友好」的浏览器使用的是 XMLHTTPRequest2 对象。IE 使用的是 XDomainRequest。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/323236.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

nssl1269-射击【贪心,堆】

正题 题目大意 有n个东西&#xff0c;东西必须在aisa_i\ sai​ s前破坏&#xff0c;破坏后可以获得wiw_iwi​价值&#xff0c;求最大价值。 解题思路 我们可以将时间从大到小排序&#xff0c;然后用堆&#xff0c;每次处理价值最大的就好了。 code #include<cstdio> #…

搭建一个二次元博客

小叙&#xff1a; 因为前段日子尝试过自己搭建网站&#xff0c;也在b站发了视频&#xff0c;奈何技术太菜&#xff0c;被喷的严重。所以决定重构一下网站&#xff0c;改成一个个人博客。这里非常感谢小游提供的主题&#xff0c;感谢他对这么优秀的主题的推广。 如果你正好也要…

jar包天天见,可是你知道它的运行机制吗

转载自 jar包天天见&#xff0c;可是你知道它的运行机制吗 今天介绍两个大家每天都在用但是却很少去了解它的知识点&#xff1a;spi 和 jar 运行机制&#xff0c;废话不多说&#xff0c;开始正题。 spi spi 是 Java 提供的一套用来被第三方实现或者扩展的 API &#xff0c;…

nssl1270-创世纪【树形dp,基环树】

正题 题目大意 每个物品有一个可以限制的物品&#xff0c;要求一个集合内所有的物品都有一个不在集合内物品限制。求这个集合可以保护的最多物品 解题思路 类似没有上司的舞会 其实就是在基环树森林&#xff0c;我们可以利用二次树形dp的方法。 先找到环&#xff0c;然后强行…

从头编写 asp.net core 2.0 web api 基础框架 (5) EF CRUD

Github源码地址&#xff1a;https://github.com/solenovex/Building-asp.net-core-2-web-api-starter-template-from-scratch 这是第一大部分的最后一小部分。要完成CRUD的操作。 Repository Pattern 我们可以直接在Controller访问DbContext&#xff0c;但是可能会有一些问题: …

做这个网站原因之二

讲讲我最近干了什么事吧以及以后该干啥 其实大部分我学到的东西&#xff0c;都写在博客上了&#xff0c;可以通过博客看到一个人的学习轨迹。除了这些&#xff0c;我也尝试拍些视频去学习一些新的东西。视频剪辑&#xff0c;特效什么的都在尝试。 有个视频我也只是随便尝试尝试…

ssl提高组周四备考赛【2018.11.1】

前言 呆学校呆4天依旧不想复习期中&#xff0c;期中考凉透了。 成绩 RankRankRankPersonPersonPersonScoreScoreScoreAAABBBCCC1112014lyk2014lyk2014lyk2002002001001001007070703030302222017wyc2017wyc2017wyc1801801801001001008080800003332017xjq2017xjq2017xjq17017017…

spring cloud+dotnet core搭建微服务架构:配置中心续(五)

前言 上一章最后讲了&#xff0c;更新配置以后需要重启客户端才能生效&#xff0c;这在实际的场景中是不可取的。由于目前Steeltoe配置的重载只能由客户端发起&#xff0c;没有实现处理程序侦听服务器更改事件&#xff0c;所以还没办法实现彻底实现这一功能。这一章的例子&…

聊聊最近吧

讲讲我最近干了什么事吧以及以后该干啥 其实大部分我学到的东西&#xff0c;都写在博客上了&#xff0c;可以通过博客看到一个人的学习轨迹。除了这些&#xff0c;我也尝试拍些视频去学习一些新的东西。视频剪辑&#xff0c;特效什么的都在尝试。 有个视频我也只是随便尝试尝试…

C# 实现虚拟数字人

随着Ai技术的提升和应用&#xff0c;虚拟数字人被广泛应用到各行各业中。为我们的生活和工作提供了非常多的便利和色彩。 通过设置虚拟数字人的位置大小&#xff0c;可以让数字人可以在电脑屏幕各个位置显示&#xff1a; 虚拟数字人素材&#xff1a; 虚拟数字人(实际有语音&am…

AspectCore.Extension.Reflection : .NET Core反射扩展库

在从零实现AOP的过程中&#xff0c;难免会需要大量反射相关的操作&#xff0c;虽然在.net 4.5/.net core中反射的性能有了大幅的优化&#xff0c;但为了追求极致性能&#xff0c;自己实现了部分反射的替代方案&#xff0c;包括构造器调用、方法调用、字段读写&#xff0c;属性读…

P2468-[SDOI2010]粟粟的书架【主席树,二维前缀和】

正题 评测记录:https://www.luogu.org/recordnew/lists?uid52918&pidP2468 题目大意 对于每一个询问&#xff0c;求一个区域内最少取多少个数使它们的和不小于a。 解题思路 我们肯定取最大的 对于前50%的数据&#xff0c;用 sumi,j,ksum_{i,j,k}sumi,j,k​表示(1,1)(1,…

【分享】通过手游赚¥

这本来是个回答&#xff0c;但是在知乎被删了&#xff0c;于是我决定还是在自己网站再发一份&#xff0c;特么知乎店大欺人&#xff0c;我一这么水回答&#xff0c;还被认为是广告营销 首先说明一点&#xff0c;这个完全是自我经历&#xff0c;一种分享吧。觉得假的自然假。 我…

C++描述杭电OJ 2008.数值统计 ||

C描述杭电OJ 2008.数值统计 || Problem Description 统计给定的n个数中&#xff0c;负数、零和正数的个数。 Input 输入数据有多组&#xff0c;每组占一行&#xff0c;每行的第一个数是整数n&#xff08;n<100&#xff09;&#xff0c;表示需要统计的数值的个数&#xff…

Azure Cosmos DB技术性解读

Azure Cosmos DB是微软公司打造的一项全球分布式、横向分区、多模型数据库服务。该服务允许客户弹性&#xff08;及独立形式&#xff09;跨越任意数量地理服务区对吞吐量与存储进行扩展。Azure Cosmos DB可立足第99百分位比例提升99.99%高可用性水平&#xff0c;提供可预测吞吐…

NOIP2018-普及总结

前言 原本说要去提高的&#xff0c;然后市里瞎搞&#xff0c;就去不了了QVQQVQQVQ。 总结 这次一看感觉题目比较难&#xff0c;所以基本凉凉… 首先这次有很多失误&#xff0c;特别是T2T2T2&#xff0c;其实很容易就分析出要用longlonglong\ \ longlong long的&#xff0c;但…

语音服务——阿里云

一、语音通知 语音通知是指通过调用语音呼叫的API&#xff0c;从运营商网络向指定号码发起一通呼叫&#xff0c;呼叫被应答后&#xff0c;播放一段指定的音频。 根据音频形式的不同&#xff0c;语音通知的API分为两个&#xff1a; 若播放的音频为固定内容的音频文件&#xf…

【博客】csdn搬家到wordpress

在wordpress的插件中搜索cnblogs2wp&#xff0c;安装后&#xff0c;在工具->导入->选博客搬家&#xff0c; 遇到了些问题 总是遇到博客地址不对 https://blog.csdn.net/weixin_43560272 首先修改了后缀 这是我的博客首页地址绝对没错的啊 后缀绝对改了的 总是说地址…

C++描述杭电OJ 2009.求数列的和 ||

C描述杭电OJ 2009.求数列的和 || Problem Description 数列的定义如下&#xff1a; 数列的第一项为n&#xff0c;以后各项为前一项的平方根&#xff0c;求数列的前m项的和。 Input 输入数据有多组&#xff0c;每组占一行&#xff0c;由两个整数n&#xff08;n<10000&…

P2323-[HNOI2006]公路修建问题【并查集】

正题 评测记录:https://www.luogu.org/recordnew/lists?uid52918&pidP2323 题目大意 有n个点&#xff0c;m条边&#xff0c;对于每条边修二级公路和一级公路修建价格不同(一级比二级贵)。要求留下n-1条边使其成为一棵树且至少有k条一级公路&#xff0c;要求最贵的公路价…