首先, 在开篇, 我需要声明一点, 请善用搜索引擎, 百度即便是对于搜技术解决方案再垃圾, 也不可能你 跨域 这种基础的问题都找不到答案的, 跨域根本不算是什么大问题. 而且, 不要总是特立独行, 你只是个普通人, 胳膊永远是拧不过大腿的, 学会团队合作, 学会和后端沟通, 和技术总监沟通, 把你的意见发表出来, 并说出因为所以然.
为什么会有跨域这个问题
- 因为前端代码是跑在 浏览器 里的, 你的所有网路请求说白了就是 浏览器 帮你发出去的. 并不是什么 js 帮你发出去的, js只是一门语言, 他只是按照浏览器的要求, 语法的要求, 按照一定的规范和格式, 把数据发出去, 就是这样.
- 为什么后端没有跨域这个问题, 因为后端是跑在 系统 里面的
- 浏览器可以主动发起一个 跳过跨域 的网络请求(放弃吧! 和前端无关! 儿子控制不了爸爸), 但是他不会让你在 它的内核 里发起跨域请求. 浏览器是跑在 系统 里的, 后端写的程序也是直接跑在 系统 里的, 前端相当于是 浏览器的下属, 得听从 浏览器 的规则.
- 为什么浏览器不允许你去发送跨域请求? 很简单, 因为没有那家浏览器有那个能力自己造内核, 基本都是行业内比较知名的内核, 比如 chrome 的内核, 浏览器只是一个壳, 然后把内核嵌入进去, 你前端界面的渲染包括界面的展示, 并不是浏览器弄出来的, 而是内核渲染出来的.
- 既然这个问题明白了, 只要是个正常人, 都能明白了, 浏览器需要按照内核的要求, 来界定你是否可以发一个跨域请求出去. 非常不幸的告诉你, 是个正常的内核, 纯前端都是不允许发跨域请求的.
拆台杠精上线
博主, 我觉得你说的不对, 你看哈, 我要使用 vue-cli 建立的 webpack 项目, 配置了 proxyTable , 使用 npm run dev 跨域访问了! 你这说的不对, 前端是可以发跨域请求的!
- 首先, 请把这个单词翻译过来理解下: proxyTable, 是什么意思? 代理表, 什么是代理, 代理就是代替你请请求某个url并将结果返回给你, 谁给你代理? 并不是浏览器给你代理的, 是 vue-cli 下的 小型服务器 帮你去请求这个url的, 换言之就是, 你在网页上发起了一个 ajax 请求, 小型服务器会拦截你这个请求, 然后帮你发出去, 然后等对面回应了, 再将结果返回给你. 浏览器根本就管不到了. 浏览器这时候只负责的角色是: 这里有人要发起一个ajax请求了, 呐, 丢给你, 你去处理吧, 处理好了丢给我, 我再给他 , 是这样的, 明白不?
- 还有, 小型服务器只有在 npm run dev 模式下才有效, 也就是说, 只有在开发模式下代理表才生效, 如果你是构建的代码 npm run build 那个对不起, 没人给你拦截请求并代替你请求了, 又回归到浏览器的约束层, 明白不?
博主, 不行! 你说的还不对, 我就是觉得不对, 那你说, 为什么我自己请求你所谓的那个小型服务器就没有跨域的提示?
- 很简单, 因为你们符合 同源策略, 这个名词我再稍后再详细讲解, 对于浏览器而言, 你们是 一家人, 既然是一家人, 那浏览器还管你干嘛? 管多了还怪浏览器"多管闲事"呢. 而对于不符合同源策略的规则, 浏览器就类似于扮演着"银行"的角色, 你们都不是一个家人, 凭什么我让你从他的卡里取钱? 待会人家钱没了还怪我喽? 这傻X事情浏览器可不做.
什么是同源策略
- 同源策略, 通俗易懂的解释就是 界定你们是一家人的标志
- 如何才是一家人? 很简单, 协议, 域名, 端口 全部一致, 即可
- 举个例子: 你在本地跑一个项目, 端口是8080, 然后去请求百度的接口(打个比方), 肯定是不符合同源策略的, 你看, 你本地是什么地址? 127.0.0.1? localhost? 百度呢? baidu.com, 你看, 不一样吧. 你本地肯定是 http:// 打头吧? 百度呢? https:// 打头, 你看, 又不一样, 那百度的端口呢? 80(为什么是80这里不扩展了,懂的自然懂), 你呢? 8080, 如果是你, 你会觉得这两个玩意是一家人???
如何解决呢
如果您仔细阅读了上面的因为所以然, 那么您一定能猜到怎么解决问题了, 那很简单, 就是让浏览器 认为 你们是一家人, 就这样, 那怎么解决呢? 也很简单, 注意, 如下部分请给后端人员看, 纯前端我说的已经很清楚了, 无法处理跨域请求. 还不理解的在读一遍博文.
-
小伙伴, 首先, 你需要写一个拦截器, 然后把所有接口(假设你所有接口都需要前端去请求而不是自己用的话)拦截住, 然后统一修改请求头部分即可.
- 添加 Access-Control-Allow-Origin 字段, 表示允许那些域名访问接口, 图省事的话, 参数填写成星号即可(*), 及允许任何域名访问接口, 当然很显然, 这是不安全的, 部署上线阶段建议改为指定的域名
- 添加 Access-Control-Allow-Methods 字段, 表示允许那些类型的请求, 图省事也可以填写成星号(*), 这个一般对安全影响不到, 较真的话可以写成 GET,POST, 因为一般来说, 接口都只用这两种方式(不接受杠精)
- 如果您的身份验证机制还是 session 的话, 强烈建议您和您的老板说, 换成JWT的模式, 至于JWT是个什么鸟玩意自行百度或者我有时间再写吧! 前后端分离的模式标配 JWT, session的模式属于SSR那种模式的标配, 跑题了, 如果你的验证方式是 session 的话, 那么不好意思, 你还要添加一个 Access-Control-Allow-Credentials 字段, 参数为 true, 表示允许发送身份凭证(也就是所谓的sessionID)到接口, 前端的ajax请求还需要调整, 具体可看后面的博文), 这样, 您的后端程序, 才能通过 sessionID找到对应的某个用户, 然后就不用我说了, 你懂得...