前后端分离项目跨域问题分析及解决思路

本文介绍了前端跨域问题的解决思路,主要讨论了CORS和代理两种方式。CORS通过服务端设置接口响应头允许跨域请求,但未解决跨域请求携带cookies信息的问题,可通过设置ajax请求的withCredentials属性解决。代理方式以nginx为例,将前后端代理为同源服务,是解决跨域问题的最优方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

浏览器的同源策略限制默认情况下前端页面和后端服务在不同服务器(域名、端口不一样)时,前端页面js无法请求到后端接口服务,即存在跨域问题。

跨域问题解决思路
使用jsonp方式解决
使用cors解决
使用nginx代理解决
这里不讨论jsonp的方式,主要讨论cors和代理方式。

cors方式
通过服务端设置接口响应头Header允许接口被跨域请求,接口做如下设置即可:
@RequestMapping("crossorigin")
public String crossorigin(HttpServletResponse response) {
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    return "crossorigin请求";
}

 那么服务端即允许接口被跨域访问,不同源的前端页面也就可以调用该接口。

当然,这里只是单独设置了一个接口的响应头,实际项目中可以根据需要选择不同的设置方式,例如:

 ​​​​​​使用spring的注解@CrossOrigin
自定义拦截器,对每个请求的response header进行设置
spring自带的cors标签进行xml设置
web.xml中通过filter设置
我更喜欢自定义拦截器的方式对response header设置,允许接口跨域请求。

还存在的一些问题
上面操作只是解决了接口可以跨域请求问题,对于跨域请求携带cookies信息,还没有解决。因为默认前端页面ajax跨源请求不提供凭据(cookie、HTTP认证及客户端SSL证明等),这也是跨域请求sessionID每次都变化的问题,下面举例说明sessionID每次变化的原因:

浏览器第一次请求服务器,cookies中没有携带sessionID,服务器会随机生成一个唯一sessionID,然后返回给浏览器,浏览器将这个sessionID保存到cookies。
正常非跨域请求,以后浏览器再次请求服务器,会将这个sessionID通过cookies发送给服务器,服务器接收到sessionID,就不会重新生成一个sessionID返回给浏览器,而是返回本次接受到的sessionID,通过这种方式来保持session会话,这样每次请求服务端时sessionID就不会变化。
因为跨源请求不提供凭据(cookie、HTTP认证及客户端SSL证明等),也就是每次请求不携带cookie中数据,每次请求cookies中都不会携带sessionID,那么服务端就会认为请求是没有sessionID的第一次请求,便重新生成一个sessionID返回给浏览器。所以,每次前端页面跨源ajax请求sessionID都会变化。

要让跨域请求提供凭据,可以在ajax请求中通过将withCredentials属性设置为true,指定某个请求应该发送凭据。
这样每次跨域请求都会将cookie中的sessionID发送给服务器,sessionID就不会再改变了。

要使前端ajax跨域请求携带凭据(cookies、http认证等),需要在ajax请求中增加属性,增加下面属性

xhrFields: {  withCredentials: true } 即可。

前端代码:
<!DOCTYPE html>
<html lang="zh-cn">
<head>
<title>session-test</title>
<script src="jquery-3.3.1.min.js" type="text/javascript"></script>
</head>
<body>
    <h1>session</h1>
    <script>
        $(document).ready(function() {
            $.ajax({
                url:"http://localhost:8080/ssm-example/getSession", 
                xhrFields: {
                       withCredentials: true
                },
                success:function(data){
                    alert("sessionID = " + data);
                }
            });
        });
    </script>
</body>
</html>

后端代码:

package com.ssm.example.controller;
 
import javax.servlet.http.HttpSession;
 
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
 
@Controller
public class UserController {
    
    @RequestMapping("/getSession")
    @ResponseBody
    @CrossOrigin()
    public String getSession(HttpSession session) {
        String sessionID = session.getId();
        System.out.println(sessionID);
        return sessionID;
    }
}
当然,因为session的局限性,越来越多的项目放弃使用session的方式做登录认证,而是将需要认证的信息例如token放在请求头中,传递给服务端,因此也无需跨源请求传递请求凭证,前端页面也无需增加上面属性。

代理方式解决跨域问题
代理方式工具有多种,这里使用常用的nginx举例,nginx代理解决跨域原理其实很简单,从浏览器同源策略的限制角度考虑,通过代理方式将前端页面和后端接口代理成为同源服务(即浏览器访问前端页面和后端接口的ip主机相同、port端口相同),这样前端页面请求接口时就不会因为同源策略限制出现跨域问题。例如:

nginx配置,将前端页面代理为localhost:80地址,将后端接口代理为localhost:80/apis地址,那么浏览器就会以为前端页面和后端接口同源。

注意:因为nginx配置代理路径时,对Windows路径支持不太好,因此root路径最好使用相对路径。
worker_processes  1;
 
events {
    worker_connections  1024;
}
 
