小皮博客 | Xiaopi's Blog

104-微服务安全设计-用户&服务鉴权

微服务架构下,系统整体的安全性与原有的单体应用结构也有很多差别。我们需要解决服务间的鉴权和认证,同时也要解决对调用者进行认证。

设计原则

  • 无状态: 为了合理保持微服务水平扩展的特性。
  • 客户端无关: 需要设计统一的安全策略来满足不同终端请求。
  • 统一登录: 一次登录,可以在平台各个模块间共享登录状态及信息。
  • 权限控制: 每个组件或者子系统应该有不同的权限控制。

常见的鉴权方案

分布式session

  • 相对于传统单体应用使用的session+中间件(如tomcat)session共享机制,服务的水平扩展受到了极大的制约。一般的优化方案是把session放在跨进程的存储架构中,比如redis。
  • Springcloud同样也可以使用redis做分布式session的存储方案。
  • Spring Session对分布式Session提供了支持,同时也可以与Springboot/SpringCloud无缝集成。

API Tokens

流程

  • Token一般会包含用户的鉴权相关信息,通过在请求当中携带token来传递状态,保证服务本身易于水平扩展。其他微服务可以从token当中提取用户,权限信息完成认证(确定是系统合法用户)和鉴权(确定该用户的角色,权限),而不需要建立客户端对服务器端的session(一般tomcat或者其他容器共享session很麻烦)。

API Token时序图

1. 用户使用包含用户名和密码的credential包从客户端发起资源请求。这里的客户端可以是web的js代码,也可以是android或者ios系统及其他物联网设备。
2. 后端API接收请求后通过授权中心(也有可能是用户中心或者用户微服务),生产出token,返回给客户端。登录及认证流程完成。
3. 客户端获取token后,后续在token失效前都是通过携带此token发起资源请求。
4. 后端验证token的有效性及其权限信息,确认用户合法性及权限,然后调用对应的服务返回给客户端。

### 优点
服务器端无状态,也不存储session,在每个请求里面携带用户信息。 为水平扩展提高了上限。
支持移动端。 支持跨程序,跨域调用。

### 缺点
每次请求都要携带token,与auth服务进行交互验证。 将鉴权的性能压力由原来的每个服务承担,变成了鉴权服务器承担,并且引入了额外的请求资源消耗(但是符合职责分离的原则,便于优化)。

## JWT
### 描述
JSON Web Tokens(JWT)是一种认证协议,基于JSON的开放标准(RFC 7519)。JWT一般被用来在身份提供者和服务提供者之间传递被认证的用户身份信息,便于从服务器端获取资源,也可以增加其他一些额外的其他业务逻辑必须的声明信息。Token可以直接被用于认证,也可以用于加密。

授权服务器将用户信息和授权范围序列化后放入JSON字符串,使用Base64进行编码,然后使用私钥对这个字符串进行签名,得到一个JSON Web Token。 其他所有的资源服务器都应该持有对应RSA公钥,当资源服务器接收到这个在Http Header中存有的token请求,资源服务器就可以拿到这个token,并且verify他们是否用正确的私钥签名的(是否经过授权服务器签名,也就是验签)。验签通过后,反序列化之后就拿到了token中包含的有效验证信息。

### JWT认证流程

JWT认证流程
  • 客户端调用登录接口(或者获取token接口),传入用户名密码。
  • 服务器端请求身份认证中心,确认用户名密码正确。
  • 服务端创建JWT,返回给客户端。
  • 客户端拿到JWT,进行存储(可以存储在缓存中,数据库中,如果是浏览器,存储在cookie中),在后续请求中,在HTTP请求头加上JWT。
  • 服务端校验JWT,校验通过后,返回相关资源和数据。

JWT数据结构


JWT数据结构

header.payload.signature

JWT是由此三段信息的BASE64编码之后通过.连接起来的。

  • 图上的header参数表示类型为JWT,签名算法是RS256
  • payload用来存放有效信息
    • iss: jwt的签发者。
    • sub: jwt所面向的用户。
    • aud: 接收jwt的接收方,比如测试环境用 test-api.domain.io, 生产环境用api.domain.io
    • exp: jwt的过期时间,必须大于签发时间。
    • iat: jwt的签发时间。
    • scope: jwt的唯一身份标志,用来标识token的一次性,避免重放攻击。
    • 还可以定义私有字段。
  • 签名(signature): 使用header及payload进行base65编码,并且使用私钥进行加密。

rsa256.sign(<base64.encode(header)>.<base64.encode(payload)>)

优点

  • 是api tokens的一个标准实现,比自定义方案更加成熟稳定,易于统一规范和共识。
  • 跨语言支持,使用JSON作为标准结构。
  • 基于token,无状态。
  • 占用字节小,便于传输。

token注销方式

  • 由于jwt的校验方式只依赖客户端持有,如果用户显式的注销,可能服务器端还未进行注销状态同步,而各个业务服务器的校验token的方式并不会去集中式的查一下是否合法,而是直接依赖非对称加密算法在业务服务器自身完成。
  • token可以存储在localstorage中,浏览器注销时自然情况。
  • token放在分布式缓存,每次校验时去查一下状态是否已经注销,但这样的话就落入了方式1当中的分布式session的逻辑,失去了快速校验的优点。
  • 过期自动注销,过期时间可以短一些,比如20分钟。现在大部分服务的策略应该是基于此。

范例

参考github.com/sunsetyan/9008-blog-demo/01-jwt.git

OAuth2


OAuth2流程
  • OAuth2是一个跨服务授权(Authorization)的开放网络标准,在业界广泛应用的是2.0版本。
  • 简单来说是客户端应用程序代表用户(得到用户的批准的情况下)去访问受保护的资源。常见的微信授权登录、支付宝小程序授权都是OAuth2的实现方案或者变种。

Spring Cloud Security

  • 包含了Spring Security和Spring Scurity OAuth
  • 基于OAuth2和OPENID协议的可配置SSO登录机制。
  • 基于tokens保证访问安全。
  • 引入UAA(User Account and Authenticaiton)鉴权。

范例

参考github.com/sunsetyan/9008-blog-demo/02-springcloud-security.git

参考文献

https://www.dazhuanlan.com/2019/12/17/5df8295721b81/
https://blog.csdn.net/u013322876/article/details/60139167

版权声明

本文标题:104-微服务安全设计-用户&服务鉴权

文章作者:盛领

发布时间:2020年07月22日 - 03:28:56

原始链接:http://blog.xiaoyuyu.net/post/2270bd06.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

如您有任何商业合作或者授权方面的协商,请给我留言:sunsetxiao@126.com

盛领 wechat
欢迎您扫一扫上面的微信公众号,订阅我的博客!
坚持原创技术分享,您的支持将鼓励我继续创作!