oauth2登录路径是/oauth/token,根据参数的不同,可实现不同方式的登录。
入口文件是TokenEndpoint,但在进入到此方法之前,会先进行认证,拿最普通的密码方式登录来说,需要传的参数必须得有Authorization或者client_id和client_secret,否则登录接口会返回401。二者关系是client_id:client_secret的base64加密的值就是Authorization传的参数值。
1.判断登录接口的认证是走client认证还是Authorization认证
判断方法是AbstractAuthenticationProcessingFilter.doFilter
if的条件会进入ClientCredentialsTokenEndpointFilter.ClientCredentialsRequestMatcher.matches方法,内容如下,主要是判断参数中是否含有client_id参数,有的话就走client认证,没有的话就走上图if条件,Authorization认证
2.Authorization认证
Authorization认证的代码均在BasicAuthenticationFilter.doFilterInternal方法中
上图中 this.authenticationConverter.convert 会将Authorization进行解密,解析出client_id和client_secret,放到authRequest中,供后续使用。两种认证方式,只是数据传入服务的方式不同,后台对参数进行不同的处理后,其实认证方式是相同的,都是ProviderManager.authenticate。
3.client认证
AbstractAuthenticationProcessingFilter.doFilter方法的else中,调用了 attemptAuthentication方法,然后ClientCredentialsTokenEndpointFilter.attemptAuthentication实现了该方法。
在做了一些验证之后,进入到ProviderManager.authenticate方法中。
4.后续认证
ProviderManager.authenticate方法
核心是 result = provider.authenticate(authentication),在这个部分,provider为DaoAuthenticationProvider,DaoAuthenticationProvider继承了AbstractUserDetailsAuthenticationProvider,authenticate使用的是AbstractUserDetailsAuthenticationProvider.authenticate。
后续逻辑调用依次为
this.retrieveUser
>>>DaoAuthenticationProvider.retrieveUser
>>>ClientDetailsUserDetailsService.loadUserByUsername
>>>JdbcClientDetailsService.loadClientByClientId
JdbcClientDetailsService这个类中包含了从数据库去客户端认证的相关信息,可对内置的sql进行赋值覆盖,从而从自定义的表中取信息。信息中包含密码信息,在对比解析出的密码,就完成了验证。验证之后,才进入到登录接口中