http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
 
    server {
        listen       80;
        server_name  localhost;
        charset UTF-8;
        location / { # 这里配置前端页面代理
            root   html;
            index  index.html index.htm;
        }
        location /apis { # 这里配置后端接口代理
            proxy_pass http://localhost:8080/;
        }
    }
}
前端页面JavaScript配置,经过上面nginx代理,现在前端页面地址通过 http://localhost/具体页面路径 访问,页面ajax请求接口地址也要换成nginx代理后的http://localhost/apis/具体接口地址 来访问,这样浏览器在调用的时候才会没有同源限制。
<h3 id="h3">hello crossorigin</h3>
<script type="text/javascript">
    $("#h3").click(function() {
        alert("开始请求");
        $.ajax({
            url:"http://localhost/apis/crossorigin", # 这里使用的是nginx代理后的接口路径,关键
            success:function(data) {
                alert("Data: " + data);
            }
        });
    });
</script>

页面访问http://localhohst/crossorigin.html,那么页面和接口的ip都是localhost,port端口都是80,没有浏览器同源限制,解决了跨域问题,前端页面请求会携带cookies等凭证,后端接口无需针对response header做跨域调整。

代理方式应该是解决跨域问题的最优方案,开发中应该优先采用该方式处理跨域问题,当然方案的选择还是要根据实际遇到的需求变通。

### 回答1: springbootvue前后端分离项目的设计思路和方法一般是前端后端分离,通过RESTful接口进行数据交互。前端使用Vue框架进行开发,后端使用SpringBoot框架进行开发,前后端通过接口进行数据传输。具体的方法一般是先确定需求,然后进行接口设计,前端后端分别开发,最后进行集成测试和上线发布。在开发过程中,需要注重接口的设计和规范,保证数据的安全性和正确性,同时需要注重前后端的协作和沟通,保证项目的顺利进行。 ### 回答2: Spring Boot和Vue的前后端分离项目设计思路和方法一般如下: 1.确定项目需求:首先明确需要开发的功能和需求,详细了解业务流程,并确定前后端交互的数据格式和接口规范。 2.选择技术栈:根据项目需求选择合适的技术栈。前端可以选择Vue作为前端框架,后端可以选择Spring Boot作为后端框架。 3.前端项目搭建:使用 Vue CLI 搭建前端项目,设置好项目的目录结构和配置文件。 4.后端项目搭建:使用 Spring Initializr 或手动配置搭建 Spring Boot 项目,引入必要的依赖,并设置好项目的配置文件。 5.接口开发:后端开发人员按照需求设计和编写接口,包括接口的路径、请求参数、返回数据等。可以使用Spring Boot提供的@RestController注解编写RESTful风格的接口。 6.前后端联调:前端开发人员根据后端接口文档,使用axios等工具发送请求,获取后端返回的数据并进行处理。 7.界面设计和交互开发:前端开发人员根据需求进行界面设计和交互开发,使用Vue组件化开发,配合Element UI等UI框架实现页面效果。 8.前端打包和部署:前端代码打包为静态资源,发布到服务器或者云服务上。可以使用Vue CLI提供的命令进行打包。 9.后端打包和部署:后端代码打包为jar包,发布到服务器或者云服务上。可以使用Spring Boot提供的Maven插件进行打包。 10.项目优化和测试:根据实际情况进行性能优化和功能测试,确保项目的稳定性和可靠性。 以上是Spring Boot和Vue前后端分离项目的一般设计思路和方法,具体实现过程中还需要根据项目需求进行适当的调整和优化。 ### 回答3: Spring Boot和Vue.js是目前非常流行的前后端分离的技术栈。设计思路和方法一般包括以下几个方面: 1. 前后端分离项目前端后端分别使用Vue.js和Spring Boot进行开发。前端负责展示页面和用户交互逻辑,后端负责处理业务逻辑和数据存储。 2. RESTful API:前后端通过RESTful API进行通信。后端提供接口供前端调用,并返回JSON格式的数据。 3. 数据交互:前端通过Axios等工具向后端发送请求,后端通过数据持久化(如数据库)存储数据,并返回处理结果给前端。 4. 解决方案:由于前后端分别运行在不同的端口或者名下,可能存在访问问题。可以通过配置后端的CORS(资源共享)或者使用代理服务解决问题。 5. 登录认证:在用户登录时,前端发送登录请求到后端进行验证,并采用令牌(Token)机制来保存用户的登录状态。后续的请求中,前端会携带该令牌,在后端进行验证,保证接口的安全性。 6. 前端路由:在Vue.js中使用vue-router进行前端路由管理,实现单页应用。根据URL的变化,前端可以切换到不同的页面,而需要重新加载整个页面。后端只负责提供基础页面和接口。 7. 构建与部署:前端使用npm或yarn进行项目的构建,将生成的静态文件部署到Web服务器上。后端使用Spring Boot中的嵌入式服务器进行部署。可以将前后端打包在一起发布,或者分别打包后独立发布。 总之,Spring Boot和Vue.js的前后端分离项目设计思路和方法主要包括前后端分离、RESTful API、解决方案、登录认证、前端路由和构建部署。这些方法可以使项目更加灵活、可维护和易扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值