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。一顿搜索找到接口。
看到getAccessToken就知道找对了
跟着方法一路深入就找到这个createAccessToken方法,如果存在token就返回,否则就创建token。
继续深入方法,获取了key后就去读redis了,那么真心就一定在extractKey方法中
看到代码后恍然大悟
只要 username, client_id 和 scope,除非client_id 和 scope 不一样。在我的情况是这两个值是相同的, 那么用户名同样的话那么生成的token就是一样的。然后在根据生成的token返回,前端带上这个不属于这个账号的token去访问接口。那么一切就还原了。
4.解决问题
既然知道了是username的问题,我们只需要把username改成唯一即可。在重写的authenticate方法里处理一下即可。
这样问题就可以解决了。确保每次生成的token都是不一样。
5.总结
一般情况下通过查日志和清缓存就能解决大部分问题。如需要深入源码的时候,个人认为不需要知道整个方法的细节,抓住重点即可。这就是我排查问题的整个思路了,希望对大家有所帮助。