记一次生产登录严重BUG SpringCloud Oauth2

25 阅读2分钟

1.背景故事

最近有用户反馈,登录后发现自己的用户数据没了,而且自己的角色和管理员都不正确。当时测试跟我在测试环境怎么都没法复现。查了一个下午毫无发现,当时人傻了。

2.问题发现

就当我们百思不得其解的时候,运维同学把问题复现了。当用户登录的时候,只要用户名是一样的情况下,就会遇到账号登录成别人账号的情况。比如说:aaa@qq.com这个账号有所有的功能权限,bbb@qq.com只有一个功能权限。当用户aaa@qq.com登录的时候,会写入redis。当用户bbb@qq.com登录的时候,会获取aaa@qq.com的token。

3.排查问题

查日志

当时就去查看了生产的日志,无论是SQL查询的用户还是日志输出返回的数据都是正确的。所以先排除掉自定义登录逻辑的错误。

清缓存

既然不是代码问题,那就看一下缓存吧,清了缓存后第一个账号登录正常,但是第二个账号还是不正常。这时候我把怀疑的目光抛向了Oauth2。

Debug源码

既然我们用了框架,那就要找到源头,登录的接口请求的是oauth/token。一顿搜索找到接口。 image.png 看到getAccessToken就知道找对了

image.png 跟着方法一路深入就找到这个createAccessToken方法,如果存在token就返回,否则就创建token。

image.png 继续深入方法,获取了key后就去读redis了,那么真心就一定在extractKey方法中

image.png 看到代码后恍然大悟

image.png 只要 username, client_id 和 scope,除非client_id 和 scope 不一样。在我的情况是这两个值是相同的, 那么用户名同样的话那么生成的token就是一样的。然后在根据生成的token返回,前端带上这个不属于这个账号的token去访问接口。那么一切就还原了。

4.解决问题

既然知道了是username的问题,我们只需要把username改成唯一即可。在重写的authenticate方法里处理一下即可。

image.png这样问题就可以解决了。确保每次生成的token都是不一样。

5.总结

一般情况下通过查日志和清缓存就能解决大部分问题。如需要深入源码的时候,个人认为不需要知道整个方法的细节,抓住重点即可。这就是我排查问题的整个思路了,希望对大家有所帮助。