✅技术社区—跨域问题及解决方案

一、什么是跨域、为什么会跨域?

我们把问题分解

  • 谁出现的跨域?

==》 浏览器!

  • 为何出现?

==》 同源策略

  • 什么是同源策略?
      • 根据百度百科 同源策略/SOP(Same origin policy)是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。
      • 所谓同源 ==》指的是 “协议+域名+端口” 三者的相同 只要有一个不同就会导致跨域问题

所谓同源指的是:

协议、域名、端口号都相同,只要有一个不相同,那么都是非同源。

浏览器在执行脚本的时候,都会检查这个脚本属于哪个页面,即检查是否同源,只有同源的脚本才会被执行;而非同源的脚本在请求数据的时候,浏览器会报一个异常,提示拒绝访问。

①、http://www.123.com/index.html 调用 http://www.123.com/welcome.jsp 协议、域名、端口号都相同,同源。

②、https://www.123.com/index.html 调用 http://www.123.com/welcome.jsp 协议不同,非同源。

③、http://www.123.com:8080/index.html 调用 http://www.123.com:8081/welcome.jsp 端口不同,非同源。

④、http://www.123.com/index.html 调用 http://www.456.com/welcome.jsp 域名不同,非同源。

⑤、http://localhost:8080/index.html 调用 http://127.0.0.1:8080/welcom.jsp 虽然localhost等同于 127.0.0.1 但是也是非同源的。

同源策略限制的情况:

1、Cookie、LocalStorage 和 IndexDB 无法读取

2、DOM 和 Js对象无法获得

3、AJAX 请求不能发送

注意:对于像 img、iframe、script 等标签的 src 属性是特例,它们是可以访问非同源网站的资源的。

二、跨域解决方案

  1. JSONP(JSON with Padding)JSONP是一种非官方的跨域解决方案,通过动态创建<script>标签的方式来绕过同源策略的限制。服务器端需要按照约定好的回调函数格式(jsonobject)返回数据,客户端通过定义同名的回调函数来接收数据。
  • 优点: 兼容性好,支持老版本浏览器。
  • 缺点: 前后端代码耦合度高,只支持GET请求,安全性较差,容易受到XSS攻击。

首先我们要修改 index.jsp 页面的 ajax 请求:

1         $.ajax({
 2             type:"get",
 3             async:false,
 4             url:"http://localhost:8080/JavaWeb01/getPassWordByUserNameServlet?userName=Tom",
 5             dataType:"jsonp",//数据类型为jsonp
 6             jsonp:"backFunction",//服务端用于接收callBack调用的function名的参数
 7             success:function (data) {
 8                 alert(data["passWord"]);
 9             },
10             error:function () {
11                 alert("error");
12             }
13 
14         });

注意:我们修改了 dataType 的数据类型为 jsonp,并且新增了 jsop 属性值为 “backFunction”。

接着在 项目的 Servlet 中进行如下修改:

1 @WebServlet("/getPassWordByUserNameServlet")
 2 public class UserServlet extends HttpServlet{
 3     @Override
 4     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 5         String userName = req.getParameter("userName");
 6         String passWord = null;
 7         if(userName != null){
 8             passWord = "123";
 9         }
10         JSONObject jsonObject = new JSONObject();
11         jsonObject.put("passWord",passWord);
12         //1、第一种方法:*表示支持所有网站访问,也可以额外配置相应网站
13         //resp.setHeader("Access-Control-Allow-Origin", "*");
14 
15         //2、第二种方法:jsonp
16         String backFunction = req.getParameter("backFunction");
17         resp.getWriter().println(backFunction+"("+jsonObject.toJSONString()+")");
18         
19         //resp.getWriter().println(jsonObject.toJSONString());
20     }
21 }

  1. CORS(Cross-Origin Resource Sharing)是一种机制,它允许来自不同源的Web页面访问服务器上的资源,解决了由于浏览器的同源策略而引起的跨域访问限制问题。CORS 通过在服务器端添加特定的HTTP响应头,来告知浏览器允许来自特定源的Web应用访问服务器上的资源。
  • 优点: 支持所有类型的HTTP请求,安全性较高。
  • 缺点: 老版本浏览器不支持。
  • CORS 通信过程都是浏览器自动完成的,不需要用户参与
  • 对于开发者一样,CORS 通信与普通的 AJAX 通信没有差别,代码完全一样。浏览器一旦发现 AJAX 请求跨域,就会自动添加一些附加的头信息
  • 因此 实现CORS的关键是服务器,只要服务器实现了CORS接口 就可以跨域通信

