开发者社区> 嘿嘿!!> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

使用 OAuth 2 和 JWT 为微服务提供安全保障

简介: Part 1 - 理论相关 作者 freewolf 关键词 微服务、Spring Cloud、OAuth 2.0、JWT、Spring Security、SSO、UAA 写在前面 作为从业了十多年的IT行业和程序的老司机,今天如果你说你不懂微服务,都不好意思说自己的做软件的。
+关注继续查看

Part 1 - 理论相关
作者 freewolf

关键词
微服务、Spring Cloud、OAuth 2.0、JWT、Spring Security、SSO、UAA

写在前面
作为从业了十多年的IT行业和程序的老司机今天如果你说你不懂微服务都不好意思说自己的做软件的。SOA喊了多年无人不知但又有多少系统开发真正的SOA了呢但是好像一夜之间所有人都投入了微服务的怀抱。

作为目前最主流的“微服务框架”Spring Cloud发展速度很快成为了最全面的微服务解决方案。不管什么软件体系什么框架安全永远是不可能绕开的话题我也把它作为我最近一段时间研究微服务的开篇。

老话题“如何才能在微服务体系中保证安全”为了达成目标这里采用一个简单而可行方式来保护Spring Cloud中服务的安全也就是建立统一的用户授权中心。

这里补充说一下什么是Authentication认证和Authorization鉴权其实很简单认证关心你是谁鉴权关心你能干什么。举个大家一致都再说的例子如果你去机场乘机你持有的护照代表你的身份这是认证你的机票就是你的权限你能干什么。

学习微服务并不是一个简单的探索过程这不得学习很多新的知识其实不管是按照DDDDomain Driven Design领域驱动设计中领域模型的方式还是将微服务拆分成更小的粒度。都会遇到很多新的问题和以前一直都没解决很好的问题。随着不断的思考随着熟悉Facebook/GitHub/AWS这些机构是如何保护内部资源答案也逐渐浮出水面。

为了高效的实现这个目标这里采用OAuth 2和JWT(JSON Web Tokens)技术作为解决方案

为什么使用OAuth 2
尽管微服务在现代软件开发中还算一个新鲜事物但是OAuth 2已经是一个广泛使用的授权技术它让Web开发者在自己提供服务中用一种安全的方式直访问Google/Facebook/GitHub平台用户信息。但在我开始阐述细节之前我将揭开聚焦到本文真正的主题云安全

那么在云服务中对用户访问资源的控制我们一般都怎么做呢然我举一些大家似乎都用过的但又不是很完美的例子。

我们可以设置边界服务器或者带认证功能的反向代理服务器假设所有访问请求都发给它。通过认证后转发给内部相应的服务器。一般在Spring MVC Security开发中几乎都会这样做的。但这并不安全最重要的是一旦是有人从内部攻击你的数据毫无安全性。

其他方式:我们为所有服务建立统一的权限数据库并在每次请求前对用户进行鉴权听起来某些方面的确有点愚蠢但实际上这确实是一个可行的安全方案。

更好的方式: 用户通过授权服务来实现鉴权把用户访问Session映射成一个Token。所有远程访问资源服务器相关的API必须提供Token。然后资源服务器访问授权服务来识别Token得知Token属于哪个用户并了解通过这个Token可以访问什么资源。

这听起来是个不错的方案对不但是如何保证Token的安全传输如何区分是用户访问还是其他服务访问这肯定是我们关心的问题。

所以上述种种问题让我们选择使用OAuth 2其实访问Facebook/Google的敏感数据和访问我们自己后端受保护数据没什么区别并且他们已经使用这样的解决方案很多年我们只要遵循这些方法就好了。

OAuth 2是如何工作的
如果你了解OAuth 2相关的原理那么在部署OAuth 2是非常容易的。
让我们描述下这样一个场景“某App希望获得Tom在Facebook上相关的数据”

OAuth 2 在整个流程中有四种角色:

资源拥有者(Resource Owner) - 这里是Tom
资源服务器(Resource Server) - 这里是Facebook
授权服务器(Authorization Server) - 这里当然还是Facebook因为Facebook有相关数据
客户端(Client) - 这里是某App
当Tom试图登录Facebook某App将他重定向到Facebook的授权服务器当Tom登录成功并且许可自己的Email和个人信息被某App获取。这两个资源被定义成一个Scope权限范围一旦准许某App的开发者就可以申请访问权限范围中定义的这两个资源。

