Spring Security Oauth2 扩展grant_type

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来验证了 。

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
使用Spring Security OAuth2进行code换取access_token的步骤如下: 1.客户端向认证服务器发出授权请求,包括客户端ID、访问范围、重定向URI和response_type=code参数。 2.认证服务器对用户进行认证,如果用户认证通过,认证服务器将生成授权码(code)。 3.认证服务器将授权码(code)发送给客户端重定向URI中。 4.客户端收到授权码(code)后,使用code和client_secret向认证服务器请求access_token。 5.认证服务器验证code和client_secret,如果验证通过,将生成access_token。 6.客户端收到access_token后,即可使用该token访问受保护的资源。 示例代码如下: ``` RestTemplate restTemplate = new RestTemplate(); MultiValueMap<String, String> params= new LinkedMultiValueMap<>(); params.add("grant_type", "authorization_code"); params.add("code", code); params.add("redirect_uri", redirectUri); params.add("client_id", clientId); params.add("client_secret", clientSecret); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(params, headers); ResponseEntity<String> responseEntity = restTemplate.postForEntity(tokenUrl, requestEntity, String.class); ``` 其中,code是授权码,redirectUri是客户端重定向URI,clientId和clientSecret是客户端ID和密钥,tokenUrl是认证服务器的地址。授权服务器将返回一个JSON格式的字符串,其中包含access_token等信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值