理解并解决【跨域】问题--通过代理或【CROS】
迪丽瓦拉
2024-06-01 11:23:38
0

文章目录

  • 一.理解跨域问题
    • 引起跨域问题的原因
    • 浏览器的同源策略
  • 二.跨域问题的解决办法
    • 解决方法1-------代理(前端配置)
    • 解决方法2-----开启跨域资源共享`CORS`(后端)
  • 知识小贴士

一.理解跨域问题

主要出现在前后端分离项目

引起跨域问题的原因

浏览器的同源策略,由于跨域不符合浏览器的同源策略,被浏览器拦截了

浏览器的同源策略

  • 概念,它限制了从一个源的文档或脚本与另一个源的资源进行交互。主要是为了安全。
  • 通俗来说,浏览器不允许在js(脚本)中请求非同源(协议,ip地址,端口号任何一个不相同认为不同源)的资源。
  • 举个例子:我前端项目的地址是http://localhost:8080/XXXX, 在js(javascript脚本)中是不允许请求http://localhost:9000的因为不同源,只能请求8080端口。
  • 前后端分离项目,通常在js中使用ajax请求非同源服务器的数据,往往会引发跨域问题。

二.跨域问题的解决办法

跨域问题出现是因为再js中请求了不同源(协议,ip,端口不同)的服务器,只需要请求相同的源的服务器就可以解决这个问题,这就用到了代理,所有请求都请求相同的Node.jsnginx,对于部分请求(主要是获取静态资源的,不涉及跨域问题)直接返回对应资源,对于涉及跨域的请求,让node.jsnginx请求到对应资源再返回给浏览器,毕竟只有浏览器才有同源策略,服务器是没有的。
既然跨域浏览器不允许,那就直接告诉浏览器允许跨域----后端接口允许跨域,也可以解决跨域问题

解决方法1-------代理(前端配置)

如果不明白什么是代理,请阅读知识小贴士

  • 没有代理,浏览器通过http://localhost:8080/home.html获取html网页数据,在html页面向http://localhost:9000/xx获取html页面具体数据,由于浏览器同源策略请求是不允许的
    在这里插入图片描述

  • 通过nginxNode.js代理后,获取urlhttp//localhost:9000/xxx.htmlhtml页面
    获取urlhttp://localhost:9000/api/xxx页面内的数据 ,相同的http://localhost:9000并不会引发跨域问题,只不过带api前缀的被Node.jsngiinx代理了,向http://localhost:8080/xxx获取对应资源后再返回给客户端
    在这里插入图片描述

  • 实际解决问题(在前端添加代理配置)
    vue.config.js中添加如下配置,只要是带api前缀的都会被代理到http://localhost:9000,请求路径
    http://localhost:8080/api/xxx 被代理到http://localhost:9000/api/xxxx
    这样解决了跨域问题问题

module.exports = {devServer:{proxy:{'/api':{//匹配所有以'/api'开头的请求路径target:'http://localhost:9000',//代理目标的基础路径changeOrigin:true, //可要可不要看具体需求pathRewrite:{'^/api':''}  可要可不要看具体需求}   }}
}
​

解决方法2-----开启跨域资源共享CORS(后端)

  • cors概念
    cors是w3c标准全称是跨域资源共享。

  • 使用cors解决跨域问题
    主要实现方式是在服务器端添加响应头Access-Control-Allow-Origin(允许请求的域) 和Access-Control-Allow-Methods(允许请求的方法)

    • 在springboot中在controller加@CrossOrigin注解,springboot框架会自动实现。加注解后controller类中的所有接口都被允许访问
    • 手动添加–创建一个拦截器,在每个请求响应时增加允许跨域的请求头
      将下面拦截器放在项目中就可以解决跨域问题
@Configuration
public class CorsConfig implements Filter {@Overridepublic void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {HttpServletResponse response = (HttpServletResponse) res;HttpServletRequest request = (HttpServletRequest) req;String origin = request.getHeader("Origin");if(origin!=null) {response.setHeader("Access-Control-Allow-Origin", origin);}String headers = request.getHeader("Access-Control-Request-Headers");if(headers!=null) {response.setHeader("Access-Control-Allow-Headers", headers);response.setHeader("Access-Control-Expose-Headers", headers);}response.setHeader("Access-Control-Allow-Methods", "*");response.setHeader("Access-Control-Max-Age", "3600");response.setHeader("Access-Control-Allow-Credentials", "true");chain.doFilter(request, response);}@Overridepublic void init(FilterConfig filterConfig) {}@Overridepublic void destroy() {}
}

知识小贴士

什么是代理?
是一个位于客户端和目标服务器之间的服务器(代理服务器),为了从目标服务器取得内容,客户端向代理服务器发送一个请求并指定目标,然后代理服务器向目标服务器转交请求并将获得的内容返回给客户端。

在这里插入图片描述

相关内容