+——–+ +—————+
| |–(A)- Authorization Request ->| Resource |
| | | Owner |
| |<-(B)– Authorization Grant —| |
| | +—————+
| |
| | +—————+
| |–(C)– Authorization Grant –>| Authorization |
| Client | | Server |
| |<-(D)—– Access Token ——-| |
| | +—————+
| |
| | +—————+
| |–(E)—– Access Token ——>| Resource |
| | | Server |
| |<-(F)— Protected Resource —| |
+——–+ +—————+
Tom允许了权限请求再次通过重定向返回某App重定向返回时携带了一个Access Token访问令牌接下来某App就可以通过这个Access Token从Facebook直接获取相关的授权资源也就是Email和个人信息而无需重新做Tom相关的鉴权。而且每当Tom登录了某App都可以通过之前获得的Access Token直接获取相关授权资源。

到目前为止我们如何直接将以上内容用于实际的例子中OAuth 2十分友好并容易部署所有交互都是关于客户端和权限范围的。

OAuth 2中的客户端和权限范围和我们平时的用户和权限是否相同
我需要将授权映射到权限范围中或将用户映射到客户端中
为什么我需要客户端
你也许在之前在类似的企业级开发案例中尝试映射过相关的角色。这会很棘手

任何类型的应用都提供用户登录登录结果是一个Access Token所有的之后的API调用都将这个Access Token加入HTTP请求头中被调用服务去授权服务器验证Access Token并获取该Token可访问的权限信息。这样一来所有服务的访问都会请求另外的服务来完成鉴权。

权限范围和角色客户端和用户
在OAuth 2中你可以定义哪个应用网站、移动客户端、桌面应用、其他可以访问那些资源。这里只有一个尺寸来自哪里的哪个用户可以访问那些数据当然也是哪个应用或者服务可以访问那些资源。换一种说法权限范围就是控制那些端点对客户端可见或者用户根据他的权限来获取相关的数据。

在一个在线商店中前端可以看做一个客户端可以访问商品、订单和客户信息但后端可以关于物流和合同等另一方面用户可以访问一个服务但并不是全部的数据这可以是因为用户正在使用Web应用当他不能的时候其他用户却可以。服务之间的访问时我们要讨论的另一个维度。如果你熟悉数学我可以说在OAuth 2中客户端-权限范围关系是线性独立于用户-权限关系。

为什么是JWT
OAuth 2并不关心去哪找Access Token和把它存在什么地方的生成随机字符串并保存Token相关的数据到这些字符串中保存好。通过一个令牌端点其他服务可能会关心这个Token是否有效它可以通过哪些权限。这就是用户信息URL方法授权服务器为了获取用户信息转换为资源服务器。

当我们谈及微服务时我们需要找一个Token存储的方式来保证授权服务器可以被水平扩展尽管这是一个很复杂的任务。所有访问微服务资源的请求都在Http Header中携带Token被访问的服务接下来再去请求授权服务器验证Token的有效性目前这种方式我们需要两次或者更多次的请求但这是为了安全性也没什么其他办法。但扩展Token存储会很大影响我们系统的可扩展性这是我们引入JWT读jot的原因。

+———–+ +————-+
| | 1-Request Authorization | |
| |————————————>| |
| | grant_type&username&password | |–+
| | |Authorization| | 2-Gen
| Client | |Service | | JWT
| | 3-Response Authorization | |<-+
| |<————————————| Private Key |
| | access_token / refresh_token | |
| | token_type / expire_in / jti | |
+———–+ +————-+
简短来说响应一个用户请求时将用户信息和授权范围序列化后放入一个JSON字符串然后使用Base64进行编码最终在授权服务器用私钥对这个字符串进行签名得到一个JSON Web Token我们可以像使用Access Token一样的直接使用它假设其他所有的资源服务器都将持有一个RSA公钥。当资源服务器接收到这个在Http Header中存有Token的请求资源服务器就可以拿到这个Token并验证它是否使用正确的私钥签名是否经过授权服务器签名也就是验签。验签通过反序列化后就拿到OAuth 2的验证信息。

验证服务器返回的信息可以是以下内容

access_token - 访问令牌用于资源访问
refresh_token - 当访问令牌失效使用这个令牌重新获取访问令牌
token_type - 令牌类型这里是Bearer也就是基本HTTP认证
expire_in - 过期时间
jti - JWT ID
由于Access Token是Base64编码反编码后就是下面的格式标准的JWT格式。也就是Header、 Payload、Signature三部分。

