一尘不染

SpringBoot 1.5.x +安全性+ OAuth2

spring-boot

我有一个具有OAuth2安全性的Spring Boot REST API。

今天,我已将的版本spring-boot-starter-parent从升级1.4.21.5.2

变化完全使我感到困惑。

以前,我可以使用Postman测试我的REST API。当我的访问令牌不正确或我没有特定资源的权限时,服务器响应如下:

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

现在,它一直将我重定向到/login页面…当我登录时-它显示了没有任何OAuth2身份验证的资源…

我试图禁用它,我发现了这个神奇的属性:

security.oauth2.resource.filter-order = 3

此行已关闭,重定向到登录页面。

但是,我的问题是:

  • 就安全性而言,这两个版本之间发生了什么?
  • 这是“唯一”行是唯一有效的解决方法吗?
  • 此登录页面的目的是什么,使用的身份验证是什么(我在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");
    }
}
}

安全性

@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();
}
}

阅读 326

收藏
2020-05-30

共1个答案

一尘不染

好的,我现在知道了。

@Cleto Gadelha指出了我非常有用的信息。

但是我认为发行说明还不清楚,或者错过了一些信息。除了OAuth2资源过滤器从3变为之外SecurityProperties.ACCESS_OVERRIDE_ORDER - 1,重要的信息是默认WebSecurityConfigurerAdapter顺序为100
(源)

因此,在1.5.x版本之前,OAuth2资源服务器顺序为3,其优先级 高于WebSecurityConfigurerAdapter

在1.5.x版本之后,OAuth2资源服务器的顺序设置为SecurityProperties.ACCESS_OVERRIDE_ORDER - 1
Integer.MAX_VALUE - 8我认为),现在它的优先级肯定比基本顺序
WebSecurityConfigurerAdapter

这就是为什么从1.4.x迁移到1.5.x后为我显示登录页面的原因

因此,@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)WebSecurityConfigurerAdapter类上设置更优雅和类似Java的样式解决方案

2020-05-30