Spring Boot 2 Oauth如何实现隐式代码流

时间:2019-01-12 09:36:21

标签: spring spring-boot oauth oauth-2.0

当前,我正在将OAuth引入我的Spring应用程序中,但是我没有运气来正确集成它。我正在使用 Spring Boot 2

我的要求是:

  • 授权和资源服务器是同一服务器上运行的同一应用
  • 隐式,授权码授予和资源所有者凭证授予流程需要
  • 我要保护的API生活在“ / api / v1 /”下

所有流程都无法正常工作。.到目前为止,我所实现的工作基于https://www.devglan.com/spring-security/spring-oauth2-role-based-authorization的教程以及答案:https://stackoverflow.com/a/52386009/4454752

所以我的 AuthorizationServer 看起来像这样:

'2018-03'

然后 ResourceServer

MTD

最后一个 WebSecurityConfig

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

  private final AuthenticationManager authenticationManager;

  @Autowired
  public AuthorizationServerConfig(AuthenticationManager authenticationManager) {
    this.authenticationManager = authenticationManager;
  }

  @Bean
  public JwtAccessTokenConverter accessTokenConverter() {
    JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
    converter.setSigningKey("as466gf");
    return converter;
  }

  @Bean
  public TokenStore tokenStore() {
    return new JwtTokenStore(accessTokenConverter());
  }


  @Override
  public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    clients
      .inMemory()
      .withClient("my-client-id")
      .authorizedGrantTypes("authorization_code", "implicit", "refresh_token", "password")
      .authorities("ADMIN")
      .scopes("all")
      .resourceIds("product_api")
      .secret("$2a$10$jfAHmk4szDU/t1qLGlFTLukuBZL0ZHZGUJQICePjjyq6IrLOS934.")
      .redirectUris("https://example.com")
      .accessTokenValiditySeconds(7200)
      .refreshTokenValiditySeconds(7200);
  }

  @Override
  public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
    oauthServer
      .tokenKeyAccess("permitAll()")
      .checkTokenAccess("permitAll()");
  }

  @Override
  public void configure(AuthorizationServerEndpointsConfigurer endpoints) {

    endpoints
      .authenticationManager(authenticationManager)
      .accessTokenConverter(accessTokenConverter());
  }

}

我的UserDetails和完整的用户管理已经设置,因此无需在此处进行任何更改。

现在是用例。

如果访问“ / oauth /令牌”:

   @Configuration
@EnableResourceServer
@Order(2)
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {


  @Override
  public void configure(ResourceServerSecurityConfigurer resources) {
    resources.resourceId("product_api");
  }

  @Override
  public void configure(HttpSecurity http) throws Exception {
    http
      .requestMatchers()
      .antMatchers("/**")
      .and().authorizeRequests()
      .antMatchers("/**").permitAll()
      .and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
  }


}

因此,通过my-client:my-secret我得到了带有访问令牌和刷新令牌的响应。但是,如果我想在API上使用访问令牌,则会得到@Configuration @Order(1) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Resource(name = "userDetailService") private UserDetailService userDetailsService; @Bean public BCryptPasswordEncoder encoder() { return new BCryptPasswordEncoder(); } @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Autowired public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder(encoder()); } @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers("/api/v1/**") .hasAnyRole("ADMIN", "USER").and() .httpBasic().and().formLogin().and().authorizeRequests().anyRequest().authenticated(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth .userDetailsService(userDetailsService) .passwordEncoder(encoder()); } } 。如果我使用curl --request POST \ --url http://localhost:8080/oauth/token \ --header 'authorization: Basic bXktY2xpZW50Om15LXNlY3JldA==' \ --header 'content-type: application/x-www-form-urlencoded' \ --data 'grant_type=password&username=admin&password=test' 检查令牌,则表明令牌有效。

如果我使用“ / oauth / authorize”(隐式流),则会出现相同的问题。我知道我需要从Spring开始的登录页面才能使其正常运行,这就是为什么我在Access denied中添加了/oauth/check_token的原因。但是,如果我查询formLogin(),然后重定向到WebSecurityConfig,然后从重定向URL获取访问令牌,但是如果再次使用此令牌,则会收到http://localhost:8080/oauth/authorize?response_type=token&client_id=my-client&redirect_uri=https://example.com错误。

我要访问的端点由以下控制器处理:

/login

我非常确定Security(安全性)配置有问题,但是我不知道它可能是什么。我在网上浏览了很多指南,但没有找到一个单独的指南来解释所有授权代码。我认为对URL进行身份验证可能是一个小错误,但我不知道它可能是什么。

如果有人知道答案,我会很高兴。

1 个答案:

答案 0 :(得分:0)

将您的configure()实现从WebSecurityConfig移动到如下所示的Resource Server configure()方法

http.authorizeRequests()
      .antMatchers("/api/v1/**")
      .hasAnyRole("ADMIN", "USER")

不需要configure()方法中的其余配置