{
“alg”:”RS256”,
“typ”:”JWT”
}
{
“exp”: 1492873315,
“user_name”: “reader”,
“authorities”: [
“AURH_READ”
],
“jti”: “8f2d40eb-0d75-44df-a8cc-8c37320e3548”,
“client_id”: “web_app”,
“scope”: [
“FOO”
]
}
&:lƧs)ۡ-[+
F”2”Kآ8ۓٞ:u9ٴ̯ޡ 9Q32Zƌ޿$ec{3mxJh0DF庖[!뀭N)㥔knVVĖV|夻ׄE㍫}Ŝf9>’<蕱굤Bۋеϵov虀DӨ8C4K}Emޢ YVcaqIW&uʝub!׏Ť\՟-{ʖX܌WTq
使用JWT可以简单的传输Token用RSA签名保证Token很难被伪造。Access Token字符串中包含用户信息和权限范围我们所需的全部信息都有了所以不需要维护Token存储资源服务器也不必要求Token检查。

+———–+ +———–+
| | 1-Request Resource | |
| |———————————–>| |
| | Authorization: bearer Access Token | |–+
| | | Resource | | 2-Verify
| Client | | Service | | Token
| | 3-Response Resource | |<-+
| |<———————————–| Public Key|
| | | |
+———–+ +———–+
所以在微服务中使用OAuth 2不会影响到整体架构的可扩展性。淡然这里还有一些问题没有涉及例如Access Token过期后使用Refresh Token到认证服务器重新获取Access Token等后面会有具体的例子来展开讨论这些问题。

点击获取优惠券

点我获取阿里云优惠券

我的官网
我的博客

我的官网http://guan2ye.com
我的CSDN地址http://blog.csdn.net/chenjianandiyi
我的简书地址http://www.jianshu.com/u/9b5d1921ce34
我的githubhttps://github.com/javanan
我的码云地址https://gitee.com/jamen/
阿里云优惠券https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=vf2b5zld&utm_source=vf2b5zld

阿里云教程系列网站http://aliyun.guan2ye.com

1.png

我的开源项目spring boot 搭建的一个企业级快速开发脚手架

1.jpg

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
还不会使用JWT格式化OAuth2令牌吗?
`OAuth2`默认的`AccessToken`是由`DefaultAccessTokenConverter`生成,是具有唯一性的`UUID`随机字符串,我们如果想要使用`JWT`来格式化`AccessToken`就需要使用`JwtAccessTokenConverter`来进行格式化,当然如果你有自己独特的业务可以自己实现`AccessTokenConverter`接口,并将实现类交付给`IOC`托管即可。
5 0
SpringCloud微服务实战——搭建企业级开发框架(二十三):Gateway+OAuth2+JWT实现微服务统一认证授权
OAuth2是一个关于授权的开放标准,核心思路是通过各类认证手段(具体什么手段OAuth2不关心)认证用户身份,并颁发token(令牌),使得第三方应用可以使用该token(令牌)在限定时间、限定范围访问指定资源。   OAuth2中使用token验证用户登录合法性,但token最大的问题是不携带用户信息,资源服务器无法在本地进行验证,每次对于资源的访问,资源服务器都需要向认证服务器发起请求,一是验证token的有效性,二是获取token对应的用户信息。如果有大量的此类请求,无疑处理效率是很低,且认证服务器会变成一个中心节点
414 0
微服务架构 | 7.2 构建使用 JWT 令牌存储的 OAuth2 安全认证
JWT 为 OAuth2 令牌提供规范标准,并且可以自定义 JWT 令牌;
90 0
OAuth2.0实战(三)-使用JWT(下)
OAuth2.0实战(三)-使用JWT(下)
109 0
SeaJS入门篇一 怎么使用query
研究了2个多小时,终于搞定引入jq 1.写个html页面 ddddddddd 2.配置脚本路径 // seajs 的简单配置 seajs.config({ //base: "",//默认和sea.
850 0
+关注
嘿嘿!!
不想当码农的程序员
文章
问答
文章排行榜
最热
最新
相关电子书
更多
API网关实践
立即下载
基于 OpenResty 和 Node.js 的个推微服务实践
立即下载
基于资产配置业务场景下全链路监控平台
立即下载