【项目实践】记一次对后端服务进行跨域改造和HTTPS升级的探究和实践

分类专栏:
经验分享

文章标签:
总结
计算机网络
原创

起因

项目背景是之前做的玛嘉环境物联网平台,其中的数据大屏是利用jeecg进行制作,不过后来发现数据大屏不可用,显示接口异常。

在这里插入图片描述

翻了相关文档后,发现了jeecg的一条官方通知

在这里插入图片描述 之前也没遇到过这种问题,他给出了解决方案,我一开始以为只要进行一项改造就行,后来才发现都需要......

于是乎,我开始了我的实践之路。

一、跨域问题

1.跨域问题产生的原因

要解决一个问题首先要明白产生这个问题的原因,不然只能像无头苍蝇一样乱撞。 跨域问题始于浏览器的同源策略,最初是用于防止跨站脚本攻击(XSS),即攻击者将别的网站缓存在浏览器的信息(token,cookie等)发到自己的服务器上,亦或者利用这些信息伪装成用户进行攻击操作。同源策略禁止了这一可能,就算用户不慎进入攻击者的网站,网站也不能获取其他网站(不同域)的信息,也就保证了用户隐私和数据安全。

归根结底,这一限制都源于浏览器的同源策略。

那为什么之前就能生效呢?原因是jeecg提供了代理服务,通俗点说就是提供了接口,该接口就是转发请求用的,这样就绕开了浏览器的同源策略。

而现在jeecg不提供代理服务了,那我们该如何解决跨域问题呢?

2.跨域问题的解决方案

①跨域方案理论

浏览器的同源策略虽然防止了XSS跨站脚本攻击,但是也将开发者拒之门外,虽然我们很多时候并不会涉及跨域问题,但是总有一些需求场景需要我们跨域访问。

如果我们想跨域访问,该如何做呢?

  • 对浏览器进行配置,使其允许跨域
  • 利用JSONP实现跨域(不发送xhr请求,利用script标签的src进行访问,返回js代码,然后在客户端执行)
  • 跨域资源共享CORS

第一种就是更改浏览器策略,但是毕竟不是每个用户都会修改,所以一般不会采用;第二种利用script标签的src进行访问,返回可执行js代码,然后本地执行,这种方法也不常用。

这里我采用第三种方法,跨域资源共享——CORS

浏览器开发商也意识到了同源策略给开发者们带来的不便,于是CORS标准诞生了,目前大多数浏览器都已支持CORS标准。

什么是CORS呢?

它其实是一种浏览器和服务端配合的一种“协议”。 浏览器将跨域请求区分为“简单请求”与“非简单请求”。

简单请求只需要CORS服务端在接受到携带Origin字段的跨域请求后,在response header中添加Access-Control-Allow-Origin等字段给浏览器做同源判断。 非简单请求需要CORS服务端对OPTIONS类型的请求做处理,其他与简单请求一致。

通俗来讲,CROS是浏览器通过在请求头和响应头中增加字段的方式来沟通是否允许跨域。 这个过程可以形象为以下对话: 浏览器:“这是一个跨域请求,来自....,你要不要处理嘞?” 服务端:“我只允许XXX的源访问,其他我不接受” 浏览器默默对比了下,转手拦下攻击者请求。

②CORS实践

具体做法其实很简单,Spring的web模块已经为我们提供了@CrossOrigin注解,我们只需在对应大屏接口上加上这个注解,spring就会为我们增加对应的拦截器处理请求,在响应头中添加Access-Control-Allow-Origin等字段告诉浏览器可以跨域访问。

在这里插入图片描述

当然也可以在注解中加入允许的域(访问地址)来控制。

二、https接口改造

1.Mixed-content错误

本以为搞定了跨域问题就万事大吉了,可没想到依旧是接口异常,打开开发者工具,发现报了mixed-content错误。

在这里插入图片描述

网上一搜才发现这又是浏览器的锅.................

Mixed-content错误出现是因为https页面中去访问http请求,而浏览器不允许这样的访问,所以..........

Https的目的主要是为了防止中间人攻击。

之前之所以没有这个问题,就是jeecg做了代理,即用自己支持https的接口转发请求到我们服务器,和跨域问题一样绕开浏览器的限制。

而现在的解决方法就是将后端接口服务升级为https。

2.HTTPS原理

这里简单说一下HTTPS的原理,HTTPS可以看做是HTTP+SSL/TSL的组合(市场大多是用TSL)。即在HTTP的基础上增加了SSL协议来保证传输的安全。其原理通俗来讲就是利用非对称算法(或者数学原理)得到只有浏览器和服务器才知道的秘钥(这意味着这个过程中不能出现该秘钥在网络中明文传输),之后的通信再利用该秘钥进行加密通信。

当然为了解决这个过程中公钥可信度问题,出现了SSL数字证书,它是通过第三方权威机构来为证书“背书”的。

3.HTTPS实践

