控制台
authing blog banner
查看文章
Authing share | 一文带你读懂云原生、微服务与高可用
云原生 云原生是一个不断变化的概念,它的定义也在不断变化,其解释权不被个人或某些组织所有。但大体上,云原生(CloudNative) ,云指的是应用位于云中,而不是传统的数据中心;原生是指应用在设计之初就是以在云上运行为目标的,最大限度的利用云的分布式、高弹性等优势。   Pivotal 公司于 2013 年首次提出云原生(CloudNative)概念,现在 Pivotal 已成为了 Vmware tanzu 的一部分,他们最新的官网对于如何构建云原生应用描述了以下 4 点: DevOps:DevOps 是软件开发人员和 IT 运营之间的协作,旨在提供解决客户问题的高质量软件,使构建、测试和发布软件可以快速、频繁且更一致地进行。 微服务:微服务是一种将应用程序开发为小服务集合的架构方法; 每个服务都实现业务功能,在自己的进程中运行,并通过 HTTP API 或消息传递进行通信。 每个微服务都可以独立于同一应用程序中的其他服务进行部署、升级、扩展和重新启动,通常作为自动化系统的一部分,可以在不影响客户的情况下频繁更新实时应用程序。 容器化:与标准虚拟机 (VM) 相比,容器有更高的效率和速度。 使用操作系统级虚拟化,单个操作系统实例在一个或多个隔离容器之间动态划分,每个容器具有唯一的可写文件系统和资源配额。 创建和销毁容器的低开销以及单个 VM 中的高打包密度使容器成为部署单个微服务的理想计算工具。 安全性:云原生安全基于以下三个原则提供了一种降低企业风险的变革性方法:更新可用时立即修复易受攻击的软件; 经常从已知良好的状态重新修复服务器和应用程序; 经常轮换用户凭据。 总而言之,云原生架构的应用程序应该是:采用容器化方案,基于微服务架构提高灵活性和可维护性,借助敏捷方法、DevOps 支持持续迭代和运维自动化,利用云平台设施实现弹性伸缩、动态调度、优化资源利用率的应用程序。   云原生构建应用简便快捷,部署轻松自如、按需伸缩、架构灵活;相比 OpenStack 等虚拟化方案,减少了虚拟化的开销、部署成本低、性能更好;相比纯 Docker 集群,有更好的编排能力,维护性更好,可用性更高,可以减少故障率;而天生对微服务的支持也使得高内聚、低耦合可以轻松实现,使得运维、扩容、敏捷开发变得更加容易;云原生的优点不一而足,缺点却难以与其相提并论。 微服务 软件设计有两个关键目标:高内聚、低耦合,围绕这 2 个核心目标,又提出了单一职责、开闭原则、里氏替换、依赖导致、接口隔离、最少知识等设计原则,这也即是微服务的原则。   一个项目,开始搭建时总会有预料不到的后续问题,随着用户和业务的增长,性能就会出现瓶颈,或者项目的架构难以满足业务需要,这时候除了常规的代码优化外,就需要拆分服务了。   举个例子,一个项目刚刚创建,谁也不知道它未来要服务多少客户,5 个人的团队就能完成全部的开发任务,每个开发人员都对项目的代码心中有数,但随着业务的增长,复杂度的提升,团队从 5 个人变成了 50 个人,代码也从几千行到了几十万行,这时候单一的开发人员就很难对所有的代码都做到“心中有数”了,而当代码数量再度增加,业务也更上一个层级的时候,单纯的某一个子业务的代码就已经复杂到需要一个团队来开发维护了,此时老的架构已经不能支持业务的需求,对代码的维护也成了一个难题。   更好的做法是,在某个合适的时间点把代码按照核心功能拆分成一个个微服务,每个服务只关注自己的实现,每个服务都可以单独开发和部署,每个服务都可以交给一个团队,服务之间通过预先定义好的接口进行通讯。这样,每个团队只需关心自己负责部分的代码和功能,而个别服务出现故障也不会影响其他服务,而且采用这种架构我们可以快速进行迭代开发,提高交付效率。   Authing 就采用了微服务架构,这样可以带来最大的灵活性、可靠性和开发效率。 高可用 高可用是一种面向风险设计,使系统具备控制风险,提供更高的可用性的能力。   从概率学上讲,凡是可能出错的,随着次数的增加,出错将是不可避免的,这时我们就需要预先对各种风险作出评估,通过种种手段抑制避免这些风险,保障服务的可用性。   云原生和微服务虽然很好,具有灵活可拓展等一系列的优点,但想要做到高可用,还需要做很多努力,我们从控制风险、问题追踪、故障解决三个方面来讲: 控制风险 控制风险有四大因素:减少风险数量:从源头上减少风险,比如外面下雨你不出门,那你就没有被雨淋的风险;降低风险变成故障的概率:比如在任何可能阻塞业务的代码中加入错误冗余处理使其不阻塞其他业务;减少故障的影响范围:把整体业务拆成一个个微服务,某个服务挂掉了,不会影响其他服务的正常运行;缩短故障影响时长:事前做好预警工作、平时做好监控工作、有充分的预案和灾备、事后做好复盘,能自动化的操作尽量自动化,需要人工的操作尽量一键化,比如一键切换、一键回滚、一键扩容等等。   Authing 为了避免风险作出了诸多努力:在测试前会使用 Sonar 等工具检查代码质量、每次上线前都会进行多轮的冒烟测试、对于线上还会有定时的自动化测试脚本,一旦某个环节出了问题,就会自动预警以及时修复,等等。 问题追踪 平时要做好监控,发现问题才好追踪。对于云原生应用来讲,需要保证各个层面都有监控,日志集中管理,出现问题才好随时复盘,还应利用好各种工具来检测服务和集群的各项指标,出现问题前及时预警。   Authing 采用了 prometheus 、 grafana 等工具实时检测服务的各项指标,前端也做了相关埋点工作,并在各个层次和维度上记录了详细的日志统一管理,从开发、提测到上线,每一个节点都有记录了明细的相关文档可以追踪,这样可以保证及时预警避免事故发生,即便出了事故也可以快速定位修复问题。 故障解决 即便做了这样或那样的努力,有时候还是无法避免故障的发生,这时候就要尽快解决问题。在平时做了充分监控和记录的前提下,查阅日志和监控记录,复线问题,定位代码以找到错误并修复问题的速度就至关重要了。   Authing 采用了微服务架构,当问题出现时我们可以快速定位哪个模块出了问题,根据已有的日志和监控,快速定位、复现问题并解决问题,事后通过复盘避免类似事故的再次发生。   Authing 作为 SaaS 产品一直致力于提高自己的可用性,给客户更好的体验,我们会不断优化自己的架构,不断实践,不断进步。  
案例分享 | Authing 身份供应方案助力 PingCAP 实现 40 多个应用的单点登录和组织管理
随着企业数字化转型的高速进程,企业在发展进程中不断引入软件应用、IT 设备等搭建企业基础设施,来实现数字化管理,减少企业支出成本、提升管理运营效率。而在这一进程中,企业数字化系统建设体量越来越大,随之带来的应用软件账号管理、员工身份授权管理、老旧应用集成管理等问题,为企业 IT 部门和运维管理部门带来了极大的挑战。   在此环境下,Authing 身份供应/同步中心能基于第三方应用/ AD 中获取组织架构和账户信息,以及从 IDaaS 同步组织架构和账户信息到第三方应用/ AD 的配置、管理、审计中心,极大节省用户数据跨应用管理的成本,用户信息的维护成本和用户信息可流动性的管理。 01 Authing 身份供应/同步中心方案 Authing 与应用系统之间以 SCIM / LDAP 方式建立通信。   数据通过同步引擎、字段映射,基于 SCIM 与 LDAP 协议实现应用系统之间用户数据的同步。同步的成功和失败都会记录详细的网络日志,方便管理员随时查看任务信息,掌握同步进度和情况。   同步功能还提供定时任务机制,实现自动化数据同步的能力。想要构建同步机制,只需在同步中心选择身份源或者选择下游身份接收者(应用),配置映射同步的字段,设置好定时任务,点击开始,系统就会自动的进行用户信息增删改查的同步任务。     字段映射能力   Authing 的同步中心,采用极简的设置解决了复杂的员工身份同步管理问题,实现组织的同步和信息的同步。     02 案例分享 PingCAP 是一家企业级开源分布式数据库厂商,提供包括开源分布式数据库产品、解决方案与咨询、技术支持与培训认证服务。   由 PingCAP 创立的分布式关系型数据库 TiDB,为企业关键业务打造,具备「分布式强一致性事务、在线弹性水平扩展、故障自恢复的高可用、跨数据中心多活」等企业级核心特性,帮助企业最大化发挥数据价值,充分释放企业增长空间。   需求挑战:   • PingCAP 在长达 3 年的时间里一直存在多个员工身份源,在公司组织机构、跨平台的管理上存在难点,包括飞书,北森,Google 等接近 40 个应用之间的单点登录、协同办公和组织的管理需求。   • PingCAP 在国内、海外多个国家都有办公室,怎样做好各国员工身份管理,降低身份管理和运营成本是现阶段亟待解决的问题。   • PingCAP 希望可以通过北森 HR 系统作为企业统一身份源,进行海内外员工入职、单点登录、协同办公(项目组管理)、离职等自动化管理,能够搭建一个身份中台,管理和同步员工信息、组织机构,并可扩展到下游应用中,减少身份重复产研建设。   解决方案:   • 单点登录:基于 OIDC、SAML 协议,Authing 帮助 PingCAP 对接现有全部应用,Authing 的身份供应帮助 PingCAP 实现 单点登录 SSO 的功能,实现使用一个账号登录企业所有应用。   • 身份供给/同步中心:基于 SCIM、LDAP 协议实现组织机构供给能和 Authing 身份供给能力,实现 PingCAP 员工身份上下游同步供给的能力,可扩展高可用。   • 全球化部署:Authing 通过全球化部署方案,在中国区、美国区,分别部署两个业务中心。在中国区创建一个数据中心,通过外部读写一致的能力,保证了整体数据安全。   • Authing 对员工入离职管理和信息同步的产品能力,帮助 PingCAP 大大降低了运维时间和成本。   客户评价:   高科技创新的产品,灵活敏捷,响应速度快。没想到我们 40 多个应用的单点登录、协同办公和基于身份供应的上下游需求,用 Authing 产品很快就帮我们实现了需求。
Authing 与飞连达成全面合作,携手开创企业数据安全新格局
今年 7 月,字节跳动旗下智能科技品牌火山引擎宣布推出“飞连”正式版,这是集虚拟专用网络、办公网络管控、终端管控、网络准入、防病毒等功能为一体的数字化办公平台,能够帮助员工安全连接企业网络、设备和办公应用。   近期,Authing 与飞连达成全面合作。   01 飞连全面支持 Authing 登录 随着企业数字化转型的不断深化,远程办公 & 运维、移动办公逐渐成为新常态。受疫情影响,企业办公方式在也不断改变,边界不断扩大,复杂的办公环境也为企业带来了诸多挑战。   Authing 是国内首款以开发者为中心的全场景身份云产品,集成了所有主流身份认证协议,为企业和开发者提供完善的、安全的用户认证和访问管理服务。Authing 致力于以身份为中心,在所有 SaaS 软件和用户中建立身份共享的社会性基础设施,帮助企业构建安全的现代 IT 基础设施,不仅保护公司业务,更重新定义用户体验。   飞连在支持原有企业微信和钉钉身份基础之上,扩展使用 Authing 登录方式,同时还实现了和 Authing 组织部门数据打通。Authing 成为 ToB SaaS 的中立公共身份服务商又进一步。     基于飞连新一代融合办公安全解决方案与 Authing 独特的身份云基础设施实现融合,更加保障企业用户与客户的网络访问安全、灵活、易用、高效的数字化基座。飞连全面支持 Authing 登录,实现网络连接与身份云产品层面的打通,最终全方位保护客户数据安全。另外,通过多端融合及 Authing 产品的自适应多因素认证,Authing 实现一个账号登录所有应用,飞连实现终端安全集约化建设与轻管理,共同保障企业数字化办公动态安全防御体系的建设和落地。     02 生态合作 Authing 完善的统一身份认证体系,覆盖用户账号的全生命周期管理和权限控制结合飞连稳定的办公安全保障能力,发挥各自领域的优势,逐步实现全产品的合作、深度项目合作及品牌市场合作,为用户赋能增值,共建新生态,共拓新领域,实现双方市场共享及资源共享,推动行业企业数字安全转型落地。   Authing CTO 尚斯年表示,以 Authing 目前在数字身份领域已具备的明显优势,率先将 IDaaS 技术、方案和产品在国内推广和落地的企业,客户群和行业分布较广,产品创新力强,场景布局深,与飞连在产品和方案上形成融合,共建工作组,实现全生态的深度合作。   03 最佳实践 Authing -飞连 合作解决方案 远程办公场景 为了更好的支持企业远程办公和保护企业的网络安全,推出虚拟专用网络(VPN)结合统一身份管理方案。既可以避免企业暴露内部服务在互联网上从而被黑客攻击,同时提高企业员工远程办公的效率和访问控制。飞连结合 Authing 打通网络链路来实现统一身份认证体系。 Office 办公场景 可通过 WIFI 准入、终端安全、监控告警、统一身份认证、统一身份授权、用户行为分析、风险引擎管控等能力,来保障办公安全、合规、高可用、可扩展结合为一体的安全身份基础设施。   合作客户案例   PingCAP PingCAP 是一家企业级开源分布式数据库厂商,提供包括开源分布式数据库产品、解决方案与咨询、技术支持与培训认证服务。   结合 Authing 身份能力和飞连新一代融合办公安全解决方案,降低客户沟通成本,一站式解决 PingCAP 40 多个应用的单点登录、协同办公和基于身份供应的上下游需求,以及在用户登录过程中的安全防护问题。   仙工智能 上海仙工智能科技有限公司成立于 2020 年,是一家以智能化软件开发为核心的创新型公司。   Authing 完善的身份认证能力,和对应用的高可复用性,结合飞连的办公网络管控和终端管控机制,快速完成仙工智能对应用的身份集成及外部客户的安全登录管理,这一联合解决方案,创建了无缝的登录体验,提高了企业的安全策略,并大幅降低维护成本。
Authing 入选“卓信大数据计划”成员单位
9 月 10 日,中国信息通信研究院(以下简称“中国信通院”)公布了第三批“卓信大数据计划”成员单位名单,经审核认证,Authing(北京蒸汽记忆科技有限公司)顺利入选。   当前,数据成为国家基础性战略资源、重要生产要素,对于推动经济高质量发展,助力国家治理体系和治理能力现代化具有重要作用。中共中央关于“十四五”规划和二〇三五年远景目标建议明确提出建设网络强国、数字中国,发展数字经济,建立数据安全保护基础制度和标准规范,保障国家数据安全。   随着《数据安全法》以及《个人信息保护法》的正式通过,行业企业对数据安全领域的合规有着强烈的意愿,企业数据安全治理、数据安全保障、数据安全体系建设的重要性不断增强。然而,行业企业仍面临着不会做、不外化、不能用等诸多问题。因此,业内迫切希望行业内推出权威的数据安全治理全要素解决方案。   为促进各行各业更加安全的存储数据、使用数据、共享数据,中国信通院在广泛听取各方意见和建议后,于2021年初正式启动“卓信大数据计划”,旨在通过推出多层次指导措施和基础服务帮助企业提升数据安全能力,推动我国数字经济更加健康、可持续的发展。   Authing 作为国内领先的统一身份认证 IDaaS 服务商,致力于连接全球人与应用,让身份管理变得简单,保护企业数据资产。除了制定相应数据安全保障体系和机制,还积极参与到相关国家标准的应用试点中。此外,Authing 也在通过技术创新与产业合作,不断探索企业的用户认证和访问管理服务,实现企业的身份认证、访问控制、身份治理,响应“十四五”规划和二〇三五年远景目标,促进企业数据安全生态建设。   Authing 的对身份认证安全的重视根植于心,此次入选国家信通院“卓信大数据计划”,也将为 Authing 持续提升数据安全保障能力赋能。   “卓信大数据计划”第三批入选名单如下(排名不分先后):   名单来自“卓信大数据计划”  
还分不清摘要、加密?一文带你辨析密码学中的各种基本概念
你一定听到过这些词:加密、解密,也听过种种说法:   我要用 md5 把密码加密一下 将 base64 字符串进行解密 把 token 进行加密,验证时需要解密   很遗憾,以上的说法都是错误的。那么本文就带领大家一探密码学的究竟。当你说「加密」的时候你究竟想说的是?当你说「解密」的时候,你实际指的是? 编码 首先我们从编码开始。一生二,二生三,三生万物,编码就是「一」。试想一下如何用一个只能存储数字的设备来存储汉字呢?一个很自然的想法是将汉字转化成数字,然后再存起来:   例如:用 1 来表示「一」,用 2 来表示「二」,用 24 来表示「人」...... 将所有汉字映射成一个数字,然后将这些数字存储起来。   需要对编码方式进行事先约定,不然你一个编码,我一个编码,大家谁都听不懂谁说的是什么。 谁让电脑是美国人最先发明的,非常流行普及的编码方案也是人家提出的,让我们看看 ASCII 编码:     所以当你想要将「Good morning」存进电脑里,需要存「47 6f 6f 64 20 6d 6f 72 6e 69 6e 67」(16 进制,篇幅原因不再展开成为二进制)。   那么 base64 是什么?base64 也是一套编码规范,可以将二进制数据映射成可见字符(什么是不可见字符?像空格,换行符,制表符都是不可见的)。应用场景呢,比如你想把一张图片塞到 JSON 格式的数据里面,就要对图片二进制流进行 base64 编码。   所以,以后,作为一个密码学专家,你就要说,我会用 base64 算法编码一下图片文件。   最后一个问题,对信息编码会产生信息损失吗?请读者自己思考一下。 摘要 试想有一个搅拌机,放进去原料,输出果汁。在计算机的世界里,也有这样一个摘要机,输入数据,会输出数据的摘要。常见的摘要算法有 sha1、md5。     可以从摘要值反推输入的信息吗?可以从果汁还原水果吗?熟鸡蛋可以反生吗?摘要的计算是单向的,只能通过输入的信息计算摘要而不能从摘要反推信息。   MD5 算法总会输出一个 128 位二进制数,那么我计算一个电影文件的摘要,我可以通过这个 128 二进制数来还原整个电影吗?显然不能。   摘要算法的另一个特性是对于任意的输入变动,得出的结果是截然不同的。见上图,123456 和 1234567 只差了一个数字,计算出来的摘要值是完全不同的。即使你偷偷剪掉一个电影的一秒钟,计算出的电影摘要值也是完全不同的。   所以这有什么用呢?假设你是电影导演,在电影上映前需要先将剪辑后的作品发给不同的公司进行审核校对,那么你可以偷偷剪掉第一秒,计算一个摘要值,然后发给一个公司;偷偷剪掉第二秒,计算一个摘要值,然后发给第二个公司,以此类推。这样一旦有人将你的作品泄露到网上,你就能够通过摘要值立刻知道是哪家公司泄露出去的!还记得《权力的游戏》最后一季上映前先泄露了四集吗?如果他们使用这种方法,追查起来就可以很方便了。   总结一下摘要的特性:不可逆,失之毫厘,谬以千里。   所以,以后,作为一个密码学专家,你就要说,我要用 MD5 对明文密码做一个摘要然后再存储到数据库。 加密 试想在现实世界里,如果加密传递信息呢?把信息写在纸上,然后把纸装进盒子里,再把盒子锁上,最后把盒子邮寄给接受者。前提是接收者必须有这把锁的钥匙。你需要另寻办法将钥匙给到他。   在计算机的世界里,对称加密算法的原理也是类似。你有一段信息,有一个密钥,你用一段文字作为密钥,对你的信息做数学运算,得到一个结果,然后你把结果发给你的接收方,他用同样的文字作为密钥,对加密结果做数学运算,得到信息的原文。   常见的对称加密方法 AES、DES,本质上都是使用一段文字对原始信息做数学运算,然后将结果发送给接收方。   加密的意义在于,及时信息在传递过程中被黑客截获,他也不知道双方在说什么。       那么对称加密的密钥如何传递呢?另寻办法的方法是什么?非对称加密呼之欲出。非对称加密算法,用于加密和解密的密钥是不同的。也就是说,一段文字用于加密信息,另一段文字用于解密加密的结果。 公钥 在数学上,公钥就是两个数字(e,n)。e 一般取 65537,n = p * q(p 、q 为质数)。公钥用于加密。 私钥 在数学上,私钥就是两个数字(d,n)。d 是 e 对于 ø(n)(欧拉函数)的逆元。私钥用于解密。 公钥与私钥的关系 1. 在数学上没有区别,都是一对数字,取决于将哪一组数字公开。 2. 公钥加密的内容要使用私钥解密;私钥加密的内容要使用公钥解密。 3. 私钥要自己保护好,不得泄露;公钥可以公开在互联网上,任何人都可以用它来加密信息,当然加密内容只有私钥能够解出来。   下面是一次 RSA 加密信息的过程:       Q: 可不可以用私钥加密数据呢?   A: 可以!   Q: 那用公钥解密数据?   A: 是的!   Q: 公钥暴露在网络上,任何人都能解密数据,那加密还有什么意义?   A: 继续往下看! 拓展:上图中要计算每个字符编码的 e 次幂,需要算几次? 签名 先计算信息的摘要值,用私钥对摘要值进行加密,生成的结果叫签名值,签名算法有 RS256。顾名思义,是 RSA + HS256 的组合写法。签名需要分两步走:   计算信息的摘要值 用私钥加密摘要值,得到签名值   验签 利用公钥对签名信息进行验证。拿到一段信息和它的签名值,需要先本地计算信息摘要值,用公钥解密签名值,和计算的信息摘要值进行比对。     还记得公钥和私钥的区别吗?如果我们用私钥对数据加密,任何人都可以用公钥解密加密结果(公钥是公开的),如果解出来的内容是有意义的,那么数据的来源一定是私钥的持有者,如果解出来的内容是乱码,那么数据的来源就不是私钥的持有者。   那么之前对称加密算法的密钥传递问题也解决了,接收方将公钥给发送方,发送方用公钥加密一个密钥,接收方用私钥解密加密后的内容,得到密钥原文。如此一来,钥匙就安全地交给接收方了。   总结一下,如果你想对一段信息签名,先算它的摘要,然后用私钥加密摘要值,这样所有人都可以使用公钥验证它的正确性;如果你想加密传输一段信息,用公钥加密这段信息,这样信息接受者可以用私钥解密加密后的结果。   当你说加密的时候,你实际想说:编码、摘要、加密;当你说解密的时候,你实际想说:编码、解密、验签。
Authing 官方
·
2021-08-26
·
811 人阅读
Authing share | 身份访问管理关乎企业的发展
据报道,美国安全企业曾发现一起重大数据泄露事件,一个属于 One More Lead 的数据库将多达 6300 万的用户信息储存在一个没有保护的数据库中,至少有 6300 万人的身份信息可能被盗,或者被诈骗,甚至更糟。如何进行统一的身份和访问管理,来减少数据泄漏的风险呢。 01 身份信息安全关乎着企业的发展 首先,身份和访问管理,或者简称身份管理 IAM:Identity and Access Managetment,大多数人想到的都是针对企业内部员工、合作伙伴、临时人员等提供统一身份认证和权限管理能力的内部产品(Enterprise Identity & Access Management 或 EIAM)。 然而,随着软件的边界拓展到我们生活的方方面面,统一管理身份的需求也不断拓展边界,以企业为核心,由内而外,企业也开始容纳外部的海量顾客身份,由此诞生了针对互联网用户的顾客身份管理(Customer Identity & Access Management 或 CIAM)。 初始由 Accenture、AWS 等国外服务商率先将 CIAM 作为一个独立的、必须的产品来看待。完全不同于以内部效率为核心的 EIAM 产品,CIAM 的目标是协助企业完成全局的信息化转型,在所有对外服务中统一用户的身份,在以体验为核心的用户争夺战中,为终端用户提供完整的身份自助服务、为不同平台用户提供统一而流畅的使用、注册体验,以此来提高用户的留存、黏性,进一步创造价值,在行业竞争中取得先机。 今天领先的 IDaaS 服务商,都在致力于为企业提供上手即用、安全可拓展的用户管理和认证服务。使用 IDaaS,企业的 IT 研发、运维人员都可以快速管理任何应用、人员或设备的连接。无论是顾客、成员或是合作伙伴,无论是在云上、本地或是在移动设备上,IDaaS 服务商都可以帮助政企的 IT 服务变得更加安全,提高外部的核心业务的上线速度,也提高内部人员的生产力并保持合规性。 当然,企业在做好身份管理的过程中也⾯临着诸多挑战。 比如身份系统重复建设,导致多⽤户⻆⾊和分⽀机构并存,并需要投⼊⼤量运维资源,⽼旧应⽤的集成将⾯临极⼤的改造成本,使企业运营成本直线上升。此外,如果权限管理体系建设不完善,会导致⼤量应⽤系统外部暴露,业务系统技术标准不统⼀,因此安全管理制度和策略难落实,身份管理的难度也会增⼤。而基于边界的传统⽹络安全架构会使得企业数字化转型成为难题。另外,如果多应⽤重复开发身份登录模块,则⽆法复⽤和统⼀⼊⼝,因此导致开发周期长,成本⾼,身份管理难度大。 02 Authing 下⼀代身份云 致力于降低企业开发成本 Authing 基于身份源的用户管理体系,快速集成国内外多应用系统,加速企业研发团队核心系统的研发,减少研发周期。 同时,Authing 节约构建了身份管理系统的成本,并减轻未来维护升级的负担。Authing 的流水线 pipeline 能帮助开发者快速自定义认证流程中的功能改造,极大的降低企业开发成本,提高生产力。解放出的人力可让开发团队专注于核心业务,为企业的创新能力扩展出新空间,同时也可加快产品交付上市的时间。 Authing 可以帮助用户应对以上种种挑战,并摆脱系统结构复杂、耗时耗资、扩展性差等传统身份认证管理(IAM)解决方案的困境,快速实现任何 Web、App 和企业软件的身份认证和用户管理,为客户和员工提供最完善的登录解决方案。 Authing 已帮助上千家企业和开发者构建标准化的用户身份,可帮助企业降低 90% 运维成本,降低 50% 开发⼯时,提升管理和运营效率,统⼀数字身份,刻画更⾼精度的⽤户画像。 Authing 还拥有 700+ 开放接口,支持 RESTful 和 GraphQL,以及 Python、JavaScript、Node、PHP、Java、Swift、Rust 等编程语言和框架,满足 Web、 iOS、 Android 或其他后端各平台的使用需求。Authing 全面支持 Serverless 架构,有和 Serverless 安全兼容的 OIDC 框架,可以实现安全的单点登录和身份认证。多语言、跨平台、直观、友好、丰富的 SDK 支持。 想要进行统一的身份认证管理,快来试用吧!
搭建数据中台|实现用户原生打通
前言 大数据时代,数据成为企业的第一驱动力,数据具有普遍的代表性,能够给企业的机会提供有力的线索,在当前瞬息万变的商业战场上作出最正确,最科学的决策。 有人把数据比作石油,内部存在着无限的能量和财富,孕育而生了数据中台的概念。数据中台则像发电厂一样,将数据挖掘出最有价值的一面,得到源源不断的财富。 01 搭建数据中台的意义 建立数据标准 数据标准是指企业保障数据内外部使用和交换的一致性、准确性,进而制定的规范性约束。 在企业没有数据中台时,企业基本不会有数据标准,即便是有数据标准,也会由于没有数据中台这个实体形态,而无法进行落地执行,那么数据中台的建设就会帮助企业去建立数据标准与规范。 例如数据接入规范、数据存储规范、数据安全规范、数据分析规范等等。 在消费这些数据时又会存在权限、调用等等问题。 这些都是在建立数据中台时应运而生的,形成一套企业级别的内部规范,最终的目的是为业务降低成本,提高效率。 打破数据孤岛 本质上,数据中台就是将杂乱无章的数据,转化成为可以使用、决策的数据生产力。面对海量的数据,数据中台则是可以充分将外部数据融合,结合内部业务的分析,打破数据孤岛的现状,并打造可以持续增值扩张的数据资产,在数据整合后降低了使用数据的门槛,打造了企业内部完整健康的数据生态,实现了数据的价值闭环。 在全球大数据驱动的时代,企业必须通过最真实的数据,了解最真实的客户,在数据支持的条件下不断创新,打破数据孤岛,才能在企业竞争中保持优势。 在当下「生态」的概念愈发火热,但是很多业务的搭建,在最初并未考虑到跨应用分析的场景。 02 场景举例 比如多个应用之间,都有独立的账号体系,在各自的场景下可以很好的完成用户的数据采集,行为追踪,但是一旦希望跨应用追踪用户,做应用生态营销时,经常发现无法对应上是哪个用户,无法串联起用户行为,造成很多有价值的信息流失。 最终在生态建设上,失败于数据的应用隔离、业务隔离,本质上则是数据打通的不彻底,促使企业只能在海量的数据中清洗、Mapping,或者通过改造复杂的接入逻辑,但是成本过高,弥补为时已晚。 Authing 作为数据时代的一把利刃,通过用户身份的打通,从业务的入口打破数据孤岛,让用户在应用之间的行为,实现全链路、全流程的原生打通。   统一身份管理 接入进 Authing 的应用,天然实现用户统一,用户的行为在不同的应用内得以串联,打破同一用户多标识造成的数据孤岛,给予业务人员更准确的分析体验。   多种身份源能力 Authing 已支持 微信、Gitlab、飞书等多种社交与企业级第三方登录方式,降低客户改造成本,使用户轻松接入。   统一用户目录管理 Authing 提供的标准用户目录管理,将统一后的用户身份信息进行存储,可成为企业的用户身份仓库,供给上下游业务系统,实现高可用的数据共享。 …… Authing 拥有现代的 IDaaS 身份中台解决方案,助力企业便利地设置条件访问,通过统一身份提高用户安全无缝的访问体验。如果您正在为身份模块的开发而烦恼,不妨使用一下 Authing 的功能。
多因素认证 (MFA) 是防止数据泄露的最佳安全实践方法
据 IBM X-Force 的最新跟踪数据显示,2020 年数据盗窃相比 2019 年增加了 160%。随着云计算、IoT、5G 等技术的深入发展和普及,催生了大量数据泄露事件的发生,同时也给企业敲响了安全警钟。 01 多因素认证是防止数据泄露的最佳安全实践方法 对于企业而言,由于敏感数据泄露而造成的声誉受损威胁有可能对企业及其客户造成重大损害,还可能会导致诉讼和高额的监管罚款,而且还会影响企业的长期发展。 单纯使用用户名和密码来保护用户资料已不再安全,攻击者很容易劫持登录凭据和身份并访问敏感信息。因此,通过实施多因素认证(MFA)为帐户添加额外的安全层,成为企业防止数据泄露的最佳安全实践方法。 多因素认证(MFA)是一种非常简单的安全实践方法,它能够在用户名称和密码之外再额外增加一层保护。启用多因素认证后,用户进行操作时,除了需要提供用户名和密码外(第一次身份验证),还需要进行第二次身份验证,多因素身份认证结合起来将为你的帐号和资源提供更高的安全保护。 多因素身份验证(MFA)是为了验证一项交易的合理性而实行多种身份验证,其目的是建立一个多层次的防御,使没有被授权之人访问计算机系统或网络更难。多因素身份验证是由2个或3个独立的凭证进行验证,这些凭证主要有以下三个要素:   所知道的内容:用户当前已经记忆的内容,最常见的如用户名密码等; 所拥有的物品:用户拥有的身份认证证明,最常见的方式有 ID 卡、U盾、磁卡等; 所具备的特征:用户自身生物唯一特征,如用户的指纹、虹膜等。 02 功能强大的 Authing 多因素认证 通过对数据安全监管等技术的研究,Authing 提升了针对违法数据流动等安全隐患的监测发现与处理能力,采用全局多因素认证( MFA)提升整体的安全性。Authing 多因素认证可赋能 Authing 应用快速启用多因素认证(MFA),即刻提升应用认证与访问安全等级。 Authing 可提供多种认证方式,提高企业身份安全性,包括手机令牌、短信/邮箱验证码、兼容第三方身份验证器、生物识别、图形锁、小程序认证等。   Authing 多因素认证具有以下核心功能: 通过多种认证方式,保障业务安全; 认证流程自定义,一键开启,操作简单; 支持设备环境数据上报,多维度分析安全级别; 支持配置策略,实现环境风险自适应;   同时适用于应用内权限控制场景;   默认集成于通用登录组件(Guard); 用户数据管理、行为日志查询; 提供 SDK 与开放接口,助力开发者快速调用相关能力,并构建自定义的用户管理页面。   Authing 多因素认证具备多种优势:   开发者友好:提供开箱即用的端 SDK,方便端上开发者快速实现 MFA。 定制数据上报:定制数据上报,参与流程发起决策,覆盖更加复杂精细化场景。 基于策略:多因素认证的触发条件基于自定义策略,策略系统简单、高效、完备、灵活。 配置简单:基于友好的用户界面,快速配置具体应用的多因素认证。   03 更加灵活智能的自适应多因素认证 自适应多因素认证较于传统多因素认证,能够根据当前安全状况,选择应用不同的 MFA 方式,在保障安全的同时也兼顾用户体验。自适应多因素认证提供了更加灵活和智能的验证策略。 在用户进行认证流程时,自适应多因素认证对当前登录的用户生成的多种关键要素:   用户属性: 例如用户名、密码、用户身份等用户自身的属性和信息; 位置感知: 位置感知分为虚拟位置(IP 地址)和物理位置(国家、地区等); 请求来源: 对当前用户的请求来源进行判断,如:硬件设备信息、用户当前所在的系统等; 生物识别: 使用用户的生物信息进行识别,如:指纹信息、人脸识别等; 行为分析: 是否来自常用的登录地点、是否多次输入错误密码、用户之前的操作记录等一系列用户行为。   ……    
Authing x 元气森林 :打通内部应用系统,打造云上身份管理新生产力
客户介绍 元气森林成立于 2016 年,是自主研发、自主设计的创新型饮品品牌。仅短短 5 年时间,在无糖软饮市场上拔得头筹,荣登《第一财经》金字招牌碳酸饮料榜榜首,业务不仅覆盖全国,还出口美国、新西兰、新加坡等 40 多个国家和地区。 目前,元气森林员工数千人,但规模扩展快,市场竞争激烈,以业务为中心的 IT 管理,迫切需要更加具备弹性、可扩展性,以随时适应未来的商业变化。 需求挑战 01 “从分散到统一” 云端单点登录解决方案 元气森林意识到,传统的身份系统难以解决不断扩容的问题,并且身份分散在各个应用间,如何统一管理内部用户的角色和权限,与身份体系打通,是目前运维人员管理的难点。 元气森林通过对接 Authing API,快速创建了一站式的团队应用平台,通过集成系统,快速导入组织架构和所有成员数据,减少了因身份分散带来的安全漏洞风险,没有繁琐的、额外的开发设计,缩减了 80% 的研发时间和成本。 单点登录不仅为员工提供了更好的登录体验,释放了灵活的劳动力,还增强了安全防护能力,对任何组织来说都是双赢的。  02 “从复杂到智能” 自动化生命周期管理解决方案 Authing 以身份为中心,为元气森林构建适应未来的用户管理体系和安全访问控制策略。自动化生命周期管理解决方案,可以智能实时地控制用户的不同访问权限。 将 SSO 与自动化生命周期管理配对,一方面用户可以通过单一的身份验证体验无缝访问他们的所有应用程序,进一步降低弱密码实践带来的风险。另一方面集中式身份管理,可以有效的实时监测,极大的提高对威胁响应的速度。 结语 Authing 提供的高扩展性基础架构,可以满足未来元气森林物联网设备、应用系统,以及劳动力不断扩大数十倍的需求,有效的应对整个环境的不确定性,助力其可持续的提高生产效率。 客户评价 Authing 为我们提供了身份源能力,快速的部署及开发者友好,满足了我们现有和未来的需求,为我们节省了大量的研发人力、费用和周期,让我们将这些宝贵的资源更多应用在公司和客户上。我们很赞赏 Authing 平台遵循开放标准,并具备广泛的功能,使我们的研发人员更容易对接系统。
Authing 官方
·
2021-08-17
·
828 人阅读
用 Canvas 写游戏实录|Authing 开发者活动分享
撰稿人:Authing 邓家旺 我想先和大家从一个非常有趣的游戏说起:康威生命游戏。这是一种相当独特的无人游戏,它几乎全程不需要玩家参与,只需要布好初始的图像,就可以静静地观察游戏运行,如果我们能根据规则,找到规律,就会发现游戏中的网格可以组成各种复杂的结构。 例如在游戏中,有一种结构叫做高斯帕滑翔机,每四个回合向右下方平移一格:     或者是轻型飞船,可以在4个回合向右移动两格,是生命游戏里最快的运动速度,可以理解为这个世界的“光速”。     除了平移运动,甚至还可以创造出更加复杂的繁殖结构:高斯帕滑翔机枪,每14个回合就发射一架高斯帕滑翔机。     更不可思议的是,你甚至可以递归地用生命游戏来模拟另一个生命游戏,进而创造无穷巨大的结构。这个游戏非常有意思,我们研究一下「生命游戏」在程序上是如何写出来的。 这个游戏本身很简单,本质上是两件事: 1.画格子,默认白色,允许用户操作绘制黑色(有生命)2.根据规则,自动计算下一回合的格子状态,让格子自动刷新 所以我们要先做的第一件事是画格子,画格子有两种思路。 第一种是绘制线条,让线条在视觉上组成网格:   第二种是根据四个顶点连线,直接画「格子」:     稍作分析,会发现这个游戏基本不会对“线”有改动,所以我们就按第二个方案来绘制格子,这样我们就可以很方便地拿到格子的坐标,标记它的生命也非常简单,布尔值就行。 实现这个游戏在程序上要怎么做,我们需要思考几个问题: 1.怎么用程序实现矩形、多个矩形2.怎么用程序计算下一回合的数值3.怎么用程序根据数值,绘制新一轮的图像4.最好能响应用户操作,交互(可以绑定用户的交互操作) 我们用最简单的 html + css + js 来实现,不用依赖任何库就可以做到这件事,事情分成几个阶段做,第一阶段最简单,画 1 个格子。   <canvas id="id-canvas" width="800" height="600"></canvas> <script> const domCanvas = document.querySelector('#id-canvas') const context = domCanvas.getContext('2d') context.fillRect(100, 100, 40, 40) </script>   只要能看到最基本的一个格子,就说明绘图是 OK 的。我们继续第二阶段:画很多格子。   const domCanvas = document.querySelector('#id-canvas') const context = domCanvas.getContext('2d') let { width, height } = domCanvas let grids = initData(width, height, 40) for (let i of grids) { context.strokeStyle = 'rgba(0, 0, 0, 1)' context.strokeRect(i.x, i.y, 40, 40) } // initData 不是重点,返回值是格子数组,结构大致如下 [ { row: number, col: number, x: number, y: number, life: boolean, }, ...... ]   由于画很多格子需要在视觉上可辨认,所以我们就不填充格子了,而是画格子的边框,然后来一个 for 循环即可,这一步也很简单。 我们继续第三阶段:让 1 个格子运动起来。   let x = 100 let y = 100 let fps = 30 setInterval(() => { let { width, height } = domCanvas let gridLength = 40 context.clearRect(0, 0, width, height) if (x < width - gridLength) { context.fillRect((x += 10), y, gridLength, gridLength) } else { context.fillRect(x, y, gridLength, gridLength) } }, 1000 / fps)   这里的 fps 是指每秒刷新多少次,我们称为 “帧”。可以看到,格子每帧向右移动 10 个像素,并在碰到边界时停下。如果我们能让一个格子按我们所想的方式动起来,那么就能让所有格子都如此。 第四阶段:让所有格子动起来,闪烁。   let gridLength = 40 let { width, height } = domCanvas let grids = initData(width, height, gridLength) let fps = 2 setInterval(() => { context.clearRect(0, 0, width, height) for (let i of grids) { i.life = Math.random() > 0.5 if (i.life === true) { context.fillStyle = 'gray' // 稍微灰色一点会让眼睛舒服些 context.fillRect(i.x, i.y, gridLength, gridLength) } else { context.strokeStyle = 'gray' context.strokeRect(i.x, i.y, gridLength, gridLength) } } }, 1000 / fps)   随机操作所有格子填充灰色或不填充,就已经做到了“让所有格子动起来”。 最后,第五阶段,让格子根据规则运动。   // 先说明一下规则: // 如果一个生命周围的生命少于 2 个,它在回合结束时死亡。 // 如果一个生命周围的生命超过 3 个,它在回合结束时死亡。 // 如果一个死格子周围有 3 个生命,它在回合结束时获得生命。 // 如果一个生命周围有 2 个或 3 个生命,它在回合结束时保持原样。 let gridLength = 40 let { width, height } = domCanvas let grids = initData(width, height, gridLength) let fps = 10 addGosper(grids, 2, 2) window.grids = grids setInterval(() => { context.clearRect(0, 0, width, height) let gridsCopyed = JSON.parse(JSON.stringify(window.grids)) for (let i of gridsCopyed) { if (i.life === true) { context.fillStyle = 'gray' context.fillRect(i.x, i.y, gridLength, gridLength) } else { context.strokeStyle = 'gray' context.strokeRect(i.x, i.y, gridLength, gridLength) } let nextLife = getNextRoundLife(i) i.life = nextLife } window.grids = gridsCopyed }, 1000 / fps) // initData 前面已经说明过了 // addGosper 就是提前标记其中几个格子为存活状态 // getNextRoundLife 见下面的实现,本质上是计算各格子周围的生命数量决定下回合状态 const getGridLife = (row, col) => { // 检查这个格子的生命状态 if (!window.grids) { return false } let grid = grids.find((i) => i.row === row && i.col === col) return grid ? grid.life : false } const getNextRoundLife = (grid) => { let lifeAround = 0 let { row, col } = grid // 上面三个 lifeAround += getGridLife(row - 1, col - 1) lifeAround += getGridLife(row, col - 1) lifeAround += getGridLife(row + 1, col - 1) // 左右两个 lifeAround += getGridLife(row - 1, col) lifeAround += getGridLife(row + 1, col) // 下面三个 lifeAround += getGridLife(row - 1, col + 1) lifeAround += getGridLife(row, col + 1) lifeAround += getGridLife(row + 1, col + 1) if (grid.life === false) { if (lifeAround === 3) { return true } } if (grid.life === true) { if (lifeAround === 2 || lifeAround === 3) { return true } } return false }   目前为止,我们已经成功让游戏实现了,如果我们接着加入 Event 事件,加入细节优化,比如帧率调整、格子大小调整、颜色、这个游戏就可以直接玩了。 但是还不行!目前这份代码问题太大: · 使用了全局 window 对象,这不好,一旦添加功能容易炸。 · 我们用的 setInterval API 其实并不能动态改变帧率,比较好的方式是两种:用 settimeout 递归、用 requestAnimationFrame 递归,并且也不应该自己管理这个绘制,应该托管起来。 · 我们的绘制、更新操作都是手动的,这会增加很多开发成本,一旦对象多起来,场景丰富起来,就会要写非常多的代码来负责绘制,不容易做抽象,也不容易修改维护。 · 格子生命的判定和绘图的逻辑不应该混合到一起,它们一个是数据状态,一个是绘图操作,应该拆分开。 · 我们没有把“格子”这个物体单独抽象出来,这不好。   要处理这些问题,我们需要换一个思维方式。在编程上采取更好的实现,将代码组织好,进一步设计自动刷新的模型,让程序接管更多人手动操作的部分。     const __main_v2 = () => { let domCanvas = document.querySelector('canvas') let context = domCanvas.getContext('2d') // 1,场景初始化,托管 canvas 和 context // 托管自动刷新渲染的 rendering let scene = new Scene() scene.registerCanvas({ canvas: domCanvas, context: context, }) scene.registerContinuousRendering() scene.setFps(2) // 2,抽离一个单独的 Life 物体(组件),自己负责自己的逻辑工作 let lifeGame = new LifeGame(context) scene.registerObject(lifeGame) }   理论上,和“整个游戏场景”有关的代码就只有这些:获取上下文、初始化场景、为场景添加物体。 至于物体到了场景里具体如何表现,只需要我们提前写好物体即可,换句话说,说这和场景本身是分离的。那么来看看和场景无关的 LifeGame 的实现:   class Grid { constructor(row, col, x, y, life) { this.row = row this.col = col this.x = x this.y = y this.life = life ? life : false } } class LifeGame { constructor(context = null, config = {}) { this.context = context ? context : null // life game 需要有很多属性,比如自己的初始化格子树 this.gridLength = config.gridLength ? config.gridLength : 40 this.containerWidth = config.width ? config.width : 800 this.containerHeight = config.height ? config.height : 600 this.grids = this.initGrids() // 手动添加一架高斯帕滑翔机,当然也可以不添加 this.addGosper(2, 2) } copyGrids() { return JSON.parse(JSON.stringify(this.grids)) } addGosper(startRow, startCol) { let { grids } = this let start = grids.find((i) => i.row === startRow && i.col === startCol) start.life = true let g2 = grids.find((i) => i.row === startRow + 1 && i.col === startCol + 1) g2.life = true let g3 = grids.find((i) => i.row === startRow + 2 && i.col === startCol + 1) g3.life = true let g4 = grids.find((i) => i.row === startRow + 0 && i.col === startCol + 2) g4.life = true let g5 = grids.find((i) => i.row === startRow + 1 && i.col === startCol + 2) g5.life = true } initGrids = () => { let { containerWidth, containerHeight, gridLength } = this let xLen = containerWidth / gridLength let yLen = containerHeight / gridLength let grids = [] for (let i = 0; i < xLen; i++) { let row = [] for (let j = 0; j < yLen; j++) { let g = new Grid(i, j, i * gridLength, j * gridLength, false) row.push(g) } grids.push(row) } return grids.flat(Infinity) } getNextRoundLife(grid) { let lifeAround = 0 let { row, col } = grid lifeAround += this.getGridLife(row - 1, col - 1) lifeAround += this.getGridLife(row, col - 1) lifeAround += this.getGridLife(row + 1, col - 1) lifeAround += this.getGridLife(row - 1, col) lifeAround += this.getGridLife(row + 1, col) lifeAround += this.getGridLife(row - 1, col + 1) lifeAround += this.getGridLife(row, col + 1) lifeAround += this.getGridLife(row + 1, col + 1) if (grid.life === false) { if (lifeAround === 3) { return true } } if (grid.life === true) { if (lifeAround === 2 || lifeAround === 3) { return true } } return false } getGridLife(row, col) { let grid = this.grids.find((i) => i.row === row && i.col === col) return grid && grid.life ? 1 : 0 } update() { let gs = this.copyGrids() gs.forEach((g) => { let nextLife = this.getNextRoundLife(g) g.life = nextLife }) this.grids = gs } draw() { if (!this.context) { return } const { context, grids, gridLength } = this for (let i of grids) { if (i.life === true) { context.fillStyle = 'black' context.fillRect(i.x, i.y, gridLength, gridLength) } else { context.strokeStyle = 'black' context.strokeRect(i.x, i.y, gridLength, gridLength) } } } }   目前的组织方式是使用了一个 Scene 对象,Scene 对象提供了注册上下文的方法,提供了自动渲染,并且允许添加物体,交给 Scene 来处理。 我们在外部层面不再关心物体是如何被画出来的,我们只知道造出一个符合标准的“物体”,然后添加到场景里,它就一定会被画出来。   class Scene { constructor() { this.fps = 10 this.pause = false this.canvas = null this.context = null this.objects = [] // 所有物体 } registerCanvas(props) { this.canvas = props.canvas this.context = props.context } registerContinuousRendering() { let { canvas, context } = this setTimeout(() => { if (this.pause == true) { return } context.clearRect(0, 0, canvas.width, canvas.height) this.update() this.draw() this.registerContinuousRendering() }, 1000 / this.fps) } registerObject(obj) { this.objects.push(obj) } setFps(fps){ this.fps = fps } update() { for (let i of this.objects) { i.update() } } draw() { for (let i of this.objects) { i.draw() } } }   我们造出来的标准物体就是 LifeGame,它非常简单,其他方法我都是拷贝的 V1 版本,只有一个地方有区别,数据更新和绘制的逻辑被拆分开,变成了两个方法:update 和 draw,只要有这两个方法,他们就会被 scene 自动处理。因此,我们专心在这两个方法里决定好自己被画成什么样就行了。 最终游戏看起来像这样:我们提前添加一架滑翔机,然后让程序自动运行就好。     生命游戏很简单,我们讲到这里,如果我们运用上这个思路,只需要不停地往场景里添加物体,就很容易做出来一个真正的游戏,例如看下面这段伪代码做的事:   let scene = new Scene() scene.registerContinuousRendering() scene.setFps(2) let cloud = new Cloud() cloud.x -= random(0, 10) // 0-10 之间随机一个数字 scene.registerObject(cloud) let monster = new Monster() monster.hp = 100 scene.registerObject(monster) let hero = new Hero() hero.attack = 25 hero.hp = 10 scene.registerObject(hero) scene.registerEventsPressKey('j', () => { hero.jump() }) scene.registerEventsPressKey('i', () => { hero.chop() })   这就构建出了一个有背景(云朵)、有怪物(和生命值)、有主角的游戏,并且通过绑定键盘事件,在按下 “j” 的时候会跳跃,在按下 “i” 的时候会挥剑攻击的游戏。 只要我们提前写好 Cloud, Monster, Hero 对象,我们就可以在业务层很简单地做到这些事。这就让游戏可以完全按照我们的兴趣被创造。 本文根据 Authing 开发者活动的演讲内容整理,有兴趣的读者可以尝试一下,最后祝大家周末愉快~
Authing 官方
·
2021-08-13
·
719 人阅读