工作原理

  • 当一个Web应用尝试发起一个跨源请求时(例如,使用 XMLHttpRequest 或 Fetch API),浏览器会自动在请求中添加一个 Origin 头,该头包含了发起请求的页面的源信息(协议、域名和端口)。服务器接收到请求后,会检查 Origin 头,并根据自身的CORS策略决定是否允许该跨源请求。
  • 如果服务器允许该请求,它会在响应中添加一个 Access-Control-Allow-Origin 头,该头的值可以是 *(表示允许所有源)或者是与请求中 Origin 头相匹配的特定源。浏览器接收到响应后,会检查 Access-Control-Allow-Origin 头,如果源被允许,浏览器就会处理响应;如果不被允许,浏览器会阻止响应,并抛出一个错误。

后端需要做的工作

  • 分为三个场景
  • 专门支持某个接口跨域:通过@CrossOrigin注解

  • 批量支持某一批接口跨域:实现一个Web MVC Configure 这样的一个Bean,重写跨域的映射的方法,通过注册器来添加那一批接口可以实现跨域

  • 支持所有接口都跨域:设置一个过滤器来限制所有接口跨域请求

  1. 代理服务器 使用代理服务器(如 Nginx)进行请求转发是一种常见的解决跨域问题的方法。通过配置代理服务器,可以使客户端请求看起来像是发往同源服务器,而实际上是由代理服务器转发到目标服务器。这样就绕过了浏览器的同源策略限制。
  • 优点: 可以解决所有跨域问题,安全性较高。
  • 缺点: 需要服务器端额外配置和维护。

使用代理服务器(如 Nginx)进行请求转发是一种常见的解决跨域问题的方法。通过配置代理服务器,可以使客户端请求看起来像是发往同源服务器,而实际上是由代理服务器转发到目标服务器。这样就绕过了浏览器的同源策略限制。

工作原理

  1. 客户端请求:客户端(例如浏览器)发送一个请求到代理服务器,这个请求的URL看起来是同源的,因为它指向代理服务器所在的域。
  2. 代理转发:代理服务器接收到请求后,根据配置将请求转发到实际的目标服务器。这个转发过程对客户端是透明的。
  3. 目标服务器响应:目标服务器处理请求并返回响应给代理服务器。
  4. 代理返回响应:代理服务器再将目标服务器的响应转发回客户端。

Nginx 配置示例

假设有一个前端应用部署在 http://www.example.com 上,需要访问一个部署在 http://api.another-domain.com 的后端API。可以在 Nginx 中配置一个代理来实现跨域请求:

server {
    listen 8081;
    server_name www.example.com;

    location /api/ {
        proxy_pass http://api.another-domain.com/;//只要是前缀是api的请求都转发到这个地址z
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

在这个配置中:

  • server_name 指定了前端应用的域名。
  • location /api/ 指定了一个路径,所有以 /api/ 开头的请求都会被转发。
  • proxy_pass 指定了目标服务器的地址。
  • proxy_set_header 指令用于设置请求头,这些请求头会被转发到目标服务器。

使用场景

代理服务器的跨域解决方案适用于以下场景:

  • 开发环境:在本地开发时,可以使用代理服务器将前端请求转发到后端API,避免跨域问题。
  • 生产环境:在生产环境中,可以使用代理服务器来统一前端和后端的域名,从而避免跨域问题。
  • 跨域资源共享:当需要访问第三方服务或API时,可以通过代理服务器进行请求转发,实现跨域资源的访问。

相关推荐

  1. 问题解决方案

    2024-03-17 13:38:05       15 阅读
  2. 问题解决方案

    2024-03-17 13:38:05       8 阅读
  3. 问题 解决

    2024-03-17 13:38:05       12 阅读
  4. 项目记录:问题解决方案

    2024-03-17 13:38:05       40 阅读
  5. 解决问题

    2024-03-17 13:38:05       22 阅读
  6. 解决问题

    2024-03-17 13:38:05       7 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-17 13:38:05       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-17 13:38:05       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-17 13:38:05       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-17 13:38:05       20 阅读

热门阅读

  1. 基础练习题之函数

    2024-03-17 13:38:05       20 阅读
  2. ClickHouse副本节点数据损坏恢复

    2024-03-17 13:38:05       23 阅读
  3. Clickhouse MergeTree原理(二)—— 表和分区的维护

    2024-03-17 13:38:05       18 阅读
  4. Centos设置docker自启动,以及容器程序自启动

    2024-03-17 13:38:05       21 阅读
  5. Python:递归函数

    2024-03-17 13:38:05       22 阅读
  6. html导航栏+下拉菜单+表单验证

    2024-03-17 13:38:05       23 阅读
  7. HTML

    HTML

    2024-03-17 13:38:05      20 阅读
  8. 在CentOS 7系统下通过二进制方式安装MySQL 8.0.34

    2024-03-17 13:38:05       20 阅读
  9. Jtti:如何在CentOS中安装和配置Tomcat应用服务器

    2024-03-17 13:38:05       21 阅读