Spring Security Oauth2 扩展grant_type
Spring Security Oauth2 自定义grant_type的实现在使用Jhipster 搭建微服务框架时,使用了jhipster 提供的uaa做用户认证授权,Jhipster uaa 是基于spring security oauth2 做授权认证,而spring security oauth2 默认授权模式不满足实际的业务需要,例如手机验证码授权、第三方认证授权等,那么需要自...
·
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 {
// 仅仅复制了 ResourceOwnerPasswordTokenGranter,只是改变了 GRANT_TYPE 的值,来验证自定义授权模式的可行性
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) {
//covers expired, locked, disabled cases (mentioned in section 5.2, draft 31)
throw new InvalidGrantException(ase.getMessage());
} catch (BadCredentialsException e) {
// If the username/password are wrong the spec says we should send 400/invalid grant
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()));// 获取默认的granter集合
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 {
//pick up all TokenEnhancers incl. those defined in the application
//this avoids changes to this class if an application wants to add its own to the chain
Collection<TokenEnhancer> tokenEnhancers = applicationContext.getBeansOfType(TokenEnhancer.class).values();
TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(new ArrayList<>(tokenEnhancers));
endpoints
.authenticationManager(authenticationManager)
.tokenGranter(tokenGranter(endpoints)) // 配置granter 为最新的
.tokenStore(tokenStore())
.tokenEnhancer(tokenEnhancerChain)
.reuseRefreshTokens(false); //don't reuse or we will run into session inactivity timeouts
}
}
简单的三步,扩展完毕,可以自己修改请求的grant_type来验证了 。
更多推荐
已为社区贡献1条内容
所有评论(0)