【一文带你解决跨域问题】

16 篇文章 1 订阅
4 篇文章 0 订阅
唠嗑部分

在前后端分离项目中,ajax是数据交互中不可缺少的一个js库,它能够实现局部刷新,替代原生全局刷新对用户的冲击感,提升了用户体验,目前像jQuery-ajax, 基于Promise风格的axios是时代的主流,但是殊不知,ajax受同源策略的限制

同源策略是浏览器的一种保护机制,是浏览器的一个安全功能,不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源,如果两个 URL 的协议、ip地址、端口都相同的话,则这两个 URL 是同源

违背同源策略就是跨域访问

例如 : 3000服务器给8080服务器发送数据请求,ajax放行,数据发送成功,8080收到请求,将数据返回给3000服务器,但是由于同源策略的影响,3000服务器将ajax带来的数据拒收了

开发环境解决方案:

  • 配置代理,适用于React、Vue等工程化项目,也可以自己搭建开发代理服务器
  • 服务器统一解决,一劳永逸

生产环境部署都是通过nginx解决

下面让我们一起来重温一下

案发现场

环境搭建,两个版本,分别使用Vue脚手架和非脚手架版,简单的登录功能,用户输入用户名密码实现登录逻辑

简单的login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录base版</title>
    <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue@2.6.0"></script>
    <script type="text/javascript" src="https://cdn.bootcdn.net/ajax/libs/axios/1.3.2/axios.js"></script>
</head>
<body>
    <div id="root">
        <form @submit.stop.prevent="login">
            <input v-model="loginForm.username" type="text" required placeholder="用户名"/><br/>
            <input v-model="loginForm.password" type="password" required placeholder="密码"/><br/>
            <button type="submit">登录</button>
        </form>
    </div>
    <script type="text/javascript">
        new Vue({
            el: '#root',
            data: {
                loginForm: {
                    username:'',
                    password: ''
                }
            },
            methods: {
                login(){
                    console.log(this.loginForm)
                    axios({
                        url: 'http://127.0.0.1:2023/auth/login',
                        method: 'post',
                        data: this.loginForm
                    }).then(res => {
                        const { data } = res
                        console.log(data)
                    }).catch(err => {
                        console.log(err)
                    })
                }
            }
        })
    </script>
</body>
</html>

登录接口(模拟数据-不是重点)

/**
 * @Project: spring-boot-cross-domain-demo
 * @Author: cxs2014501@163.com
 * @Create: 2023/2/9 13:27
 * @Description:
 **/
@RestController
@RequestMapping("/auth")
public class LoginController {

    private static final String ACCOUNT = "admin";
    private static final String PWD = "admin1234";

    @PostMapping("/login")
    public Map<String, Object> login(@RequestBody LoginDTO dto){
        Map<String, Object> map = new HashMap<>();
        if (ACCOUNT.equals(dto.getUsername()) && PWD.equals(dto.getPassword())) {
            LoginVO vo = new LoginVO();
            BeanUtils.copyProperties(dto, vo);
            vo.setLoginTime(LocalDateTime.now());
            map.put("data", vo);
            map.put("msg", "登陆成功");
        } else {
            map.put("msg", "登陆失败,用户名或密码错误");
        }
        return map;
    }
}
跨域复现
在这里插入图片描述
言归正传

非脚手架版后端统一解决跨域

SpringBoot添加Mvc配置类

/**
 * @Project: spring-boot-cross-domain-demo
 * @Author: cxs2014501@163.com
 * @Create: 2023/2/9 15:11
 * @Description:
 **/
 @Configuration
public class MyMvcConfig implements WebMvcConfigurer {
    // 解决同源策略引起的跨域
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**") //1.代表当前的哪些方法添加请求头
                .allowedMethods("*") //2.设置允许的方法
                .allowedHeaders("*") //3.设置请求头
                .allowedOriginPatterns("*") //4.设置是否跨域
                .allowCredentials(true);   //5.设置是否允许携带cookie
    }
}
测试非脚手架版后端统一解决跨域
在这里插入图片描述

脚手架版配置代理解决方案(将之前统一解决的代码注释掉)

代理服务器无ajax引擎,不受同源策略限制

原理图
在这里插入图片描述

创建vue.config.js文件,配置开发代理

module.exports = {
  devServer: {
    proxy: {
      '/api': {
        target: 'http://127.0.0.1:2023/',
        pathRewrite:{'^/api':''},     // 重写路径
        ws: true,    // 用于支持websocket
        changeOrigin: true  // 控制请求头中的host,设置服务器看到的请求来源
      }
    }
  }
}

组件比较简单,改了默认的Helloworld组件,样式请忽略

<template>
  <div class="hello">
    <form @submit.stop.prevent="login">
        <input v-model="loginForm.username" type="text" required placeholder="用户名"/><br/>
        <input v-model="loginForm.password" type="password" required placeholder="密码"/><br/>
        <button type="submit">登录</button>
    </form>
  </div>
</template>

<script>
import axios from 'axios'
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  data(){
    return {
      loginForm: {
          username:'',
          password: ''
      }
    }
  },
  methods: {
      login(){
          console.log(this.loginForm)
          axios({
              url: '/api/auth/login',
              method: 'post',
              data: this.loginForm
          }).then(res => {
              const { data } = res
              console.log(data)
          }).catch(err => {
              console.log(err)
          })
      }
  }
}
</script>
登录测试
在这里插入图片描述

我们可以看到,前端代理的方式也完美解决了跨域,十分简单,还可以配置多个代理

以上两种方式均可以解决代理,也许在你开发的时候并没有出现,因为在企业中,各个环境已经提前弄好了,你根本没有机会注意到,况且后端开发在本地根本没有机会调试页面,前端在本地也只能mock数据

生产环境跨域解决方式

1、前后端项目打包

前端项目在黑窗口执行:yarn run build
在这里插入图片描述
服务端执行mvn clean package -DskipTests
在这里插入图片描述

虚拟机ip为10.10.10.10

启动java项目

上传包&构建镜像
在这里插入图片描述
启动项目
在这里插入图片描述

看到上述日志即启动成功

安装nginx,配置文件

10.10.10.10机器已安装过nginx,就不在docker搭建了,将打包后的vue文件上传至nginx的html目录下

配置文件

server {
        listen       80;
        server_name  localhost;
        
        location / {
            index index.html;
            root html;
			try_files $uri $uri/ /index.html;
        }
	
		location ^~ /api/ {
				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;
				proxy_redirect off;
    		    proxy_pass              http://127.0.0.1:2023/;
    	}
}
访问10.10.10.10并测试
在这里插入图片描述

部署完毕,测试通过,本文是将前后端均放在同一台服务器上,属于同源,放在不同机器也是OK的,就不单独搭建虚拟机测试了,nginx没有ajax引擎,不受同源策略限制

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

全栈小白.

感谢老板,祝老板今年发大财!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值