①升级步骤

  • 获取证书(有免费有付费):证书是一个二进制文件,里面包含经过认证的网站公钥和一些元数据,要从经销商购买。

  • 安装证书:证书可以放在/etc/ssl目录(Linux 系统),然后根据你使用的Web服务器进行配置。

  • 修改链接:网页加载的 HTTP 资源,要全部改成 HTTPS 链接。因为加密网页内如果有非加密的资源,浏览器是不会加载那些资源的。

  • 301重定向:修改 Web 服务器的配置文件,使用 301 重定向,将 HTTP 协议的访问导向 HTTPS 协议。

以上是普通https的步骤,而我的需求只需要将后端服务升级为https的即可。因为SpringBoot项目中已经内嵌了一个Tomcat,所以我们只需要在项目中配置即可。

②获取SSL证书

这里申请阿里的免费证书

在这里插入图片描述

然后下载下来

在这里插入图片描述 我下的Tomcat版本,里面有二进制证书和存放了密码的txt文件。

我这里购买的免费DV SSL证书,只验证网站域名所有权的简易型(Class 1级)SSL证书,能起到加密传输的作用,但无法向用户证明网站的真实身份。

另外还有其他几种SSL证书, OV SSL,提供加密功能,对申请者做严格的身份审核验证,提供可信身份证明。

EV SSL 最安全、最严格 超安EV SSL证书遵循全球统一的严格身份验证标准

③Spingboot配置

将二进制证书放到/java/resources目录下,与yml配置文件平齐。

在这里插入图片描述

然后在yml配置文件中加入如下配置

#SSL证书配置,支持https
server:
  port: 8080
  ssl:
    key-store: classpath:7382759_sd-ecos.com.pfx #路径
    key-store-password: P8q41fir #你的密码(阿里下载放在txt文件中)
    key-store-type: PKCS12 #你SSL证书的类型
    ciphers: TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA256

④引入插件

这里要注意SpringBoot项目会默认进行编译,进而导致二进制证书文件被破坏,具体表现如下:

在这里插入图片描述

image-20220309161006589

在pom.xml中加入maven-resources-plugin插件

  <plugin>
            <artifactId>maven-resources-plugin</artifactId>
            <version>3.2.0</version>
            <configuration>
                <encoding>utf-8</encoding>
                <!-- 解决Spring boot引起的profile失效问题 -->
                <useDefaultDelimiters>true</useDefaultDelimiters>
                <!-- 过滤后缀为p12、pem、pfx的证书文件 -->
                <nonFilteredFileExtensions>
                    <nonFilteredFileExtension>p12</nonFilteredFileExtension>
                    <nonFilteredFileExtension>cer</nonFilteredFileExtension>
                    <nonFilteredFileExtension>pem</nonFilteredFileExtension>
                    <nonFilteredFileExtension>pfx</nonFilteredFileExtension>
                    <nonFilteredFileExtension>jkx</nonFilteredFileExtension>
                </nonFilteredFileExtensions>
            </configuration>
        </plugin>

这个插件的作用是在maven编译打包项目的时候忽略指定后缀的文件,秘钥如果不忽略就会被编译,编译后就会出问题。

至此,后端服务便升级为了HTTPS,最终,数据大屏终于能够正常访问了。

在这里插入图片描述

后记

部署完并将过程记录为博客,本以为大功告成,可第二天早上起来,杨总告诉我系统登录的二维码出问题了。

等我吃完早饭到实验室,打开浏览器,

image-20220310092128227

这是跨域问题? 后端请求的地址时是ip格式,而前端是域名,且为http,被判定为跨域 突然意识到虽然改了后端服务支持了https,但前端服务没跟上啊。

于是我将SSL证书部署到了前端项目中(部署在nignx中),因为我用了宝塔面板,所以操作起来很方便。

在这里插入图片描述

image-20220310092932017

部署完后发现

image-20220310093441518

部署前端ssl证书后(配置Nginx),错误变为了mixed-content,仔细查看发现请求为http请求,并未改为https。

思考推测原因,大概是跨域问题仍然存在,只不过mixed-content 错误比跨域优先级高。

要解决mixed-content,要么改变前端的访问路径,要么将后端支持http重定向到https。但跨域问题,仍要解决,所以综合考虑采用该前端路径的方式(也不麻烦,因为路径引用只需改一处即可) 于是我将前端项目改成了https形式的域名路径。

image-20220310095038989

打包部署,搞定!

在这里插入图片描述

总结

无论是同源策略导致的跨域问题,还是HTTPS页面访问http资源发生的Mixed-content错误,都是因为浏览器端的约束,而之所以采取这种措施,也是为了防止诸如XSS脚本注入攻击、中间人攻击等黑客攻击,保护用户数据的安全。

  • 作者:金昊霖
  • 发表时间:2020-7-04
  • 版权声明:自由转载-非商用-非衍生-保留署名(创意共享3.0许可证)
  • 评论

    留言