【SpringBoot教程】SpringBoot 实现前后端分离的跨域访问(Nginx)

作者简介:大家好,我是撸代码的羊驼,前阿里巴巴架构师,现某互联网公司CTO

联系v:sulny_ann(17362204968),加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

# 序言

使用Nginx反向代理,可以解决跨域无权和Session丢失的问题,十分方便。下面我们以前后端分离为案例,展开Nginx的使用教程。

# 配置和启动Nginx

下载地址

Nginx下载传送门:http://nginx.org/en/download.html

注意事项:下载之后,记得解压到全英文路径,避免中文路径导致Nginx启动失败。

修改配置

打开nginx.conf ,清空配置项,然后将下面的配置信息原封不动拷贝进去:

worker_processes  1;
events {    worker_connections  1024;}
http {    include       mime.types;    default_type  application/octet-stream;
    sendfile        on;    keepalive_timeout  65;
    #前端页面服务器    server {        #监听端口和域名        listen       7000;         server_name  localhost;
        #添加头部信息        proxy_set_header Cookie $http_cookie;        proxy_set_header X-Forwarded-Host $host;        proxy_set_header X-Forwarded-Server $host;        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;                #添加拦截路径和代理地址        location /api/ {                             proxy_pass http://localhost:8080/;  #注意:使用代理地址时末尾记得加上斜杠"/"。              }                #添加拦截路径和根目录        location / {               root   html/hehe;  #注意:使用"/"拦截全路径的时候记得放在最后。               index  index.html index.htm;  #index表示首页         }                       }}
 

快速启动

在Windows 环境中:

  • 快速启动Nginx:右键管理员模式,运行nginx.exe。

  • 快速关闭Nginx:在nginx主目录,添加关闭Nginx的命令。

其中结束Nginx.bat的具体内容如下:

taskkill /f /im nginx.exe
 

使用命令快速关闭Nginx

# 部署前端页面

前后端分离后,可以直接将静态资源(例如前端页面)部署到Nginx的html目录。这里我们在$nginx_home/html目录下创建一个名为hehe的文件夹,并添加一个页面(index.html)用于跨域访问测试,index页面内容如下:

​​​​​​​

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8"/>    <title>Page Index</title></head><body><h2>前台系统7000</h2><p id="info1"></p><p id="info2"></p></body>
<script src="js/jquery.js"></script><script>        $.ajax({            url: 'http://localhost:7000/api/user/login/verifyCode',            type: "POST",            success: function (data) {                //1.获取验证码                $("#info1").html("跨域访问成功:verifyCode:" + data);                //2.核对验证码                $.ajax({                    url: 'http://localhost:7000/api/user/login/checkVerifyCode',                    type: "POST",                    success: function (data) {                        $("#info2").html("跨域访问成功:checkVerifyCode:" + data);                    }                });            },            error: function (data) {                $("#info1").html("跨域失败!!");            }        });</script>
</html>
 

#  启动后端系统

首先在POM文件添加Web依赖,然后编写控制层,提供对外的访问接口。默认启动端口是8080.

​​​​​​​

package com.hehe;
@SpringBootApplication@RestController@RequestMapping("/user/login/*")public class SpringBootNginxApplication {    //在拦截器打印访问URL    @Bean    public WebMvcConfigurer webMvcConfigurer() {        return new WebMvcConfigurer() {            @Override            public void addInterceptors(InterceptorRegistry registry) {                registry.addInterceptor(new HandlerInterceptor() {                    @Override                    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {                        if(response.getStatus()/100>=4){                            System.err.println("访问URL:"+request.getAttribute(WebUtils.ERROR_REQUEST_URI_ATTRIBUTE));                        }else {                            System.out.println("访问URL:"+request.getRequestURI());                        }                    }                });            }        };    }    //提供验证码    @RequestMapping("verifyCode")    public String verifyCode(HttpServletRequest request) {        request.getSession().setAttribute("verifyCode", "N7GX");        return request.getSession().getId() + ":" + request.getSession().getAttribute("verifyCode");    }
    //核对验证码    @RequestMapping("checkVerifyCode")    public String checkVerifyCode(HttpServletRequest request) {        return request.getSession().getId() + ":" + request.getSession().getAttribute("verifyCode");    }
    public static void main(String[] args) {        SpringApplication.run(SpringBootNginxApplication.class, args);    }}
 

# 测试跨域访问

打开浏览器,访问 http://localhost:7000/api/user/login/verifyCode ,可以看到后台获取的Session和第一次生成的验证码。如图:

打开浏览器,访问 http://localhost:7000/api/user/login/checkVerifyCode ,可以看到后台获取的Session和第二次取出的验证码。

由上图可以看到,跨域访问成功,并且Session没有丢失。

# Nginx跨域总结

Nginx VS  CORS

简单来说,Nginx是间接跨域,而CORS则实现了直接跨域。Nginx的反向代理“欺诈了”浏览器,所以浏览器和服务器都认为是同源访问,所以Session不会丢失。

(PS:如果发生跨域访问,服务器会每次都创建新的Session,所以才造成了前后端分离的Session丢失问题。) 至于CORS这种跨域机制的安全性和灵活性更高,但需要自己解决跨域访问Session丢失的问题,通常情况可以采用Session+Redis来实现Session共享。)

Nginx跨域实现过程:

第1步:http://localhost:7000/index.html


第2步:http://localhost:7000/api/user/login/verifyCode

第1步是打开页面,第2步是在这个页面发起AJAX请求,并且请求的域名端口均与当前访问页面相同,属于同源操作,所以浏览器不会报出跨域禁止的错误。

第3步:http://localhost:8080/user/login/verifyCode

第3步是本案例最为关键的一步,真正的跨域操作由Nginx的proxy_pass进行完成,并成功将验证码信息以代理的身份返回给浏览器,让浏览器处于同源访问后台的错觉。打开F12可以看到代理服务器:

关于proxy_pass 斜杠"/' 的坑

通常情况下,建议大家在代理地址末尾加上"/" ,表示转发后就是proxy_pass直接拼接映射路径。

Nginx代理效果:


转发前URL:http://localhost:7000/api/user/login/verifyCode
转发后URL:http://localhost:8080/hehe/user/login/verifyCode

​​​​​​​

     server {        listen       7000;         server_name  localhost;                #正确示范: 末尾加斜杠"/"        location /api/ {                             proxy_pass http://localhost:8080/hehe/;         }                        }
 

如果代理地址末尾没有加斜杠的话,表示转发后也是proxy_pass直接拼接映射路径,但是,拼接的时候会少了个"/",这样会引发访问路径错误。

Nginx代理效果:


转发前URL:http://localhost:7000/api/user/login/verifyCode


转发后URL:http://localhost:8080/heheuser/login/verifyCode

​​​​​​​

     server {        listen       7000;         server_name  localhost;                #错误示范: 末尾无斜杠        location /api/ {                             proxy_pass http://localhost:8080/hehe;         }                        }
 

为了更方便大家,看到在Nginx调整了proxy_pass有无斜杠的区别,楼主在控制台打印了每次请求访问的URL地址,这样更加清晰:

具体做法:关闭Nginx 将代理地址修改为:proxy_pass

http://localhost:8080/hehe ,然后启动Nginx,在浏览器访问http://localhost:7000/api/user/login/verifyCode,然后查看控制台打印的URL信息。清楚的看到了因为少了斜杠而导致拼接成错误路径,如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/213198.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mybatis之核心配置文件详解、默认类型别名、Mybatis获取参数值的两种方式

学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。各位小伙伴&#xff0c;如果您&#xff1a; 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持&#xff0c;想组团高效学习… 想写博客但无从下手&#xff0c;急需…

arm-none-eabi-gcc not find

解决办法&#xff1a;安装&#xff1a;gcc-arm-none-eabi sudo apt install gcc-arm-none-eabi; 如果上边解决问题了就不用管了&#xff0c;如果解决不了&#xff0c;加上下面这句试试运气&#xff1a; $ sudo apt-get install lsb-core看吧方正我是运气还不错&#xff0c;感…

SSL 数字证书的一些细节

参考&#xff1a;TLS/SSL 协议详解(6) SSL 数字证书的一些细节1 证书验证 地址&#xff1a;https://wonderful.blog.csdn.net/article/details/77867063 参考&#xff1a;TLS/SSL协议详解 (7) SSL 数字证书的一些细节2 地址&#xff1a;https://wonderful.blog.csdn.net/articl…

Python学习笔记-类

1 定义类 类是函数的集合&#xff0c;class来定义类 pass并没有实际含义&#xff0c;只是为了代码能执行通过&#xff0c;不报错而已&#xff0c;相当于在代码种占一个位置&#xff0c;后续完善 类是对象的加工厂 2.创建对象 carCar()即是创建对象的过程 3、类的成员 3.1 实例…

福德植保无人机:绿色农业的新篇章

今天&#xff0c;我们荣幸地向您介绍福德植保无人机&#xff0c;一种改变传统农业种植方式&#xff0c;引领绿色农业的新科技产品。福德植保无人机以其高效、环保、安全的特点&#xff0c;正逐渐成为植保行业的新宠。福德植保无人机是一种搭载了高性能发动机和精确喷洒系统的飞…

代码随想录算法训练营第四十六天 _ 动态规划_背包问题总结。

学习目标&#xff1a; 动态规划五部曲&#xff1a; ① 确定dp[i]的含义 ② 求递推公式 ③ dp数组如何初始化 ④ 确定遍历顺序 ⑤ 打印递归数组 ---- 调试 引用自代码随想录&#xff01; 本文大多数内容引用自代码随想录 60天训练营打卡计划&#xff01; 学习内容&#xff1a; …

POJ - 2528 Mayor‘s posters

本题注意离散化的时候可能会出现区间串联情况&#xff0c;比如 [1,10] [5,10] [1,4] 和 [1,10] [6,10] [1,4] 直接离散化的话两者一样&#xff0c;但是实际上是不一样的 解决办法是你在相邻的差不是1的数对中再插一个数就好了 离线区间染色 查询根节点 #include<iostrea…

数组|73. 矩阵置零 48. 旋转图像

73. 矩阵置零 **题目:**给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 题目链接&#xff1a;矩阵置零 class Solution {public void setZeroes(int[][] matrix) {Stack<int[]> mapofzerone…

【Python必做100题】之第三题(找出100以内的奇数并打印)

思路&#xff1a; 1、定义一个空列表来存储所有的奇数 2、判断是奇数就追加到列表的末尾 3、打印所有的奇数 代码如下&#xff1a; list [ ] #定义一个列表来存储所有的奇数 for i in range (1,100):if i % 2 ! 0: #判断是否为奇数list.append(i) #追加到列表的末尾 prin…

使用draw.io如何让矩形单个边框有颜色其余边框为空白?

方法步骤: 第一步&#xff1a;用户打开Draw.io软件&#xff0c;并来到流程图的编辑页面上&#xff1b; 第二步&#xff1a;接着在左侧的图形库中点击矩形选项&#xff0c;成功将其添加到流程图的绘制页面上&#xff1b; 第三步&#xff1a;这时用户点击矩形并在右侧窗口中点…

C++ //习题2.3 写出以下程序运行结果。请先阅读程序,分析应输出的结果,然后上机验证。

C程序设计 &#xff08;第三版&#xff09; 谭浩强 习题2.3 习题2.3 写出以下程序运行结果。请先阅读程序&#xff0c;分析应输出的结果&#xff0c;然后上机验证。 #include <iostream> using namespace std;int main(){char c1 a, c2 b, c3 c, c4 \101, c5 \116…

DL Homework 10

习题6-1P 推导RNN反向传播算法BPTT. 习题6-2 推导公式(6.40)和公式(6.41)中的梯度 习题6-3 当使用公式(6.50)作为循环神经网络的状态更新公式时&#xff0c; 分析其可能存在梯度爆炸的原因并给出解决方法&#xff0e; 当然&#xff0c;因为我数学比较菜&#xff0c;我看了好半…

Vue之数据绑定

在我们Vue当中有两种数据绑定的方法 1.单向绑定 2.双向绑定 让我为大家介绍一下吧&#xff01; 1、单向绑定(v-bind) 数据只能从data流向页面 举个例子&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"…

BASH中export使用:命令行中传入变量

可以看到通过export address/project这句话 定义了一个变量address,数值为/project。

运维06:监控

监控生命周期 1.服务器上架到机柜2.基础设施监控 服务器温度&#xff0c;风扇转速 ipmitool命令&#xff0c;只能用在物理机上 存储的监控&#xff08;df, fdisk, iotop&#xff09; cpu&#xff08;lscpu, uptime, top, htop, glances&#xff09; 内存情况&#xff08;free&…

MVC Gantt Wrapper:RadiantQ jQuery

The RadiantQ jQuery Gantt Package includes fully functional native MVC Wrappers that let you declaratively and seamlessly configure the Gantt component within your aspx or cshtm pages just like any other MVC extensions. 如果您还没有准备好转向完全基于客户端…

(C++)只出现一次的数字I--异或

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能&#xff0c;轻松拿下世界 IT 名企 Dream Offer。https://le…

OpenAI承认ChatGPT变懒惰,正在修复该问题

OpenAI旗下的官方ChatGPT账号在社交平台表示&#xff0c;已经收到了大量用户关于GPT-4变懒惰的反馈。 这是因为自11月11日以来&#xff0c;OpenAI就没有更新过该模型。当然这不是故意的&#xff0c;大模型的行为是不可预测的&#xff0c;正在研究修复该问题。 外界猜测&#x…

企业欠税信息API:实现税务管理的智能化与高效化

前言 随着经济的发展和社会的进步&#xff0c;企业欠税问题逐渐凸显&#xff0c;成为制约经济发展的重要因素。为了解决这一问题&#xff0c;企业欠税信息API应运而生。它通过先进的技术手段&#xff0c;提供了一种全新的欠税信息查询方式&#xff0c;帮助企业实现税务管理的智…

nginx多ip部署

1.修改网卡信息自定义多个IP 进入/etc/sysconfig/network-scripts&#xff0c;编辑ifcfg-ens33网卡文件。将dhcp动态分配修改成static&#xff0c;同时添加ip地址子网掩码、网关和DNS。 修改完成后重启网卡&#xff0c;systemctl restart network 2.修改nginx配置文件 有几个…