我正在使用Owin Oauth2(授权和资源服务器是相同的)开发单页面应用程序(AngularJS .Net MVC Json Rest API)的身份验证流程 .
我在传统的cookie会话中选择了Bearer Token路由,因为我希望保持无状态,并且因为移动应用程序将使用相同的Api,其中令牌的问题少于cookie .
这是简化的流程:
-
用户向服务器提交用户名/密码(通过Https POST到TokenProvider路由)
-
Owin使用声明创建
AccessToken
,声明包含生成的GUID(代表会话ID)和其他一些声明 . -
Owin创建
RefreshToken
. -
Server在
RefreshToken
表中创建一个条目,其中包含以下字段:
GUID(PK)| RefreshToken |票证| DateIssued | DateExpire | DateEnd
-
Server将
AccessToken
和RefreshToken
同时提供给客户端 . -
客户端将
AccessToken
和RefreshToken
存储到SessionStorage中 . -
客户端使用
AccessToken
访问Api .
当AngularJS检测到AccessToken即将到期时,它会缓冲所有请求并发出 grant_type refresh_token request
;
服务器使用客户端提供的 RefreshToken
并:
-
检查Db中的刷新令牌是否仍然有效(
DateExpire > GetTime() And DateEnd is Null
) -
从Db取得机票
-
从Ticket创建AccessToken
-
使用新鲜日期,新
RefreshToken
和新票证更新数据库条目(注意:GUID保持不变)
当客户端命中注销服务器端时,从记录用户的身份声明中读取的GUID用于使表上的条目无效( DateEnd = GetTime()
) .
客户端两个令牌都从 SessionStorage
中删除 .
通过这种方式,我可以撤销 RefreshToken
否认任何其他要求获得新鲜的 AccessToken
.
这种方法的问题在于,授权被撤销时有一个时间窗口(即: RefreshToken
在DB上无效)但 AccessToken
仍然有效(尽管在有限的时间范围内) .
我想要做的是检查每个请求的 AccessToken
的有效性,从用户身份声明中获取GUID并命中数据库以检查该特定GUID的刷新令牌是否仍然有效 .
尽管使查询执行O(1)非常简单,但单点故障本身可能会对系统的可伸缩性和性能产生负面影响 .
你知道另一种缓解这个问题的方法吗?你看到我的方法有什么缺陷吗?
1 回答
您的方法没有任何问题,它与我之前的方法非常相似,但我建议您在发送访问令牌时不进行任何数据库检查 .
为什么不发布短期访问令牌,即(30分钟),并等到撤销刷新令牌后访问令牌生存时间到期 . 在客户端上,您可以从客户端本地存储中清除刷新令牌和访问令牌 .