认证与授权(一):OAuth和JWT

1、基础应用

应用的安全主要关注两个方面:认证(Authentication)和授权(Authoriztion),即你是谁,以及你能做什么。在单体应用中,开发者可以通过简单的拦截器以及会话(Session)机制对用户的访问进行控制和记录。而在分布式系统中,由于业务逻辑封装在各个微服务中,每个微服务都需要对用户的行为进行认证和许可,于是就产生了两种可能的方式:

第一种是通过一个中心化的权限管理系统,对用户的身份和权限进行统一的管理,可以做到一次授权,多次多点使用,但是这个独立的安全微服务需要聚合各个微服务中的权限控制逻辑,当添加一个新的基于不同业务逻辑实现的微服务就可能需要在安全微服务中添加新的实现。

第二种是将安全控制分散到各个微服务中,由各个微服务根据自身的业务对用户的访问进行管理和控制。这会导致安全管理过于分散,甚至每个微服务都有自己的一套实现方式,不利于统一管理。

这两种方式各有利弊,如何选择需要根据项目的具体业务需求进行判断,甚至在一定情况下可以结合使用。

Spring Cloud Security提供了一组基本的组件用来构建安全应用程序和服务。它封装了Spring Securtiy、Spring Security OAuth2和Spring Security JWT的相关实现,同时提供自带的安全特性,致力于为Spring Cloud微服务提供快速创建常用安全模式的能力。

2、OAuth2简介

OAuth协议的目的是为用户资源的授权提供一个安全的、开放而简易的标准。

2.1、角色

OAuth2中主要分为了4种角色:
Resource Owner(资源所有者),是能够对受保护的资源授予访问权限的实体,可以是一个用户,这时会称为终端用户(end-user)。

Resource Server(资源服务器),持有受保护的资源,允许持有访问令牌(Access Token)的请求访问受保护资源。

Client(客户端),持有资源所有者的授权,代表资源所有者对受保护资源进行访问。

Authorization Server(授权服务器),对资源所有者的授权进行认证,成功后向客户端发送访问令牌。

2.2、协议流程

OAuth2的认证流程如图所示:


Oauth认证流程.jpg
  1. 客户端(浏览器)请求资源所有者(用户)的授权。
  2. 资源所有者(用户)同意授权,返回授权许可(Authorization Grant),这代表了资源所有者的授权凭证。
  3. 客户端(浏览器)携带授权许可要求授权服务器进行认证,请求访问令牌。
  4. 授权服务器对客户端(浏览器)进行身份验证,并认证授权许可,如果有效,返回访问令牌。
  5. 客户端(浏览器)携带访问令牌向资源服务器请求受保护资源的访问。
  6. 资源服务器验证访问令牌,如果有效,接受访问请求,返回受保护资源。

认证流程可类比微信开放平台接入微信登录功能。


微信登录.png
  1. 第三方发起微信授权登录请求,微信用户允许授权第三方应用后,微信会拉起应用或重定向到第三方网站,并且带上授权临时票据code参数;
  2. 通过code参数加上AppID和AppSecret等,通过API换取access_token;
  3. 通过access_token进行接口调用,获取用户基本数据资源或帮助用户实现基本操作。

3、JWT

JWT(JSON Web Token)作为一个开放的标准,通过紧凑(Compact)或者自包含(Self-contained)的方式,定义了用于在各方之间发送的安全JSON对象。

JWT可以很好地充当在上面介绍的访问令牌和刷新令牌的载体,这是Web双方之间进行安全传输信息的良好方式。只有授权服务器持有签发和验证JWT的密钥,那么就只有授权服务器能验证JWT的有效性以及发送带有签名的JWT,这就唯一保证了以JWT为载体的令牌的有效性和安全性。

JWT的一般格式如下所示:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.eyJuYW1lIjoiY2FuZyB3dSIsImV4cCI6MTUxODA1MTE1NywidXNlcklkIjoiMTIzNDU2In0
.IV4XZ0y0nMpmMX9orv0gqsEMOxXXNQOE680CKkkPQcs

它由三部分组成,每部分通过.分隔开,分别是:
Header(头部)
Payload(有效负荷)
Signature(签名)

3.1、头部

头部通常由两部分组成:
·typ:类型,一般为JWT。
·alg:加密算法,通常是HMAC SHA256或者RSA。

一个简单的头部例子如下所示:
{
"alg": "HS256"
"typ": "JWT"
}
这部分JSON会由Base64Url编码,构成JWT的第一部分,如下所示:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

3.2、有效载荷

有效负荷(Payload)是JWT的第二部分,是用来携带有效信息的载体,主要是关于用户实体和附加元数据的声明,组成如下:

  1. Registered claims(注册声明)。这是一组预定的声明,但并不强制要求。它提供了一套有用的、能共同使用的声明。主要有iss(JWT签发者)、exp(JWT过期时间)、sub(JWT面向的用户)、aud(接受JWT的一方)等。
  2. Public claims(公开声明)。公开声明中可以添加任何信息,一般是用户信息或者业务扩展信息等。
  3. Private claims(私有声明)。由JWT提供者和消费者共同定义的声明,既不属于注册声明也不属于公开声明。

一般不建议在Payload中添加任何敏感信息,因为Base64是对称解密的,这意味着Payload中的信息是可见的。
一个简单的Payload例子如下所示:
{
"name": "cang wu",
"exp": 1518051157,
"userId": "123456"
}

这部分JSON会由Base64Url编码,构成JWT的第二部分,如下所示:
eyJuYW1lIjoiY2FuZyB3dSIsImV4cCI6MTUxODA1MTE1NywidXNlcklkIjoiMTIzNDU2In0

3.3、签名

要创建签名,需要编码后的头部、编码后的Payload、一个密钥,最后通过在头部alg键值定义的加密算法加密生成签名,生成签名的伪代码如下所示:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)

上述代码中用到的加密算法为HMACSHA256。密钥保存在服务端用于验证JWT以及签发JWT,所以必须只由服务端持有,不该泄露出去。
一个简单的签名如下所示:
IV4XZ0y0nMpmMX9orv0gqsEMOxXXNQOE680CKkkPQcs
这将成为JWT的第三部分。

这三部分通过“.”分割,组成最终的JWT,如下所示:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
.eyJuYW1lIjoiY2FuZyB3dSIsImV4cCI6MTUxODA1MTE1NywidXNlcklkIjoiMTIzNDU2In0
.IV4XZ0y0nMpmMX9orv0gqsEMOxXXNQOE680CKkkPQcs

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,588评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,456评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,146评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,387评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,481评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,510评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,522评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,296评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,745评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,039评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,202评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,901评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,538评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,165评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,415评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,081评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,085评论 2 352