微服务架构下的鉴权,怎么做更优雅?( 二 )

  • 在微服务架构下,每个微服务拆分的粒度会很细,并且不只有用户和微服务打交道,更多还有微服务间的调用 。这个时候上述两个方案都无法满足,就要求必须要将 Session 从应用服务器中剥离出来,存放在外部进行集中管理 。可以是数据库,也可以是分布式缓存,如 Memchached、redis 等 。这正是 David Borsos 建议的第二种方案,分布式 Session 方案 。
  • 基于 Token 的认证随着 Restful API、微服务的兴起,基于 Token 的认证现在已经越来越普遍 。Token 和 Session ID 不同,并非只是一个 key 。Token 一般会包含用户的相关信息,通过验证 Token 就可以完成身份校验 。像 Twitter、微信、QQ、GitHub 等公有服务的 API 都是基于这种方式进行认证的,一些开发框架如 OpenStack、Kubernetes 内部 API 调用也是基于 Token 的认证 。基于 Token 认证的一个典型流程如下:
    微服务架构下的鉴权,怎么做更优雅?

    文章插图
     
    • 用户输入登录信息(或者调用 Token 接口,传入用户信息),发送到身份认证服务进行认证(身份认证服务可以和服务端在一起,也可以分离,看微服务拆分情况了) 。
    • 身份验证服务验证登录信息是否正确,返回接口(一般接口中会包含用户基础信息、权限范围、有效时间等信息),客户端存储接口,可以存储在 Session 或者数据库中 。
    • 用户将 Token 放在 HTTP 请求头中,发起相关 API 调用 。
    • 被调用的微服务,验证 Token 权限 。
    • 服务端返回相关资源和数据 。
    基于 Token 认证的好处如下:
    • 服务端无状态:Token 机制在服务端不需要存储 session 信息,因为 Token 自身包含了所有用户的相关信息 。
    • 性能较好,因为在验证 Token 时不用再去访问数据库或者远程服务进行权限校验,自然可以提升不少性能 。支持移动设备 。
    • 支持跨程序调用,Cookie 是不允许垮域访问的,而 Token 则不存在这个问题 。
    三、JWT 介绍简介JSON Web Token(JWT)是为了在网络应用环境间传递声明而执行的一种基于 JSON 的开放标准(RFC 7519) 。来自 JWT RFC 7519 标准化的摘要说明:JSON Web Token 是一种紧凑的,URL 安全的方式,表示要在双方之间传输的声明 。JWT 一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该 Token 也可直接被用于认证,也可被加密 。
    JWT 认证流程
    • 客户端调用登录接口(或者获取 token 接口),传入用户名密码 。
    • 服务端请求身份认证中心,确认用户名密码正确 。
    • 服务端创建 JWT,返回给客户端 。
    • 客户端拿到 JWT,进行存储(可以存储在缓存中,也可以存储在数据库中,如果是浏览器,可以存储在 Cookie 中)在后续请求中,在 HTTP 请求头中加上 JWT 。
    • 服务端校验 JWT,校验通过后,返回相关资源和数据 。
    JWT 结构JWT 是由三段信息构成的,第一段为头部(Header),第二段为载荷(Payload),第三段为签名(Signature) 。每一段内容都是一个 JSON 对象,将每一段 JSON 对象采用 BASE64 编码,将编码后的内容用 。链接一起就构成了 JWT 字符串 。如下:
    header.payload.signature1. 头部(Header)头部用于描述关于该 JWT 的最基本的信息,例如其类型以及签名所用的算法等 。这也可以被表示成一个 JSON 对象 。
    {"type" :"JWT","ALG" :"HS256"}在头部指明了签名算法是 HS256 算法 。
    2. 载荷(payload)载荷就是存放有效信息的地方 。有效信息包含三个部分:
    • 标准中注册的声明
    • 公共的声明
    • 私有的声明
    标准中注册的声明(建议但不强制使用):
    • iss:JWT 签发者
    • sub:JWT 所面向的用户
    • aud:接收 JWT 的一方
    • exp:JWT 的过期时间,这个过期时间必须要大于签发时间
    • nbf:定义在什么时间之前,该 JWT 都是不可用的
    • iat:JWT 的签发时间
    • jti:JWT 的唯一身份标识,主要用来作为一次性 token, 从而回避重放攻击 。
    公共的声明 :
    • 公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息 。但不建议添加敏感信息,因为该部分在客户端可解密 。
    私有的声明 :