微服务中,对用户及其权限的管理,具体实现的方式有很多种,从架构上来看分为:
- 网关层进行权限管理 <本文的实现方式>;
- 各服务独立实现校验;
- 校验逻辑实现在各服务上,通过共享数据或者授权中心等方式实现;
本文源码: 码云传送门
授权流程图示1:
校验流程图示2:
实例演示
git clone https://git.oschina.net/zhangfeng0103/springcloud-microservices-examples
cd springcloud-microservices-examples
mvn clean package
####启动本次重要的三个服务
java -Dfile.encoding=UTF-8 -jar eureka-server\target\eureka-server-1.0.0.jar
java -Dfile.encoding=UTF-8 -jar gateway\target\gateway-1.0.0.jar
java -Dfile.encoding=UTF-8 -jar uaa-service\target\uaa-service-1.0.0.jar
####测试一把(windows)
# 项目中UAA已经默认有两个用户,且有对应的权限。参考resource目录下import.sql
# 用户10086,获取token
C:\Users\zhangfeng>curl "http://localhost:8765/uaa-token/token/byPhone" -H "Content-Type: application/json" --data-binary "{\"phone\":\"10086\",\"password\":\"123\"}" --compressed
{"accessToken":"eyJhbGciOiJIUzUxMiIsInppcCI6IkRFRiJ9.eNpUjsEOgjAQRP-lR2KlYCmFk1_gDxgP23aRohRiwZgY_90NEo3HmXk7O0_mY2Q1mwHYhnmYWJ3JSshCCS03DGZHYSZERmk3eRLOqMLtSuRNnisuoSq5lqLk0lS6AKMcuoLgOeLtAD3SRQf2Qg4-xrVc6aUce_DXtX5PA7Z26Ikb2yHgx9aKdJzNb0Mwzf_CaIeR6CNLh2hbHyBNEuLSqUVOE-7e4urQh6_TQ4DzEpxebwAAAP__.JXorfMhakvVMcfW8m35d9RWv5TEiGKUjZipDXRl9lm9C-EF2UZIO7iGR9XRu6s5axnKM29b4Kvml8PiL984E9w"}
# 调用接口 解析token可以显示的看到相应的用户信息及scope
C:\Users\zhangfeng>curl "http://localhost:8765/uaa-token/token/parse?token=eyJhbGciOiJIUzUxMiIsInppcCI6IkRFRiJ9.eNpUjsEOgjAQRP-lR2KlYCmFk1_gDxgP23aRohRiwZgY_90NEo3HmXk7O0_mY2Q1mwHYhnmYWJ3JSshCCS03DGZHYSZERmk3eRLOqMLtSuRNnisuoSq5lqLk0lS6AKMcuoLgOeLtAD3SRQf2Qg4-xrVc6aUce_DXtX5PA7Z26Ikb2yHgx9aKdJzNb0Mwzf_CaIeR6CNLh2hbHyBNEuLSqUVOE-7e4urQh6_TQ4DzEpxebwAAAP__.JXorfMhakvVMcfW8m35d9RWv5TEiGKUjZipDXRl9lm9C-EF2UZIO7iGR9XRu6s5axnKM29b4Kvml8PiL984E9w" -H "Content-Type: application/json" --compressed
{"iss":"uaa","iat":1490456084,"aud":"1001","jti":"db65d37e-f226-4a97-8407-4b985ab6ded5","userName":"jack","exp":1490468084,"email":"1001@uaa.com","phone":"10086","sub":"1001","nbf":1490456084,"scope":["/oschina/**","/the-service/**","/uaa-service/manage/**"]}
# 尝试调用查看用户信息的接口
C:\Users\zhangfeng>curl "http://localhost:8765/uaa-service/manage/users/1001" -H "Authorization:eyJhbGciOiJIUzUxMiIsInppcCI6IkRFRiJ9.eNpUjsEOgjAQRP-lR2KlYCmFk1_gDxgP23aRohRiwZgY_90NEo3HmXk7O0_mY2Q1mwHYhnmYWJ3JSshCCS03DGZHYSZERmk3eRLOqMLtSuRNnisuoSq5lqLk0lS6AKMcuoLgOeLtAD3SRQf2Qg4-xrVc6aUce_DXtX5PA7Z26Ikb2yHgx9aKdJzNb0Mwzf_CaIeR6CNLh2hbHyBNEuLSqUVOE-7e4urQh6_TQ4DzEpxebwAAAP__.JXorfMhakvVMcfW8m35d9RWv5TEiGKUjZipDXRl9lm9C-EF2UZIO7iGR9XRu6s5axnKM29b4Kvml8PiL984E9w" -H "Content-Type: application/json" --compressed
{
"phone" : "10086",
"userName" : "jack",
"password" : "123",
"email" : "1001@uaa.com",
"_links" : {
"self" : {
"href" : "http://localhost:8765/uaa-service/manage/users/1001"
},
"user" : {
"href" : "http://localhost:8765/uaa-service/manage/users/1001"
}
}
}
# OK,调用顺利
# 切换用户10087
# .. .省略获取token的步骤,直接尝试调用接口
# cmd窗口有乱码,特意加了-w \nhttpstatus:%{http_code},可以看到,服务器响应的状态码为403
C:\Users\zhangfeng>curl "http://localhost:8765/uaa-service/manage/users/1001" -H "Authorization:eyJhbGciOiJIUzUxMiIsInppcCI6IkRFRiJ9.eNpUjk0KwjAQhe8yy9LYtE3TpCtP4AXExaSJGLE_mAYE8RZeQnDlpcRbOGhBXL73vnnzzuBDgAYiIqTgcYImF5qLSpaKp4DRUphzXlC6nzwJjbUpt9oxmaNiwhbIlCoLxp3AykpZayUIjsEdV9g5unjd7s_rgzx3Gud6qT71rkN_mB8sacKiHTrixt3Qu6-tatIhmt-K3mz_N4Z2GIleQ2bQ25glCWwubwAAAP__.gDIC1foN5yUpFbJ7zC-v0Q3Y4jTu8I5L4_ewvu7dPggXmZIwzucAgsj1RzcObPLF8I0dWwMPYUiALJlfiut_uQ" -H "Content-Type: application/json" --compressed -w \nhttpstatus:%{http_code}
{"content":"鏃犺闂潈闄?,"result":false}httpstatus:403
划重点:
# gateway config网关相关的配置
gateway:
token:
jwt:
key: xxxxxsthis # 与uaa中的key保持一致
filter:
noAuthenticationUrls: #此处代码,下面这些路由 ID 不需要验权
- gateway
- uaa-token
errorMessage: #这是异常处理,code与异常描述的对应关系维护
999: 系统异常
403: 无访问权限
500: 服务器错误
QA:
1、token已经发出去,该账户的权限发生了更新,怎么办?
-
a方法. 首先说一下托底的方案,token超过有效期就不能使用,这也就意味着,最后一批发放的token有效期过了以后,权限更新会应用到所有账户上。这种方式满足一部分平台的需要。
-
b方法. UAA通知网关,指定时间之前的token都无效,网关只需在token校验中加上对应的逻辑即可,具体实现上可轮询,可推送。(有点像我们的身份证,中央告知各级单位,某日开始一代身份证无法办理业务…)
2、 即将过期的token怎么刷新?
- 在网关验权过程中,发现即将过期的token,可在response header打入相应的标签,客户端发现有这个标签,调用刷新token的服务,重新获取一次即可。
本文参考了jhipster、CloudFoundry对UAA的实现。
大家有其他思路的话,希望能留言分享.