事实上,任何代码都有或多或少的缺陷,世界上根本就没有完美的代码,包括各种我们常用的工具包。Oauth2的源码配置中就是遇到了这样的问题。
或许是最初的设计有问题,每种手机APP的客户端都是共用了一套账户密码,采用Oauth2.0的验证方式调用后台API接口。但是当客户端数据并发以后,获取accesstoken的方法并发就出现了问题。在Oauth2.0的源码中,是通过删除accesstoken的记录,然后新增的方式来实现管理token的。然后由于没有乐观锁版本控制,导致同时进入该方法的不同线程会造成生成不止一条username的token信息,引起该账户再也无法使用。
其实本质上,token的粒度应该是细分到客户级别,至少也是设备级别,这也算是一个学艺不精的失误吧(一开始采用Oauth2.0只是为了接口的安全及权限控制)。但现在系统离上线不远,因此折中的办法就是修改源码,牺牲效率换取安全性,将整个查询并生成accesstoken的事务方法声明为同步方法。下面是重写DefaultTokenServices并添加到配置类中的主要代码。重写的方法是public synchronized OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) throws AuthenticationException。
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception的配置中添加.tokenServices(mPTokenService())。
@Bean
public AuthorizationServerTokenServices m