开放平台设计方案与实践
欢迎大家关注我的微信公众号【 老周聊架构 】,Java后端主流技术栈的原理、源码分析、架构以及各种互联网高并发、高性能、高可用的解决方案。 一、背景
随着业务的发展,越来越多的系统需要数据往来。那对外提供的接口也越来越多,而且各个接口散落在不同的项目中被调用,多了的话排查问题困难且混乱。基于这个痛点,我们有必要打造一套开放平台来管理各个 api 的调用情况。二、开放平台设计
我们先从整体的功能需求来分析,主要有以下几点:开发者身份注册与数据权限范围授权开发者获取相关资料(接口文档、使用说明、对接人联系方式等)平台方接入管理,申请审核流程、服务配置、服务管理、参数配置等平台方运营管理,业务交易管理及统计报表分析安全层面需求,加密、应用秘钥、应用接口权限控制、访问黑白名单、字段脱敏还原等性能方面要求,客户端缓存、服务端缓存、缓存等
这里老周给出自己的一个架构,大家可以参考下:
上面的设计方案更多的是针对比较大型的公司,想要把整个开平的能力建设完善。但市场上更多的是中小型公司,它们没有太多的人力去开发与建设这么全面的开放平台。
那如果是中小型公司,那它们的开放平台如何不费很大精力去实现呢?不管中小型还是大型公司的开放平台,上面说的那个图中其它部分可以省略,但安全机制是必需的,也就是架构图中的统一鉴权。试想一下,作为提供给第三方调用接口的开放平台,如果安全机制不能保障,那外部谁都可以来调用你们公司的内部资源,危害可想而知。
老周下面就来针对不同的业务场景来给出相应的开放平台安全机制的保障,也就是根据不同类型的网站给出相对应的开放平台设计方案。三、小型网站
3.1 基于 session 的登录认证
在传统的用户登录认证中,因为 http 是无状态的,所以都是采用 session 方式。用户登录成功,服务端会保存一个 session,当然会给客户端一个 sessionId,客户端会把 sessionId 保存在 cookie 中,每次请求都会携带这个 sessionId。服务器收到 sessionId,找到前期保存的数据,由此得知用户的身份。
对于小型网站,特别是单机系统,基于 session 的登录认证方案已经够用了,而且简单高效。四、中型网站
随着用户量的增多,上面基于 cookie + session 的这种模式缺点就显现出来了,这种模式通常是保存在内存中,而且服务从单服务到多服务会面临 session 共享问题,开销也随即越来越大。
那中型网站的安全认证机制是啥呢?接下来 JWT(JSON Web Token) 即将登场,关于 JWT 的概念与原理,老周这里觉得还是有必要说一下。
4.1 JWT 的概念
4.1.1 什么是 JWT?
JWT 是一个开放的行业标准(RFC 7519),它定义了一种简洁的、自包含的协议格式,用于在通信双方传递 json 对象,传递的信息经过数字签名可以被验证和信任。JWT 可以使用 HMAC 算法或使用 RSA的公钥/私钥对来签名,防止被篡改。
说白了 JWT 就是一套基于 token 的身份认证的方案,可以保证安全传输的前提下传送一些基本的信息,以减轻对外部存储的依赖,减少了分布式组件的依赖,减少了硬件的资源。
可实现无状态、分布式的 Web 应用授权,JWT 的安全特性保证了 token 的不可伪造和不可篡改。
本质上是一个独立的身份验证令牌,可以包含用户标识、用户角色和权限等信息,以及您可以存储任何其他信息(自包含)。任何人都可以轻松读取和解析,并使用密钥来验证真实性。
4.1.2 JWT 令牌结构
JWT 令牌由三部分组成,每部分中间使用点(.)分隔,比如:xxxxx.yyyyy.zzzzzHeader
头部包括令牌的类型(即JWT)及使用的哈希算法(如HMAC SHA256或RSA),例如:
{
"alg" : "HS256" ,
"typ" : "JWT"
}
将上边的内容使用 Base64Url 编码,得到一个字符串就是 JWT 令牌的第一部分。Payload
第二部分是负载,内容也是一个 json 对象,它是存放有效信息的地方,它可以存放 jwt 提供的现成字段,比如:iss(签发者),exp(过期时间戳),sub(面向的用户)等,也可自定义字段。 此部分不建议存放敏感信息,因为此部分可以解码还原原始内容。 最后将第二部分负载使用 Base64Url 编码,得到一个字符串就是 JWT 令牌的第二部分。 一个例子:
{
"sub" : "1234567890" ,
"name" : "微信公众号【老周料架构】" ,
"iat" : 1516239022
}Signature
第三部分是签名,此部分用于防止 jwt 内容被篡改。 这个部分使用 base64url 将前两部分进行编码,编码后使用点(.)连接组成字符串,最后使用 header 中声明签名算法进行签名。
secret:签名所使用的密钥。
HMACSHA256 (
base64UrlEncode(header) + "." + base64UrlEncode(payload), secret
)
验签过程描述:获取 token 值,读取 Header 部分并 Base64 解码,得到签名算法。根据以上方法算出签名,如果签名信息不一致,说明是非法的。
4.2 JWT 的流程
4.3 JWT 代码案例
如果你们公司有第三方应用接入的开放平台,那可以在里面走相应的接入流程得到 appId 和 appSecret。如果没有的话,那可以简单点与第三方约定相应的 appId 和 appSecret。老周这里假设你们已经约定好了,我这里直接放在请求头里来获取 token,还有其它的方式,比如放在请求参数或者 cookie 里。
4.3.1 maven 依赖 com.auth0 java-jwt 3.4.1
4.3.2 JWTUtil 工具类public class JWTUtil { private static String SECRETE = "default_secrete"; private static String APP_ID = "zhifubao"; private static String APP_SECRETE = "123abc"; /** * 传入 appId、appSecret 进行验证 * @param appId 应用id * @param appSecret 应用密钥 * @return 返回一个加密 JWT token */ public static String getToken(String appId, String appSecret) { String token = JWT.create() // 存放 payload 数据 .withClaim("appId", appId) .withClaim("appSecret", appSecret) // 使用 SECRETE 对称加密生成 signature .sign(Algorithm.HMAC256(SECRETE)); return token; } /** * 验证 token * @param token * @return */ public static boolean verifyToken(String token) { HashMap map = new HashMap<>(); // 通过 SECRETE 和相同的对称加密算法反加密 DecodedJWT jwt = JWT.require(Algorithm.HMAC256(SECRETE)) .build().verify(token); // 获得你储存的 payload 信息 String appId = jwt.getClaim("appId").asString(); String appSecret = jwt.getClaim("appSecret").asString(); if (APP_ID.equals(appId) && APP_SECRETE.equals(appSecret)) { return true; } return false; } }
4.3.3 JWTController 类@RestController public class JWTController { @RequestMapping("/getToken") public String getToken(@RequestHeader("appId") String appId, @RequestHeader("appSecret") String appSecret) { return JWTUtil.getToken(appId, appSecret); } }
4.3.4 测试
拓展:这个私钥 secrete 是固定的,为了加强安全,你甚至可以使用动态的 secrete 私钥,
例如:动态私钥 = 静态私钥 + 用户的 ip,这样即使别人得到了用户的 token,也会因为 ip 不一致而访问失败。
拿到了应用资源服务器的 token 令牌了,那我们拿这个令牌去访问相应的资源看看。@RequestMapping("/getResource") public String getResource(String resourceId) { return resourceId + " 资源获取成功"; }
简单模拟一个请求,直接返回该资源获取成功。我们接下来就用 postman 工具来模拟一下这个资源服务器的这个接口请求。
认证失败了,这是因为我们没有在请求头里填刚刚获取的 token。我们把通过调用 getToken 接口获取的 token 值放在在请求头,然后认证通过,获取到了资源服务器的资源。
4.3.5 继续追问
这里你有可能问了,老周,这里咋就带上 token 在请求头就可以获取到了资源服务器的资源啊。
我把代码贴出来,你一看就知道了。
这里写了一个 token 的拦截器,对请求头的 token 进行验签,通过才放行。@Component public class TokenInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token = request.getHeader("token"); if (token != null) { boolean result = JWTUtil.verifyToken(token); if (result) { System.out.println("通过拦截器"); return true; } } response.setCharacterEncoding("UTF-8"); response.setContentType("application/json; charset=utf-8"); try{ response.getWriter().append("认证失败,无效的token令牌!"); System.out.println("认证失败,无效的token令牌!"); } catch (Exception e) { e.printStackTrace(); response.sendError(500); return false; } return false; } }
这里有个拦截器配置类,把需要拦截的 api 路径放进来,然后会对某个 api 进行细粒度的管控。@Configuration public class IntercepterConfig implements WebMvcConfigurer { private TokenInterceptor tokenInterceptor; public IntercepterConfig(TokenInterceptor tokenInterceptor){ this.tokenInterceptor = tokenInterceptor; } @Override public void addInterceptors(InterceptorRegistry registry) { List excludePath = new ArrayList<>(); excludePath.add("/getResource/"); excludePath.add("/static/**"); //静态资源 registry.addInterceptor(tokenInterceptor) .addPathPatterns("/**") .excludePathPatterns(excludePath); WebMvcConfigurer.super.addInterceptors(registry); } }
这就实现中型网站安全认证机制了,细心的读者可能会发现,这个 token 是固定的,会存在一些不安全。是的,我上面也说了,可以用动态的 secrete 私钥或者 token 过期机制来继续保证更高的安全性。五、大型网站
大型网站的话,针对中型网站的方案就不太可行了,为什么呢?由于大型网站的请求流量很大,而 token 由于自包含信息,因此一般数据量较大,而且每次请求都需要传递,因此比较占带宽。另外,token 的签名验签操作也会给 cpu 带来额外的处理负担。可以采用微服务统一认证方案 Spring Cloud OAuth2,那什么情况下需要使用 OAuth2?第三方授权登录 的场景:比如,我们经常登录一些网站或者应用的时候,可以选择使用第三方授权登录的方式,比如:微信授权登录、QQ授权登录、微博授权登录等,这是典型的 OAuth2 使用场景。单点登录 的场景:如果项目中有很多微服务或者公司内部有很多服务,可以专⻔做一个认证中心(充当 认证平台⻆色),所有的服务都要到这个认证中心做认证,只做一次登录,就可以在多个授权范围内的服务中自由串行。
5.1 OAuth2 构建微服务统一认证服务思路
注意:在我们统一认证的场景中,Resource Server 其实就是我们的各种受保护的微服务,微服务中的 各种 API 访问接口就是资源,发起 http 请求的浏览器就是 Client 客户端(对应为第三方应用)。
5.1.1 搭建认证服务器(Authorization Server)
5.1.1.1 maven 依赖文件
5.1.1.2 application.yml 文件
5.1.1.3 OauthServerApplication9999 启动类
5.1.1.4 认证服务器配置类
5.1.1.5 认证服务器安全配置类
5.1.1.6 测试
5.1.1.6.1 获取 token
http://localhost:9999/oauth/token?client_secret=abcxyz&grant_type=password&username=admin&password=123456&client_id=client_riemannendpoint:/oauth/token
获取token携带的参数
client_id:客户端id
client_secret:客户单密码
grant_type:指定使用哪种颁发类型,password
username:用户名
password:密码
5.1.1.6.2 校验 token
http://localhost:9999/oauth/check_token?token=28317df7-4036-4bbb-8bb3-12f71fa07802
如果出现以上页面,表明 token 过期了,设置的是 20s。所以要在 20s 以内校验才会生效。
下面才是 token 校验成功的效果:
5.1.1.6.3 刷新 token
http://localhost:9999/oauth/token?grant_type=refresh_token&client_id=client_riemann&client_secret=abcxyz&refresh_token=68582d02-3a1d-4c31-ae22-ac7e84824d0d
5.1.2 搭建资源服务器(希望访问被认证的微服务)
5.1.2.1 资源服务 Resource Server 配置类
5.1.2.2 测试
此测试结果也印证了代码的效果
我们加上带上token测下看看:
5.2 OAuth2 统一认证服务思考当我们第一次登陆之后,认证服务器颁发 token 并将其存储在认证服务器中,后期我们 访问资源服务器时会携带 token,资源服务器会请求认证服务器验证 token 有效性,如果资源服务器有很多,那么认证服务器压力会很大。另外,资源服务器向认证服务器 check_token,获取的也是用户信息 UserInfo,能否把用户信息存储到令牌中,让客户端一直持有这个令牌,令牌的验证也在资源服务器进行,这样避免和认证服务器频繁的交互。我们可以考虑使用 JWT 进行改造,使用 JWT 机制之后资源服务器不需要访问认证服务器。
5.3 JWT 改造统一认证授权中心的令牌存储机制
JWT 在上面中型网站那一节说过了,这里就不重复说了,老周直接上代码了。
5.3.1 认证服务器端 JWT 改造(改造主配置类)
5.3.2 修改 JWT 令牌服务方法
5.3.3 认证服务器端测试
可以看出,使用 jwt 令牌生成的 access_token 和上一篇的不一样。
我们用这个网站:https://jwt.io/#encoded-jwt 把该 access_token 进行解码,解码如下:
其他两个验证 token、刷新 token 跟上一篇类似。
5.3.4 资源服务器校验 JWT 令牌
不需要和远程认证服务器交互,添加本地 tokenStore。
5.3.5 源服务器端测试
这样就完成了资源服务根据事先约定的算法自行完成令牌校验,无需每次都请求认证服务完成授权。六、总结
老周首先从开放平台的整体功能设计来分析了有如下几个要点:开发者认证、开放平台内部管理系统、安全机制以及性能。
但考虑很多公司它们没有太多的人力去开发与建设这么全面的开放平台,故抓住其中的最核心的一点,那就是安全机制。
针对于安全机制来说,不同类型的网站有不同的安全机制保障。小型网站:基于 session 的登录认证,在小型网站特别是单机系统,这种方案够用了,而且简单高效;中型网站:到了中型网站,服务肯定是分布式部署的,这个时候小型网站中基于 session 的登录认证方案的缺点就暴露出来了。每个应用服务都需要在 session 中存储用户身份信息,通过负载均衡将本地的请求分配到另一个应用服务需要将 session 信息带过去,否则会重新认证。我们还要通过 session 共享、session 黏贴等方案来解决。从而引入了第三方分布式组件,比如 redis,增加了系统的复杂性。并且 session 方案还有另一个缺点,比如基于 cookie,移动端不能有效使用等。所以中型网站的话基于 JWT 的 token 认证机制,服务端不用存储认证数据,易维护扩展性强,客户端可以把 token 存在任意地方,并且可以实现 web 和 app 统一认证机制。大型网站:到了大型网站,请求量也随之暴涨,中型网站的 token 认证机制的缺点也逐步暴露出来了,token 由于自包含信息,因此 一般数据量较大,而且每次请求都需要传递,因此比较占带宽。另外,token 的签名验签操作也会给 cpu 带来额外的处理负担。这个时候得采用微服务统一认证方案 Spring Cloud OAuth2,后面我们又对 OAuth2 进行了一些优化,因为大型网站的开平请求流量会很大,资源服务器会请求认证服务器验证 token 有效性,那么认证服务器压力会很大。另外,资源服务器向认证服务器 check_token,获取的也是用户信息 UserInfo,能否把用户信息存储到令牌中,让客户端一直持有这个令牌,令牌的验证也在资源服务器进行,这样避免和认证服务器频繁的交互。所以我们后续使用 JWT 进行改造,使用 JWT 机制之后资源服务器不需要访问认证服务器。性能以及安全机制都得到了有力保障。
看完希望对你有所帮助,有帮助的话,请不要吝啬你的点赞、评论、收藏,毕竟原创不易。 好了,我们下期再见。
红豆集团高质量发展三自六化先锋通用股份顾萃把握新时代机遇抢滩国际化市场公司中泰柬三大基地将通过精准定位资源互补实现联动,加速全球化布局,实现企业的国内国际双循环,打造百亿通用。通用股份党委书记董事长顾萃表示。把握新时代机遇,抢滩国际化市场,通用股份赓
猝不及防!小编一家全阳了猝不及防小编变成小阳人了一家四口全部中招小孩症状挺轻的大人就直接卧床了7岁的大宝,核酸检测阳性12月7日早晨,接到大宝学校通知,要求居家隔离。当时没多想,以为就跟往常一样,过几天就
晚餐要少食多营养?建议中老年人多吃这5样,营养足好消化俗话说得好早餐吃得像皇帝,晚餐吃得要像乞丐。人们往往更重视早餐的营养摄入,晚餐只是随便对付两口,或者干脆过午不食将晚餐省略。但这是古人的生活习惯,天黑他们就会睡觉,睡前不易有饥饿感
岁末消费季,除菌消毒健康类家电成新热点在疫情防控政策持续优化的背景下,国内消费环境发生变化,除菌消毒健康类家电销售较为火爆。今年双十二期间,叠加世界杯足球激战正酣,电视机市场持续热销。近日,苏宁易购数据显示,消毒柜洗碗
2022年国际灾害预警科技与服务创新论坛在成都举行12月11日,作为第二十届中国西部海外高新科技人才洽谈会的分论坛之一,2022年国际灾害预警科技与服务创新论坛在成都举行。论坛由四川大学联合国教科文组织驻华代表处国家预警信息发布中
2022年中国经济观察丨听!这是创新的声音400公里太空轨道T字构型,3个人,6个月。中国空间站正式开启长期有人驻留模式。从几年一发到一年几发,从核心元器件依赖进口到全部实现国产化,从试验性空间实验室到自主产权的空间站,自
中国第一代网红官员伍皓的大V往事伍皓这个名字,年轻一辈尤其是00后网友可能感到很陌生。时下网红官员们流行的直播带货古装出演跨界连麦等互联网活动里,都没有伍皓的身影。12月13日,云南省纪委监委通报伍皓涉嫌严重违法
彩虹岛手游家族系统介绍今天的话跟大家说一下彩虹岛手游家族的一些玩法我们点开家族一眼就可以看到下方有签到,家族商店以及家族任务的,我们打开签到可以看到是有不同价位的奖励,有初级,中级和高级。我们可以看到上
风C亲妈辅助!风系专辅珐露珊培养攻略,抽到即毕业!关注我,获取更多原神相关内容!各位小伙伴们大家好,这里是雨沐!在之前介绍流浪者的文章中,提到了风系辅助珐露珊。珐露珊作为流浪者池子中的UP四星,对于风C有着非常强的辅助能力,在风队
开通在即!今日试乘啦!万众期待乘坐弥蒙高铁乐游红河来源云南日报12月14日上午8时45分,弥蒙高铁试乘列车和谐号从昆明火车站发车,并于11时20分抵达红河站。首波试乘的媒体记者施工单位职工代表纷纷表示,期待与家人好友再次乘坐弥蒙高
董卿离开舞台10个多月,央视保留其名力证未辞职,知情人曝她近况董卿离开舞台10个多月,央视保留其名力证未辞职,知情人曝她近况!对此,你们大家有什么看法?网友1我特喜欢懂卿主持的节目,中国诗词大会,主持的太好了,还有一个节目主持人大赛,邀请懂卿
广州出品从这里走向国际,广府文化发源地如何焕发活力?第3期越秀春到人间,春潮涌动。新春伊始,广东省广州市先后召开高质量发展大会,吹响从春天出发的号角。为进一步凝聚高质量发展社会共识,强信心稳预期聚力量,引导全市上下奋勇争先推动高质量
宝武工会围绕基层工会加强年主线,凝聚员工积极冬练2月23日至24日,宝武工会一届九次全委(扩大)会暨工会主席研修在常熟领导力发展中心举行,会议要求,全面加强基层工会工作,凝聚全员力量助力世界一流伟大企业建设。宝武党委书记董事长陈
讲好湘南故事湘南学院召开学生记者座谈会红网时刻新闻2月25日讯(通讯员王佳摄影陈星蓝)2月23日下午,湘南学院召开学生记者座谈会。希望学校各级媒体平台能互相联动彼此支持,提高宣传力度,实现合作共赢要进一步提高创新意识和
月薪最高30000元!六安发布最新招聘信息六安市人力资源和社会保障局发布人力资源市场2023年春风行动企业用工信息1。安徽格恩半导体有限公司技术员工艺工程师设备工程师管培生本科及以上学历理工类专业优先月薪450011000
驻圣彼得堡总领馆发布增加领事证件接待时间通知中国侨网2月25日电据中国驻圣彼得堡总领事馆网站消息,为进一步满足申办领事证件的实际需求,中国驻圣彼得堡总领馆自2023年3月1日(周三)起继续增加领事证件接待时间,每周一至周五9
事关甲流!疾控部门最新发布央广网哈尔滨2月25日消息(记者庞淼)近日,进入甲流高发期,多地中小学学生出现发烧症状,部分学校因发生甲流或流感而停课。一什么是甲型流感病毒?甲型流感病毒(InfluenzaAvi
日本升第三,伊朗出线在即,中国豪取六连胜,世预赛最新排位男篮世预赛亚洲区F组结束了倒数第二轮,日本96比61大胜伊朗,排名也升至第三,中国71比59击败哈萨克斯坦,收获世预赛六连胜,哈萨克斯坦和伊朗都遭遇了输球,伊朗在领先一个胜场的情况
最新!中基私募50指数周报来了!一市场回顾近期,央行公布了一些重要金融数据1月社会融资规模增量为5。98万亿元人民币,比上年同期少1959亿元。其中,对实体经济发放的人民币贷款增加4。93万亿元,同比多增7308
斯诺克最新世界排名时代更替的时候到了吗?现年48岁的奥沙利文仍然位居世界第一,但本赛季排名赛至今未拿冠军,23年世锦赛之前很可能会让出榜首之位,七五三杰除了马叔本赛季打入过一次决赛之后其余均战绩平平。小钢炮艾伦本赛季非常
西部最新排名!掘金一骑绝尘,卫冕冠军跌至第10,湖人双喜临门北京时间2月24日,NBA常规赛重燃战火,各支球队也将全力以赴,以便能够取得一个好的名次。这次比赛已经全部打完,西部排名也是发生一些改变,最新排名为掘金灰熊国王快船太阳独行侠森林狼
三农主播说北斗种地,非一般的酷眼下,春耕正当时。全国各地田野里的景色真不少!先来看天津,能自动运行的平地机作业一次,不仅整块土地的高低误差不超过两厘米,效率也翻了倍在新疆棉田,农田覆膜机驶过的区域,拉出的农用薄