【问题标题】:SpringBoot 1.5.x + Security + OAuth2Spring Boot 1.5.x + 安全性 + OAuth2
【发布时间】:2017-08-06 23:11:10
【问题描述】:

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

今天我将spring-boot-starter-parent 的版本从1.4.2 升级到1.5.2

变化完全让我感到困惑。

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

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

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

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

security.oauth2.resource.filter-order = 3

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

但是,我的问题是:

  • 这两个版本之间在安全方面发生了什么?
  • 这个“奇怪”的行是唯一有效的修复方法吗?
  • 这个登录页面的目的是什么以及它使用什么身份验证(我检查了谷歌浏览器中的请求和响应,我看不到任何访问令牌和 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();
}
}

【问题讨论】:

    标签: java spring-boot spring-security oauth oauth-2.0


    【解决方案1】:

    好的,我现在知道了。

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

    但是我认为发行说明非常不清楚或遗漏了一些信息。除了 OAuth2 资源过滤器从 3 更改为 SecurityProperties.ACCESS_OVERRIDE_ORDER - 1 之外,关键信息是默认 WebSecurityConfigurerAdapter 顺序为 100 (source)

    因此,在 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 后出现登录页面的原因

    所以,更优雅和类 java 风格的解决方案是在 WebSecurityConfigurerAdapter 类上设置 @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)

    【讨论】:

    • 很好的调查。谢谢。
    • SecurityProperties 无法解析为变量
    • @ilovkatie 我没有单独的WebSecurityConfigurerAdapter。我面临着类似的问题你能帮我吗? stackoverflow.com/questions/65229165/…
    【解决方案2】:

    第一个和第二个问题的答案是Spring Boot 1.5 Release Notes

    OAuth 2 资源过滤器

    OAuth2 资源过滤器的默认顺序已从 3 更改为 SecurityProperties.ACCESS_OVERRIDE_ORDER - 1. 这将它放在 执行器端点,但在基本身份验证过滤器链之前。 可以通过设置恢复默认 security.oauth2.resource.filter-order = 3

    /login 页面只是 spring 重定向未授权用户的路径。由于您没有使用Custom Login Form 并且您的 Oauth2 过滤器位置错误,因此可能使用的是基本身份验证。

    【讨论】:

      【解决方案3】:

      这可能是由于资源服务器配置不正确。

      @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
        }
      

      【讨论】:

        猜你喜欢
        • 2019-12-28
        • 1970-01-01
        • 2018-05-07
        • 2019-02-17
        • 2012-06-15
        • 2021-11-26
        • 2020-06-04
        • 2018-12-05
        • 2021-07-14
        相关资源
        最近更新 更多