前言
可能之前在学校里面做的很多东西是纯后端的,不会涉及到太多和前端交互的细节,很多新手对前后端交互以及上中游业务链路的整体流程不够清晰,做一些javaweb项目可以让我们有机会对其进行更深入的研究,最近总结了一下相关技术知识点并结合自己的实践经验来和大家分享。
一、业务API网关鉴权
网关(GateWay)是什么?有哪些功能?
客户端请求服务端服务的统一入口,功能包括服务路由转发、服务注册、负载均衡、弹力设计、安全认证、流控熔断降级、日志监控等。
网关一般可以包括流量网关和业务网关,当然我们也可以把它们模糊放到一起,流量网关主要负责垂直流量控制及安全防护,提供全局性的、与后端业务应用无关的策略,例如 HTTPS证书卸载、Web防火墙、全局流量监控、日志记录、黑白名单控制、接入请求到业务系统的Nginx负载均衡等,如kong。
业务网关负责流量分发调度及服务治理,与业务紧耦合,提供单个业务域级别的策略,如服务治理、身份认证,权限控制、日志输出、数据加密、熔断限流等,如K8s的Istio。
几种网关的对比
主要聊下业务网关,比如GPT对话的页面,请求到Web的地址后,用户操作的时候会去走Http请求网关的Api接口,这个时候网关会有对应的鉴权机制。那么鉴权的目的是什么?----数据在互联网中传输是不安全的,所有处于开放环境的数据传输都可以被截取、篡改,因此数据传输必须签名加密。
签名核心解决的以下问题:
请求是否合法:请求数据的是否是我规定的那部分人
请求是否被篡改:请求的数据是否是原始数据,是否被篡改过
防止重复请求(防重放):是否重复请求
记得自己最开始不熟的时候请求网关API经常报203错误(用户信息为空),于是抽出一段时间来研究学习这部分内容,发现目前项目接触到的鉴权机制大概分成下面3种,另外还有基于proxy代理访问其他服务的,都需要考虑默认是否鉴权,以及对应的具体鉴权方式(有状态/无状态,长期/临时),可以参考这篇博文https://blog.csdn.***/DanielJackZ/article/details/122520971
Cookie + Session 实现 API 鉴权
如果是自己内部的控制台上,可能会伴随企业内部的SSO单点登录校验功能。
复习一下Cookie和Session,估计很多后端er最早接触到它还是在电商秒杀系统。
如果一个单体服务,里面设计一个登录模块,可以用Cookie和Session这种方式。Cookie的画user_token传输可以是基于线程ThreadLocal传输的。
Cookie Session Token区别与联系需要清楚 https://www.zhihu.***/question/353373715
如果cookie里面存储临时会话token的话可能过期,于是额外还有RefreshToken这种续命机制。
参考https://blog.csdn.***/NSPOKS/article/details/101771817/
如果登录以后,打开一个新的无痕页面,然后输入访问web页面地址,可能弹出登录页面,让你扫码或者用户密码或者短信验证码SSO登录,可以看到F12查看登录成功以后,传输过去的cookie信息。
另外有空还可以研究一下cookie、session、token的具体内容和格式。
跨域问题&网络安全
同源/同域策略:域名相同,端口相同,协议相同
跨域问题出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,保证安全性防止攻击,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。
前后端解决跨域问题 CORS SpringCloud Gateway注解 代理服务器
https://zhuanlan.zhihu.***/p/664531765
https://blog.csdn.***/Lee_92/article/details/129230088
https://www.shence123.***/s/11618.html
https://zhuanlan.zhihu.***/p/414130685
https://zhuanlan.zhihu.***/p/132534931?utm_id=0
网络安全风控 XSS CSRF 重放攻击等
https://blog.csdn.***/LawssssCat/article/details/104731979?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_baidulandingword~default-0-104731979-blog-106137473.235%5Ev40%5Epc_relevant_anti_vip&spm=1001.2101.3001.4242.1&utm_relevant_index=3
Cookie + Session 是最传统的 API 鉴权方式,比如很多网站的登录模块就是靠这种方式实现用户会话管理。在服务端会生成一个 session 来保持会话状态,各个 session 是通过唯一的 session_id 来标识,以次来判断请求是那个客户端发起的,session_id 存储在客户端的 cookie 中,后续所有的请求都会把 cookie 传到服务端,服务端解析 cookie 后找到对应的 session 进行判断。
特点:
(1)为了使后台应用识别是那个用户发出的请求,需要在服务端存储一份用户登录信息(session),这份信息也会在相应前端请求时返回给客户端,客户端将其保存在 cookie 中
(2)客户端下次请求时发送给服务端,服务端根据这个标识来识别具体时那个用户
(3)cookie 内仅包含一个 session 标识符,其他用户信息还是存储在服务端中
缺点:
(1)性能相对较低:每一个用户经过服务端认证后服务端都要做一次记录,以方便下次请求的鉴别,通常 session 都是保存在内存中,而随着用户认证增多,服务端开销会越来越大
(2)在一个无状态协议里注入状态,与 REST 风格不匹配
(3)因为改方案是基于 cookie 来进行识别,cookie 如果被获取用户很容易受到 CSRF 攻击
(4)很难跨平台,在移动端应用 session 和 cookie 很难行通,你无法与移动终端共享服务端创建的 session 和 cookie
API Key + API Secret
这种格式在postMan里面请求如下,这里有个小tips:可以通过PostMan的enviorment变量功能设置不同的环境(线下dev(类似http://127.0.0.1:9999 or localhost:8080等)、测试boe、预发staging、生产prod)等的地址,以及全局变量。
这种方式是指当请求的资源、API Key 和 API Secret 匹配时,用户才可以访问对应的资源,一般还会加上时间戳等方式来进行请求的时效控制。
实现方法:服务器生成一对 Key/Secret 保存,并下发给客户端,Key 和 Secret 均是按照某种规则随你生成,互相无法推算。在客户端发起请求时,需要将包含 API Key 在内的所有请求参数排序(一般都是使用字典序),然后跟 API Secret(相当于加盐)一起做 hash 生成一个 sign 参数,服务器只需要按照约定的规则做一次签名计算,然后和请求的签名做比较,如果一致则验证通过,如果验证不通过则拒绝。
这种模式并不是RBAC(角色权限控制),而是 ACL(A***ess Control List: 访问控制列表) 访问控制。这种方式实现简单,占用的计算资源和网络资源都较少,安全性也可以。但是一般来说每一个 api 都需要分配一对 Key 和 Secret,因此当 Key 和 Secret 比较多的时候,服务器会有一定的存储成本,而且服务端只能通过 API Key 来区别调用者,API Secret 一旦泄露将造成较大的安全风险。这种模式一般适用于 Web API。
token 机制实现 API 鉴权
这个可以在一些接入第三方平台的临时授权,他们没有通过Cookie+Session的登录功能,我们就可以在服务端设置对应的固定token,线下、测试、预发、生产都有不同的token值,并且添加黑白名单的路径列表,需要访问的时候,需要把自己开发的接口地址加入到权限地址列表里面,然后请求头带对应环境的token才能正确访问。
当然网关API肯定不能搞token过期了,经常过期还玩个锤子,于是可以服务端写死,约定好请求时候带上正确的token就行。
之前老的业务请求方式可能基于AK/SK的方式,后来网关暴露的API都陆续都改成了token方式,也是为了减轻服务器的存储负担。
如果没加token,或者token和环境不匹配,或者没有把路径添加到访问权限列表,或者路径写错不存在的话,都会报203,排查时候需要注意这几个点。
token 令牌机制是用来代替 session 的鉴权方式,token 机制是服务端根据特定的规则生成的一串加密字符串下发给客户端,客户端请求服务端所有资源时都会携带上这个 Token(一般设置在 header 中)。服务端来校验这个 token 的合法性,这种方式具有无状态、适合分布式、扩展性好、性能和安全性好更好等优点。
常见 Token 实现有以下几种:
自定义实现 token:应用开发者根据 token 机制原理自行实现
JWT:即 json web token,是一种主流的 token 规范
Oauth:Oauth 虽然时授权规范,但其中也用到 TOken
HTTP Basic Authentication 认证机制
Web API 是基于 HTTP 协议,而 HTTP 协议本身就带有认证机制
最后整个流程可能是下面这样,在Http请求发送Post的Object类型对象,经过Thrift序列化JSONString,在主服务的里面反序列化praseArray/Object,如果参数比较复杂并且频繁变动,就用Object接收,然后直接转String传过去,然后那边转Array或者Object,然后放到parambody转去http请求一些外部地址。
注意String类型转JSONString会报错,提前加instanceof判断一下,并且注意不恰当解析导致的"\content"的转义问题。
额外的问题:为什么公司一般HTTP接口都用POST请求,又为什么不用RestFul?
https://zhuanlan.zhihu.***/p/596637025
https://www.zhihu.***/question/336797348/answer/2189330351
https://www.zhihu.***/question/336797348/answer/2866008249?utm_id=0
额外:301 302 重定向 长链接和短链接转换的底层设计 学习一下
接口调试工具Apipost=Postman + Swagger + Mock + JMeter
二、Tomcat、Servlet、SpringMVC
如果是C++选手可能搞过Tyni-WebServer的Web服务器开发这个项目。
首先需要搞清楚它们是什么关系,个人理解:Servlet是web服务的一套协议接口,SpringMVC实现了它,是对其高级封装,Tomcat作为Web容器兼JSP/Servlet容器,可以为它们提供必要的运行环境。并且SpringBoot内置了Tomcat,可以本机80端口直接启动访问。
下面是一些比较直观的图,就不赘述了:
有个经典问题就是—Tomcat的类加载器隔离机制,及其类加载器的结构,通过重写ClassLoader的findClass和LoadClass方法可以实现自定义类加载。相关了解还有Panduora和AliTomcat等。
https://blog.csdn.***/zyh661120/article/details/119543402
https://blog.csdn.***/cristianoxm/article/details/121268913
https://blog.csdn.***/chenwiehuang/article/details/123957955
https://blog.csdn.***/weixin_45428910/article/details/129313723
https://blog.csdn.***/csucsgoat/article/details/121529374
上面的参考地址 https://www.***blogs.***/wa1l-E/p/17072581.html
关于tomcat 类加载结构,注意系统架构和类继承架构不是一回事。
https://blog.csdn.***/weixin_42146366/article/details/97749031
https://www.***blogs.***/wa1l-E/p/17072581.html
https://blog.csdn.***/qq_38526573/article/details/125425626
然后是SpringMVC,经典架构图如下,其前端控制器本质就是一个Servlet,并且SpringMVC简化了很多流程,我们项目里面更多关注Controller层也就是Handler的设计。
三、额外补充:关于长链短链转换系统的设计
长链接和短链接互相转换的功能系统设计
其实本质底层是301—永久重定向和302临时重定向
经常被问到这个系统的设计,包括存储,路由,查询规则
可以参考一些方案的地址:
https://www.***blogs.***/lingyejun/p/15894620.html
https://blog.51cto.***/u_15300891/3057116
总结
这篇文章我们梳理了web服务和前端交互相关的上中游业务技术知识点,涉及到网关鉴权、Cookie、Session、Token、AK-SK、跨域问题、网络安全、Tomcat、Servlet、SpringMVC等,总结的过程也是一种系统化的复习,可能自己以后工作时候遇到不清楚的地方,能够结合自己以前的经历回想到自己曾经整理过的内容。