Spring Security Oauth2 自定义grant_type的实现
 
   在使用Jhipster 搭建微服务框架时,使用了jhipster 提供的uaa做用户认证授权,Jhipster uaa 是基于spring security oauth2 做授权认证,而spring security oauth2 默认授权模式不满足实际的业务需要,例如手机验证码授权、第三方认证授权等,那么需要自己去扩展授权实现。
   由于初次使用spring security ,上网找了一下方案,看了很多文章基本都差不多(很多解决方案都是相互拷贝的),但实际尝试之后并没有成功,也许是我漏掉了什么配置,也许是贴出的代码不完整,总之没有成功。但是看方案的过程中也get到了很多,最终整理了我的实现方案,如果你也遇到了同样的问题,希望能给你带来帮助或提供一些思路。
   1、新建granter 继承AbstractTokenGranter 可以参考默认实现类ResourceOwnerPasswordTokenGranter
 
public class SmsCodeTokenGranter extends AbstractTokenGranter {
   
   private static final String 
GRANT_TYPE = "sms_code";
   private final AuthenticationManager authenticationManager
;
   public SmsCodeTokenGranter(
       AuthenticationManager authenticationManager
,
       AuthorizationServerTokenServices tokenServices
,
       ClientDetailsService clientDetailsService
,
       OAuth2RequestFactory requestFactory
) {
       this(authenticationManager
, tokenServices
, clientDetailsService
, requestFactory
, GRANT_TYPE);
   }
   protected SmsCodeTokenGranter(
       AuthenticationManager authenticationManager
,
       AuthorizationServerTokenServices tokenServices
,
       ClientDetailsService clientDetailsService
,
       OAuth2RequestFactory requestFactory
,
       String grantType
) {
       super(tokenServices
, clientDetailsService
, requestFactory
, grantType
);
       this.authenticationManager 
= authenticationManager
;
   }
   @Override
   
protected OAuth2Authentication 
getOAuth2Authentication(ClientDetails client
, TokenRequest tokenRequest
) {
       Map
<String
, String
> parameters 
= new LinkedHashMap<String
, String
>(tokenRequest
.getRequestParameters());
       
       String mobile 
= parameters
.get("mobile");
       String smsCode 
= parameters
.get("sms_code");
       
       User user 
= new User();
       Authentication userAuth 
= new UsernamePasswordAuthenticationToken("admin", "admin");
       ((AbstractAuthenticationToken
) userAuth
).setDetails(parameters
);
       try {
           userAuth 
= authenticationManager
.authenticate(userAuth
);
       } catch (AccountStatusException ase
) {
           
           throw new InvalidGrantException(ase
.getMessage());
       } catch (BadCredentialsException e
) {
           
           throw new InvalidGrantException(e
.getMessage());
       }
       if (userAuth 
== null || !userAuth
.isAuthenticated()) {
           throw new InvalidGrantException("Could not authenticate user: " + mobile
);
       }
       OAuth2Request storedOAuth2Request 
= getRequestFactory().createOAuth2Request(client
, tokenRequest
);
       return new OAuth2Authentication(storedOAuth2Request
, userAuth
);
   }
}
 
   2、添加自定义granter
 
    @Configuration
@EnableAuthorizationServer
public class UaaConfiguration extends AuthorizationServerConfigurerAdapter implements ApplicationContextAware {
	
	private TokenGranter 
tokenGranter(final AuthorizationServerEndpointsConfigurer endpoints
) {
        List
<TokenGranter
> granters 
= new ArrayList<TokenGranter
>(Arrays
.asList(endpoints
.getTokenGranter()));
        granters
.add(new SmsCodeTokenGranter(authenticationManager
,endpoints
.getTokenServices(), endpoints
.getClientDetailsService(), endpoints
.getOAuth2RequestFactory()));
        return new CompositeTokenGranter(granters
);
    }
}
 
   3、配置client的grant_type
 
public class UaaConfiguration extends AuthorizationServerConfigurerAdapter implements ApplicationContextAware {
	
	@Override
    
public void configure(AuthorizationServerEndpointsConfigurer endpoints
) throws Exception 
{
        
        
        Collection
<TokenEnhancer
> tokenEnhancers 
= applicationContext
.getBeansOfType(TokenEnhancer
.class).values();
        TokenEnhancerChain tokenEnhancerChain 
= new TokenEnhancerChain();
        tokenEnhancerChain
.setTokenEnhancers(new ArrayList<>(tokenEnhancers
));
        endpoints
            
.authenticationManager(authenticationManager
)
            .tokenGranter(tokenGranter(endpoints
)) 
            .tokenStore(tokenStore())
            .tokenEnhancer(tokenEnhancerChain
)
            .reuseRefreshTokens(false);             
    }
}
 
简单的三步,扩展完毕,可以自己修改请求的grant_type来验证了 。