web-dev-qa-db-ja.com

Spring Boot 1.5.x + Security + OAuth2

Spring Boot REST API with OAuth2 Securityを持っています。

本日、spring-boot-starter-parentのバージョンを1.4.2から1.5.2にアップグレードしました。

変更によって完全に混乱しました。

以前は、REST APIをPostmanでテストできました。アクセストークンが正しくなかったり、特定のリソースに対する権限を持っていなかったりすると、サーバーの応答は次のようになります。

{
  "error": "access_denied",
  "error_description": "Access is denied"
}

これで/loginページにリダイレクトされ続けます...ログインすると、OAuth2認証なしでリソースが表示されます...

私はそれを無効にしようとしました、そして私はこの魔法の特性を見つけました:

security.oauth2.resource.filter-order = 3

この行をオフにすると、ログインページにリダイレクトされます。

ただし、私の質問は次のとおりです。

  • セキュリティの観点から、これら2つのリリースの間に何が起こりましたか?
  • この「奇妙な」行は唯一の有効な修正ですか?
  • このログインページの目的とそれが使用している認証(Googleでリクエストとレスポンスを確認したChromeで、アクセストークンとoauth2が表示されないため、ユーザーを使用しているリポジトリだけですか?)

私のコードのいくつかのより重要な部分:

pom.xml

<!--- .... -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.2.RELEASE</version>
</parent>
<properties>
    <!--- .... -->
    <spring-security-oauth.version>2.1.0.RELEASE</spring-security-oauth.version>
    <!--- .... -->
</properties>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <!-- Monitor features -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-actuator</artifactId>
    </dependency>
    <!-- Security + OAuth2 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.security.oauth</groupId>
        <artifactId>spring-security-oauth2</artifactId>
        <version>${spring-security-oauth.version}</version>
    </dependency>
<!--- .... -->

application.properties

#other properties
security.oauth2.resource.filter-order = 3

OAuth2.Java

public class OAuth2 {
@EnableAuthorizationServer
@Configuration
@ComponentScan
public static class AuthorizationServer extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManagerBean;
    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("trusted_client")
                .authorizedGrantTypes("password", "refresh_token")
                .scopes("read", "write");
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManagerBean).userDetailsService(userDetailsService);
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.allowFormAuthenticationForClients();
    }
}

@EnableResourceServer
@Configuration
@ComponentScan
public static class ResourceServer extends ResourceServerConfigurerAdapter {

    @Autowired
    private RoleHierarchy roleHierarchy;

    private SecurityExpressionHandler<FilterInvocation> webExpressionHandler() {
        DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler();
        defaultWebSecurityExpressionHandler.setRoleHierarchy(roleHierarchy);
        return defaultWebSecurityExpressionHandler;
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests().expressionHandler(webExpressionHandler())
                .antMatchers("/api/**").hasRole("DEVELOPER");
    }
}
}

Security.Java

@EnableWebSecurity
@Configuration
@ComponentScan
public class Security extends WebSecurityConfigurerAdapter {

@Autowired
private UserDetailsService userDetailsService;

@Bean
public JpaAccountDetailsService userDetailsService(AccountsRepository accountsRepository) {
    return new JpaAccountDetailsService(accountsRepository);
}

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}

@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
}

@Bean
public PasswordEncoder passwordEncoder(){
    return new BCryptPasswordEncoder();
}
}
12
ilovkatie

最初と2番目の質問の答えは Spring Boot 1.5リリースノート です。

OAuth 2リソースフィルター

OAuth2リソースフィルターのデフォルトの順序が3からSecurityProperties.ACCESS_OVERRIDE_ORDER-1に変更されました。これにより、アクチュエータエンドポイントの後で、基本認証フィルターチェーンの前に配置されます。デフォルトを復元するには、security.oauth2.resource.filter-order = 3を設定します。

/ loginページは、Springが権限のないユーザーをリダイレクトする単なるパスです。 カスタムログインフォーム を使用しておらず、Oauth2フィルターの位置が間違っているため、おそらく基本認証を使用していました。

4
Cleto Gadelha

これは、リソースサーバーが正しく構成されていないことが原因である可能性があります。

@Override
  public void configure(final HttpSecurity http) throws Exception {
    // @formatter:off
    http.csrf().disable().authorizeRequests()
    // This is needed to enable swagger-ui interface.
    .antMatchers("/swagger-ui.html","/swagger-resources/**","/webjars/**", "/v2/api-docs/**").permitAll()
    .antMatchers("/api/v1/**").hasRole("TRUSTED_CLIENT")
    .antMatchers("/api/v1/**").hasRole("USER")
    .antMatchers("/api/v1/**").hasAuthority("ROLE_TRUSTED_CLIENT");
    // @formatter:on
  }
0
Amit Sachan