SegmentFault 最新的文章 |
- Shopee在React Native 架构方面的探索
- 一个 Java 猿眼中 Vue3 和 Vue2 的差异
- 可能改变前端工程化未来的特性:ESM Loader Hooks
- CSS color-scheme 和夜间模式
- SpringBoot接口 - API接口有哪些不安全的因素?如何对接口进行签名?
- Go语言ORM框架:构造查询条件
- 【分享】从Mybatis源码中,学习到的10种设计模式
Posted: 17 Jul 2022 07:11 AM PDT 1. 背景React Native(下文简称 RN)是混合应用领域流行的跨端开发框架。RN 非常适合灵活多变的电商领域业务,由于 RN 是基于客户端渲染的技术,所以相较于 H5 页面,它在用户体验方面有一定优势。 伴随着 Shopee 业务的飞速发展,我们 App 中的 RN 代码量增长得非常快,出现了构建产物体积过大、部署时间太长、不同团队依赖冲突等问题。为了应对这些痛点,我们探索了去中心化的 RN 架构,并结合该模型自研了系统(Code Push Platform,简称 CPP)和客户端 SDK,覆盖了多团队的开发、构建、发布、运行等一系列 RN 研发周期。经过近三年的迭代,现已接入多款公司级核心 App。 Shopee 商家服务前端团队打造了多款商家端应用,大部分用户是商家服务人员,他们对业务系统高可用和问题及时反馈有着很高的要求,从而也推动我们对 React Native 的架构有了更高的要求。 本文会从发展历史、架构模型、系统设计、迁移方案四个方向逐一介绍我们如何一步步地满足多团队在复杂业务中的开发需求。 2. 发展历程随着业务高速发展,我们的 RN bundle 个数飞速增加,App 个数也达到近十个。整个 RN 项目在开发模型、部署模型和架构模型三个维度都发生了变化,从单团队发展成多团队,从一个 bundle 发展成多个 bundle,从中心化架构发展成为去中心化,最终发展成为每个团队的业务代码可以独立地开发、部署、运行。 整个发展历史分为 4 个阶段,分别是单 bundle 集中开发模式、单 bundle 多业务组开发模式、多 bundle 中心化发布模式、多 bundle 去中心化发布模式。 2.1 第一阶段:单 bundle 集中开发模式最初的 RN 整体技术架构相对简单。由于当时业务形态不算复杂,为了满足独立团队在同一个代码仓库当中的开发流程,整个发布流程是基于 CDN 的更新发布,并且使用配置文件记录 RN bundle 文件的版本以及下载地址,以此进行资源管理。整个发布的产物有两个,一个是 RN 资源包,一个是用于资源版本管理的 JSON 配置文件。 每次 RN 资源在完成构建后,这两种构建产物会被放置在静态资源目录下。App 在特定的时间节点(例如 App 重启等)会自动拉取配置文件检查资源更新状态,然后再从 CDN 拉取 RN 静态资源。在下一次打开页面的时候,App 会加载最新的页面内容。
2.2 第二阶段:单 bundle 多业务组开发模式针对上述问题,多业务组的研发解决方案是 host-plugin 这种模式。 host 用于管理公共依赖和通用逻辑,它将 React、React Native、Shopee RN SDK 等通过一个独立的仓库管理起来,保证了特殊 RN 依赖的"singleton"(单例模式)条件,避免了部分客户端组件的重叠依赖,而这种重叠依赖是 RN 官方不允许的。 一个 host 对应着多个 plugin 仓库,业务代码仓库则是被看作为一个插件(plugin),以插件的形式接入主应用当中。业务团队可以按自己的编码规范来管理这个仓库。每个插件仓库会被视为 host 项目的 npm 依赖,它的构建是一个集中发布的流程。所有代码都会集成在 host 项目当中执行构建脚本。这种模式满足超级 App 的要求。
2.3 第三阶段:多 bundle 中心化架构模式针对 RN 产物体积过大的问题,我们利用构建工具将打包产物细分成多个 bundle,这一优化是非常有必要的,我们称它为"分包"。host 项目对应的是公共包,plugin 项目对应的是业务包。 整个构建发生在 host 项目,项目的模式还是"集中构建"和"集中发布"。多 bundle 产物将会发布到系统当中,客户端将拉取热更新的内容。客户端会按需加载对应的 bundle,RN 容器单次加载消耗的资源大大减少,解决了效率问题。
2.4 第四阶段:多 bundle 去中心化架构模式去中心化 React Native 架构模式与网页的"微前端"或者客户端的"微应用"的概念类似,满足了多业务团队独立开发部署,能够在同一个 App 各模块独立运行。它涵盖了开发、构建、发布、运行等多个方面。该模型解决了上面所说的四个弊端,并针对整个研发体系有了全面的升级,优点有:RN 运行时的互不干扰,开发调试的高效,构建发布的独立性。 下文会重点介绍项目的去中心化 RN 架构和系统设计,以及我们是怎样做到灵活性和稳定性的平衡的。 3. 去中心的 RN 架构模型简单来说,去中心化的 RN 发布模型涉及到四个部分:独立的 JS 运行时;独立的开发流程;独立的构建流程;独立的发布流程。在这四个关键环节的帮助下,每个团队按自己的节奏掌控 RN 的研发流程。 3.1 独立 JS 运行时独立运行时(多 JSContext,执行上下文环境)的出现是去中心化架构的最大特色。独立运行时是对独立发布的完美保证,将 RN 运行代码按照 plugin 维度进行隔离,它可以有效避免不同业务之间的变量冲突以及依赖冲突问题,即"plugin A"的发布绝对不会影响到"plugin B"。 它的设计主要包含以下三点:
这里我们采用 Least Frequently Recently Used(简称 LFRU)的策略。当刚退出的应用被重新打开,该 JSContext 会被重新启用。这样,我们能够节省 85% 的首屏渲染时长。缓存个数管理是可配置的,业务方可以根据应用的规模作为合理的预估。当该 RN 页面还在使用中,即使超出预估数,该上下文也不会立即被回收,该设计有效地保证页面的可用性。 3.2 开发流程上文提及 RN 项目的调试效率问题,它会随着业务代码的体量增多,代码调试效能也会随之下降。每个开发者的效率问题直接影响到大家的"幸福感"。相比之下,RN 去中心化发布则是针对开发流程做了特定的优化。 随着独立运行时环境的出现,RN 进入调试的时候,客户端可以做到只加载一个 plugin 到对应的 JSContext 中,其他 plugin 则采用内置 cache。 这样做有两个好处:一是保证了服务启动范围的最小化,保证了代码热加载的效率;二是确保开发和构建两种流程的一致性,这样会让一些问题在开发阶段提前暴露出来,比如 babel 插件缺失导致的编译问题。这样的"去中心化"的开发流程提高了 RN 调试效率。 3.3 构建流程随着业务发展,某 App 的 RN plugin 数有 4 个,旧构建流程受到 plugin 个数的影响,集中构建时长超过 20 分钟。而采用去中心化 RN 架构,构建时长不再随 plugin 个数增长,只和该 plugin 代码量有关,稳定在 5 分钟左右。 新架构也是同样基于 host-plugin 模型,独立仓库的隔离让每个团队有自由的发展空间。考虑到在应用内的基础 Native 依赖是统一的,host 项目仅用来管理统一的公共依赖。项目需要优先将 common bundle 构建完成,系统会记录公共包中的依赖信息。当每个 plugin 项目进行构建的时候,构建工具会剔除掉公共包依赖信息,并完成业务包的构建。每个业务包的构建产物都是独立地存放于系统当中。系统具备独立回滚、独立发布、独立灰度的能力。 这样的好处在于构建任务的最小粒度化,每个 plugin 的构建不会引起整个项目的重新构建,做到真正意义的"按需打包"。 3.4 发布流程RN 的构建和发布是两个独立的流程。这也意味着 bundle 的构建环节和发布环节完全解耦,发布时间点也可以由每个业务团队发布负责人灵活安排。每个业务组对自己的代码质量负责,灵活地把控自己的发版本节奏,不会影响其他团队线上业务。发布流程里面包含了全量发布、联合发布、灰度发布、回滚等操作,后续章节会详细介绍如何保证发布的稳定性。 4. 系统设计对于复杂的大型项目来说,简单的热更新流程已无法满足多业务组协同合作,我们需要一个功能完善、性能优越、操作友好的热更新系统来满足复杂业务的发展。Code Push Platform 由 Node.js 编写,搭配系统附属的命令行工具和客户端 SDK。
其中,系统效能提升功能又细分为:
4.1 多团队权限管控系统除了记录每次构建操作,更重要的是工作流程的去中心化,每个 plugin 的权限是隔离的。每个负责人只能在系统内部操作,plugin 1 的负责人只能触发相关的构建和发布,没法看到 plugin 2 的操作情况。系统通过严格的权限管控来规范所有发布流程,保证了项目的可控性。
权限的管理呈树状结构,一个 App 对应着一个项目,项目负责人默认是 App 团队的项目负责人。创建一个全新的插件等系统操作需要项目负责人审批。一个 App 包含有多个 plugin,每个 plugin 负责人默认是相应的业务团队负责人,他有权限分配发布和构建的权限。 4.2 bundle 生命周期管理4.2.1 客户端版本控制RN 有别于网页应用,它对客户端有着紧密的依赖关系。在客户端底层依赖没有变化的情况下,一般情况下开发者可以通过热更新进行 RN 代码的更新。但是遇到重大的更新,例如 React Native 的版本从 59 升级到 63,不仅仅需要 JavaScript 侧改动,客户端也要升级版本且没法继续向下兼容。从技术层面看,它是难以避免的。这种客户端无法向下兼容的情况,被称为"断层"。 系统会提供客户端版本控制的能力。当重大变更出现时,App 负责人应该在系统上新建一个"断层信息",版本号的范围是从最低 App 兼容版本到最高 App 版本。在这个区间客户端才能拉取到该断层的最新 RN 资源。 如下表所示,大于等于 2.5.0 版本的 App 拉取的是 105 版本 RN 包;在 2.0.0 至 2.5.0 版本拉取到 103 版本 RN 包;在 1.0.0 至 2.0.0 版本拉取到 100 版本 RN 包。 4.2.2 灰度和回滚发布流程里面包含了全量发布、灰度发布、回滚等操作。对于大型需求,全量上线会带来潜在风险。一般来说,优先针对部分用户投放新版本,发布负责人可以根据指定用户和特定范围进行灰度发布,逐步扩大灰度发布范围,直至转到全量。当发现重大 bug 的时候,发布者可以采用"零构建"的方式进行"秒级"回滚。 去中心化 RN 架构支持每个 plugin 独立发布、独立灰度、独立回滚,以最小颗粒度的操作来保证质量规避风险。plugin 维度级别的灰度和回滚能够为不同的业务团队带了灵活性,每个业务团队可以自行发布版本,控制灰度节奏,处理线上问题。 4.3 系统效能提升4.3.1 差分增量App 频繁更新 RN 资源包会造成对用户流量的消耗,最有效的方式是利用增量更新来节省流量。RN 资源包涵盖了编译后的 JavaScript 产物、图片、翻译文件等静态资源。它们的前后版本差异即是该版本变更的代码或者其他资源文件。为了让差分粒度深入到资源包内部,系统专门提供独立的"差分服务",采用二进制差分的方式对构建产物进行差分。 RN 资源包的 diff(差分)操作在服务端完成 ,patch(整合)操作在 App 端完成。在去中心化 RN 架构中,每个 plugin 的差分都是独立的。plugin 的发布会自动触发差分的执行,系统会以 plugin 为维度拉取最近五个版本,Diff Server 则会依次将它们和当前版本进行差分计算。如果计算成功,会将差分结果上传到 CDN 并反馈给系统,否则继续重试。整个差分操作是一个异步的过程,即使出现"差分服务"下线等极端情况,系统会自动降级为全量包,保证系统的可用性。 4.3.2 多场景入口体积优化由于 React Native 的构建官方依赖于 metro.js,而它并没有具备无用代码剔除(tree-shaking)的能力。随着业务代码的膨胀,包体积的优化是一个很重要的问题。 例如,ShopeePay 为公司多款核心 App 提供支付业务。ShopeePay plugin 在不同地区、不同 App 之间存在一些页面级别差异。同一个仓库含了所有代码和资源,但是构建脚本会将它们都会打包成为一个产物。很明显,这导致 ShopeePay 的发布产物包含大量冗余资源,并非最优,浪费下载流量,同时也影响代码的执行效率。 我们采用自研的多场景插件(babel-plugin-scene),该插件通过注入的环境变量设置一个场景值,babel 可以根据场景值的差异化加载不同的文件,并且以默认文件作为降级兜底。不同场景对应不同的入口文件,利用这种形式可以有效控制包体积。 4.3.3 一站式多环境融合一个正常的研发流程是从 test 环境,到 uat 环境,再到 live环境。Code Push Platform 对接了 App 的 test/uat/live环境,所以 RN 开发者只需要在该系统就可以进行"一站式"的操作,方可满足一个需求的整个研发周期。 不同环境的包资源流转,是多环境融合的一大亮点。如果某 RN bundle 在 uat 环境构建,它也不需要重新构建,将 bundle 无缝转换到 线上 环境进行发布。它带来的优势在于"零构建时长"以及资源包的稳定性,因为 bundle 没有重新进行构建,所以它的内容已经在 uat 得到了充分的验证,发布风险更小。 5. 旧业务的迁移方案如何迁移现有业务的 App 是一个非常严肃的问题,特别是历史背景较重的业务,它们可能存在"逻辑耦合"或者"组件耦合"的场景。与此同时,很多相关业务都在需求迭代当中,系统的迁移是不能阻碍需求迭代,所以旧业务"渐进式迁移"方案是非常必要的。 5.1 逻辑耦合如果两个以上 plugin 存在逻辑依赖关系,用户必须同时加载到最新的 plugin。考虑到热更新失败的可能性,逻辑耦合就是多个 plugin 隐藏着一种约束关系。例如,订单业务和购买业务存在一定的逻辑耦合关系,发布负责人针对流量极大的超级 App,不可能逐个发布 plugin。在极端的状态下,用户可能会先加载到 plugin A,新版本的 plugin A 和旧版本的 plugin B 是不兼容的,这样会带来严重后果。遇到这种情况,有两种解决方案:
方案一是最理想化的状态,但是在业务场景细分的情况下,项目结构很难做到绝对独立。 针对老业务可以考虑方案二,系统提供了 module 的概念,一个 module 对应着两个以上的 plugin。它们存在着一个绑定的关系。在同一个下载任务里面,客户端 SDK 以"事务"形式,保证多个 plugin 能够同时下载完成并投入使用。联合发布这个能力在系统层面,有效规避这种错误的可能性。 5.2 组件耦合如果说联合发布是针对在 plugin 维度的"逻辑耦合"兼容方案,"组件耦合"则是更细粒度的组件级别的耦合关系。也就是说,一个页面中存在多个组件来自不同的团队,例如商品详情页等页面有评价功能组件。这种"一个页面存在着 JSContext 相互嵌套"的情景存在于电商业务当中。 针对这种"组件耦合"情况,有两种解决方案:
方案一是最理想的解决方案。但是考虑到迁移成本,我们也提供了方案二(一种"同屏渲染"嵌套组件)来支持这种场景,它类似一种 Native 组件。在多个 JSContext 的情况下,通过 plugin 名和页面名将所需要的内容嵌套到另一个页面当中。 如下图所示,plugin A 会嵌套 plugin B 的内容,A 和 B 也可以实现在同一个屏幕进行渲染。从 Web 的方向理解,这种情况有点像 "iframe" 的场景,支持多个页面的嵌套。它非常易于 RN 开发者的理解,客户端 SDK 能够动态加载目标 bundle 并将它渲染在合适的位置。 5.3 渐进式迁移对于现有的 App,因为业务没法暂停迭代,我们难以一次性完成整体迁移。因此,我们提供了"渐进式迁移"方案。考虑到历史背景,该方案不会一次性把所有 plugin 都迁移,而是逐步拆分,再迁移接入到新发布系统。 迁移的步骤如下图所示:
随着版本迭代,重复第二和第三步骤,直至历史业务全部拆分完毕。这样我们可以达到一个最优的目标,即是真正意义的"独立构建"和"独立发布"。 6. 总结该系统的目标在于满足所有 App 的多团队研发协作效率问题,去中心化 RN 发布模型考虑到"独立运行时"、"独立开发"、"独立构建"、"独立发布"四大方面,保障了每个 plugin 运行的独立性。最终目标在于支撑 Shopee 的多个 RN 团队在不同 App 平台根据自己节奏自由发布且高效运作。 系统设计涉及到"多团队权限管控"、"客户端版本控制"、"灰度和回滚"、"增量差分"、"多入口包体积优化"、 "一站式多环境融合",加速了整个研发流程,真正做到了"灵活性"和"稳定性"的兼得。 | ||||||||||||||||||||||||||
Posted: 17 Jul 2022 11:31 PM PDT 随着 TienChin 项目视频的录制,松哥终于也要静下心来,认真捋一捋 Vue3 中的各种新特性了,然后再和小伙伴们进行分享,其实 Vue3 中还是带来了很多新鲜的玩意,今天我们就不卷 Java 了,来卷卷前端。 以下内容是一个 Java 猿对 Vue3 的理解,主要是应用层面上,如果有专业的前端小伙伴,请轻拍。 1. script 写法进入到 Vue3 时代,最明显的感受就是在一个 .vue 文件中,script 标签的写法大变样了。以前在 Vue2 中,我们都是这样写的:
不过到了 Vue3 里边,这个写法变了,变成下面这样了:
先从大的方面来看,细节实现咱们后面再细聊。 大的方面,就是在这个 export default 中,以后就只有两个元素了,name 和 setup,我们以前的各种方法定义、生命周期函数、计算属性等等,都写在 setup 中,并且需要在 setup 中返回,setup 中返回了什么,上面的 template 中就能用什么。 这种写法稍微有点费事,所以还有一种简化的写法,像下面这样:
这种写法就是直接在 script 标签中加入 setup,然后在 script 标签中该怎么定义就怎么定义,也不用 return 了。这个场景,又有点 jQuery 的感觉了。 上面这个实现里有几个细节,我们再来详细说说。 2. 生命周期首先就是生命周期函数的写法。 以前 Vue2 里的写法有一个专业名词叫做 options API,现在在 Vue3 里也有一个专业名词叫做 composition API。在 Vue3 中,这些对应的生命周期函数都要先从 vue 中导出,然后调用并传入一个回调函数,像我们上一小节那样写。 下图这张表格展示了 options API 和 composition API 的一一对应关系:
想用哪个生命周期函数,就从 vue 中导出这个函数,然后传入回一个回调就可以使用了。例如第一小节中松哥给大家举的 onMounted 的用法。 3. 计算属性除了生命周期函数,计算属性、watch 监听等等,用法也和生命周期函数类似,需要先从 vue 中导出,导出之后,也是传入一个回调函数就可以使用了。上文有例子,我就不再啰嗦了。 像 watch 的监控,写法如下:
导入 watch 之后,然后直接使用即可。 4. ref 于 reactive上面的例子中还有一个 ref,这个玩意也需要跟大家介绍下。 在 Vue2 里边,如果我们想要定义响应式数据,一般都是写在 data 函数中的,类似下面这样:
但是在 Vue3 里边,你已经看不到 data 函数了,那怎么定义响应式数据呢?就是通过 ref 或者 reactive 来定义了。 在第一小节中,我们就是通过 ref 定义了一个名为 a 的响应式变量。 这个 a 在 script 中写的时候,有一个 value 属性,不过在 HTML 中引用的时候,是没有 value 的,可千万别写成了
现在就是通过这样的方式来定义响应式对象,修改值的时候,需要用 和 Vue2 相比,这种写法有一个很大的好处就是在方法中引用的时候不用再写 this 了。 ref 一般用来定义原始数据类型,像 String、Number、BigInt、Boolean、Symbol、Null、Undefined 这些。 如果你想定义对象,那么可以使用 reactive 来定义,如下:
这里定义了 book 对象,book 对象中包含了 name 和 author 两个属性。 有的时候,你可能批量把数据定义好了,但是在访问的时候却希望直接访问,那么我们可以使用数据展开,像下面这样:
这样,在上面访问的时候,就可以直接访问 name 和 author 两个属性了,就不用添加 book 前缀了。 不过!!! 这种写法其实有一个小坑。 比如我再添加一个按钮,如下:
这个时候点击更新按钮,你会发现没反应!因为用了数据展开之后,响应式就失效了。所以,对于这种展开的数据,应该再用 toRefs 来处理下,如下:
当然,如果你将 setup 直接写在了 script 标签中,那么可以直接按照如下方式来展开数据:
5. 小结好啦,今天就和小伙伴们分享了 Vue3 中几个新鲜的玩法~作为我们 TienChin 项目的基础(Vue 基本用法在 vhr 中都已经讲过了,所以这里就不再赘述了),当然,Vue3 和 Vue2 还有其他一些差异,这些我们都将在 TienChin 项目视频中和小伙伴们再仔细分享。 | ||||||||||||||||||||||||||
可能改变前端工程化未来的特性:ESM Loader Hooks Posted: 17 Jul 2022 08:09 PM PDT 大家好,我卡颂。 在最近发布的 如果他最终落地,很可能会成为改变前端工程化未来的特性。本文我们来聊聊他。 欢迎加入人类高质量前端框架群,带飞 本文参考: Custom ESM loaders: Who, what, when, where, why, how 特性简介用过
今天要介绍的 通过定义不同 举个例子,在命令行通过
其中,
比如在开发环境(
比如在如下语句中:
整个过程就像一个 实际例子来看一个更接近日常开发的例子,考虑如下
其中包括很多
处理CSS文件以处理
如果为了测试目的,仅需要生成类名对应快照即可,所以可以实现一个简易的
处理远程引入的模块再以处理处理远程引入的模块举例。 当识别到
总结当 比如,要处理上述提到的
你觉得这个特性对未来前端工程化会有多大影响呢? | ||||||||||||||||||||||||||
Posted: 17 Jul 2022 08:00 PM PDT 欢迎关注微信公众号:前端侦探 介绍一个和深色模式相关的CSS属性: 一、什么是 color-scheme?color-scheme顾名思义,即为"配色方案",在系统中指的是"白天模式"和"夜间模式"。使用这个属性可以轻松的更改浏览器的默认配色方案,语法如下
几个关键词如下 normal:表示元素未指定任何配色方案,因此应使用浏览器的默认配色方案呈现。 下面来看一个简单的例子
在无任何CSS的情况下,效果如下 如果将系统配色设置为深色模式,由于什么都没有做,当然也不会有什么变化,如下 现在在根元素上添加
这里设置两个值,表示可选的配色方案,由系统来决定。 官方文档上虽然说是优先选择,实测两种顺序没有区别,有知道的小伙伴可以留言指点 效果如下 是不是非常神奇?平平无奇的页面马上就支持深色模式了。 还可以指定单个值,这样就和系统配色无关了,比如
这样在浅色模式下也能以深色主题来渲染,效果如下 二、color-scheme 的作用范围通过上面的例子看着好像很强大,是不是可以一键生成"深色"模式了?其实不然, 1. 表单元素先看表单元素,就拿
假设现在我们需要做一个深色模式的主题,手动将页面背景设置为黑色
是不是感觉到未勾选状态有点太过刺眼了呢? 这时,就可以用到
这样是不是柔和多了?这里选中的主题色貌似也发生了变换,这个是浏览器为了方便夜间浏览默认设置的,如果你不希望这个选中颜色,可以用
效果如下
下面是其他表单元素的深色模式 2. 滚动条
如果在没有自定义滚动条的情况下(很多设计觉得默认滚动条挺好看的),设计了一套深色主题,可能就变成了这样 滚动条是不是显得非常突兀?是不是只能通过伪类自定义滚动条样式了呢?现在有了
这样是不是和谐多了? 其实 MDN 官网已经这么做了,上面只是临时屏蔽了这一属性 3. CSS 系统颜色系统颜色指的是浏览器内置的一些颜色。比如前面的 可以看到,
这里的 这些系统颜色不仅仅可以用在表单元素上,也能用在普通元素上,比如这里取按钮文本颜色
这个颜色会在深色模式下自动变成白色,如下 如果手动的指定了一些正常颜色,那么也就失效了
所以,综合上面所述,只有系统相关的样式和颜色才可以受到 完整的 CSS 系统颜色可以参考官方 MDN 文档 ,比较有限,而且颜色都是那种黑白等高饱和度颜色,酌情使用 三、color-scheme 和 prefers-color-scheme相比
那么,它和
请问,在浅色模式下,body 的颜色是什么? 🤔 🤔 🤔 🤔 🤔 🤔 下面来看实际结果 只有当系统真正切换到深色模式,才会变成红色 所以结论是, 四、总结一下综上所述,为了更好的支持深色模式,可以在常规的深色模式下添加
这样一个小知识点,学到了吗?下面是本文要点总结
然后提一下兼容性,其实对版本要求还挺高的 但是,这并不影响我在项目中使用。原因很简单,这算得上是渐进增强的属性,即使浏览器不支持,也不会对页面造成什么影响,如果支持,体验会更好。所以,赶紧使用起来吧,就一行代码的事,无形之中提示了视觉体验。 最后,如果觉得还不错,对你有帮助的话,欢迎点赞、收藏、转发❤❤❤ 欢迎关注微信公众号:前端侦探 | ||||||||||||||||||||||||||
SpringBoot接口 - API接口有哪些不安全的因素?如何对接口进行签名? Posted: 17 Jul 2022 04:26 PM PDT 在以SpringBoot开发后台API接口时,会存在哪些接口不安全的因素呢?通常如何去解决的呢?本文主要介绍API接口有不安全的因素以及常见的保证接口安全的方式,重点实践如何对接口进行签名。@pdai 准备知识点建议从接口整体的安全体系角度来理解,比如存在哪些不安全的因素,加密解密等知识点。 API接口有哪些不安全的因素?这里从体系角度,简单列举一些不安全的因素:
常见的保证接口安全的方式?针对上述接口存在的不安全因素,这里向你展示一些典型的保障接口安全的方式。 AccessKey&SecretKey这种设计一般用在开发接口的安全,以确保是一个合法的开发者。
以阿里云相关产品为例 认证和授权
典型的是AppKey&AppSecret,或者ClientId&ClientSecret等 比如oauth2协议的client cridential模式
grant_type参数等于client_credentials表示client credentials方式,client_id是客户端id,client_secret是客户端密钥。 返回token后,通过token访问其它接口。
比如oauth2协议的授权码模式(authorization code)和密码模式(resource owner password credentials)
grant_type参数等于password表示密码方式,client_id是客户端id,username是用户名,password是密码。 (PS:password模式只有在授权码模式(authorization code)不可用时才会采用,这里只是举个例子而已) 可选参数scope表示申请的权限范围。(相关开发框架可以参考spring security, Apache Shiro,SA-Token等) https从接口传输安全的角度,防止接口数据明文传输, 具体可以看这里 HTTP 有以下安全性问题:
HTTPs 并不是新协议,而是让 HTTP 先和 SSL(Secure Sockets Layer)通信,再由 SSL 和 TCP 通信,也就是说 HTTPs 使用了隧道进行通信。 通过使用 SSL,HTTPs 具有了加密(防窃听)、认证(防伪装)和完整性保护(防篡改)。 接口签名(加密)接口签名(加密),主要防止请求参数被篡改。特别是安全要求比较高的接口,比如支付领域的接口。
首先我们需要分配给客户端一个私钥用于URL签名加密,一般的签名算法如下: 1、首先对请求参数按key进行字母排序放入有序集合中(其它参数请参看后续补充部分); 2、对排序完的数组键值对用&进行连接,形成用于加密的参数字符串; 3、在加密的参数字符串前面或者后面加上私钥,然后用加密算法进行加密,得到sign,然后随着请求接口一起传给服务器。 例如: 服务器端接收到请求后,用同样的算法获得服务器的sign,对比客户端的sign是否一致,如果一致请求有效;如果不一致返回指定的错误信息。
一般涉及这块,主要包含三点:密钥,签名算法,签名规则
PS:有读者会问,我们是可能从有些客户端获取密钥,算法和规则的(比如前端SPA单页应用生成的js中获取密钥,算法和规则),那么签名的意义在哪里?我认为签名是手段而不是目的,签名是加大攻击者攻击难度的一种手段,至少是可以抵挡大部分简单的攻击的,再加上其它防范方式(流水号,时间戳,token等)进一步提升攻击的难度而已。
严格来说不是一回事:
签名可以放在请求参数中(path中,body中等),更为优雅的可以放在HEADER中,比如X-Sign(通常第三方的header参数以X-开头)
以腾讯开放平台为例,请参考腾讯开放平台第三方应用签名参数sig的说明 实现案例本例子采用AOP拦截自定义注解方式实现,主要看实现的思路而已(签名的目的要防止参数被篡改,就要对可能被篡改的参数签名)。@pdai 定义注解
AOP拦截这里可以看到需要对所有用户可能修改的参数点进行按规则签名
Request封装
注册
实现接口
接口测试body参数 如果不带X-SIGN 如果X-SIGN错误 如果X-SIGN正确 示例源码https://github.com/realpdai/t... 更多内容告别碎片化学习,无套路一站式体系化学习后端开发: Java 全栈知识体系(https://pdai.tech) | ||||||||||||||||||||||||||
Posted: 17 Jul 2022 06:00 PM PDT 构造查询条件worm是一款方便易用的Go语言ORM库。worm支Model方式(持结构体字段映射)、原生SQL以及SQLBuilder三种模式来操作数据库,并且Model方式、原生SQL以及SQLBuilder可混合使用。 main函数
说明:
数据库表与数据模型
数据库表user对应的实体类的定义如下:
说明:
通过ID来查询数据若数据库表存在
执行该函数后的sql日志为:
通过Where函数来查询数据Where函数的使用类似Sprintf函数,函数的第一个参数是sql语句(where语句)模板,后面的参数是模板变量的值。
说明:
XXXIf查询有些情况加我们会根据变量的值来判断使用使用一个变量来作为查询条件来查询书库,例如,若用户的姓名不为空时通过用户姓名来查询数据库。常规的写法如下:
worm提供了更为简单的方法(提供了WhereIf、AndIf、OrIf函数)来支持这种查询需求:
说明:
in、not in查询worm提供了AndIn、AndNotIn、OrIn、OrNotIn函数来支持sql语句中的in、not in查询。例如:
XXXIn、XXXNotIn的第二个参数时一个变长参数,您可以将需要查询的值作为变长参数传入,也可以将查询的值放到一个数组中进行查询:
说明:
嵌套查询语句worm支持嵌套查询语句,例如查询为:
Limit与Offset在MySQL语句中可以使用Limit与Offset来查询数据库,这种查询通常用于WEB的分页查询中。worm也支持mysql的Limit与Offset语句:
orderby查询OrderBy函数对应sql语句中的order by语句:
| ||||||||||||||||||||||||||
Posted: 17 Jul 2022 05:33 PM PDT 作者:小傅哥 沉淀、分享、成长,让自己和他人都能有所收获!😄 一、前言:小镇卷码家总有不少研发伙伴问小傅哥:"为什么学设计模式、看框架源码、补技术知识,就一个普通的业务项目,会造飞机不也是天天写CRUD吗?" 你说的没错,但你天天写CRUD,你觉得 烦不? 慌不? 是不是既担心自己没有得到技术成长,也害怕将来没法用这些都是CRUD的项目去参加;述职、晋升、答辩,甚至可能要被迫面试时,自己手里一点干货也没有的情况。 所以你/我作为一个小镇卷码家,当然要扩充自己的知识储备,否则 二、源码:学设计模式在 Mybatis 两万多行的框架源码实现中,使用了大量的设计模式来解耦工程架构中面对复杂场景的设计,这些是设计模式的巧妙使用才是整个框架的精华,这也是小傅哥喜欢卷源码的重要原因。经过小傅哥的整理有如下10种设计模式的使用,如图所示 讲道理,如果只是把这10种设计模式背下来,等着下次面试的时候拿出来说一说,虽然能有点帮助,不过这种学习方式就真的算是把路走窄了。就像你每说一个设计模式,能联想到这个设计模式在Mybatis的框架中,体现到哪个流程中的源码实现上了吗?这个源码实现的思路能不能用到你的业务流程开发里?别总说你的流程简单,用不上设计模式!难到因为有钱、富二代,就不考试吗?🤔 好啦,不扯淡了,接下来小傅哥就以《手写Mybatis:渐进式源码实践》的学习,给大家列举出这10种设计模式,在Mybatis框架中都体现在哪里了! 三、类型:创建型模式1. 工厂模式源码详见:
源码详见:
2. 单例模式源码详见:
3. 建造者模式源码详见:
四、类型:结构型模式1. 适配器模式源码详见:
源码详见:
2. 代理模式源码详见:
3. 组合模式源码详见:
源码详见:
源码详见:
配置详见:
4. 装饰器模式源码详见:
五、类型:行为型模式1. 模板模式源码详见:
源码详见:
2. 策略模式源码详见:
源码详见:
3. 迭代器模式源码详见:
六、总结:"卷王"的心得一份源码的成体系拆解渐进式学习,可能需要1~2个月的时间,相比于爽文和疲于应试要花费更多的经历。但你总会在一个大块时间学习完后,会在自己的头脑中构建出一套完整体系关于此类知识的技术架构,无论从哪里入口你都能清楚各个分支流程的走向,这也是你成为技术专家路上的深度学习。 如果你也想有这样酣畅淋漓的学习,千万别错过傅哥为你编写的资料《手写Mybatis:渐进式源码实践》目录如图所示,共计20章 |
You are subscribed to email updates from SegmentFault 最新的文章. To stop receiving these emails, you may unsubscribe now. | Email delivery powered by Google |
Inbox too full? Subscribe to the feed version of SegmentFault 最新的文章 in a feed reader. | |
Google, 1600 Amphitheatre Parkway, Mountain View, CA 94043, United States |
No comments:
Post a Comment