繁体   English   中英

在Spring Boot中将Oauth2与formlogin和执行器安全性结合起来

[英]Combining Oauth2 with formlogin and actuator security in Spring Boot

我正在使用Spring Boot 1.5.9,并且有一个应用程序具有使用OAuth2客户端凭据的API,而formlogin用于在同一个Spring Boot应用程序中使用Thymeleaf的CMS。

为此,我有以下bean来配置表单登录:

@Configuration
public class WebSecurityGlobalConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;
    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        auth.userDetailsService(userDetailsService)
            .passwordEncoder(passwordEncoder);
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring()
           .antMatchers(HttpMethod.OPTIONS);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            // api security is handled elsewhere (See OAuth2ServerConfiguration)
            .antMatchers("/api/**", "/oauth/**", "/management/**")
            .permitAll()
            // end api security
            .anyRequest().hasRole(UserRole.ADMIN.name())
            .and()
            .formLogin().loginPage("/login")
            .permitAll()
            .and()
            .logout().permitAll();
    }
}

因此,对于表单登录部分,我声明了与API,Oauth和/ management相关的所有内容(我在application.properties为执行器端点设置的自定义上下文路径):

management.context-path=/management
management.security.roles=ADMIN

对于Oauth2,我有这个:

@Configuration
public class OAuth2ServerConfiguration {

    private static final String RESOURCE_ID = "my-app-service";

    @Configuration
    @EnableResourceServer
    @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
    protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

        @Override
        public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
            resources.resourceId(RESOURCE_ID);
        }

        @Override
        public void configure(HttpSecurity http) throws Exception {

            http.authorizeRequests()
                .antMatchers(HttpMethod.OPTIONS, "/api/**")
                .permitAll()
                .and()
                .antMatcher("/api/**")
                .authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .authorizeRequests()
                .antMatchers("/management/health", "/management/info").permitAll()
                .antMatchers("/management/**").hasRole(UserRole.ADMIN.name())
                .anyRequest().authenticated();
        }
    }

    @Configuration
    @EnableAuthorizationServer
    protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

        @Autowired
        private AuthenticationManager authenticationManager;

        @Autowired
        private UserDetailsService userDetailsService;

        @Autowired
        private PasswordEncoder passwordEncoder;

        @Autowired
        private TokenStore tokenStore;

        @Autowired
        private SecurityConfiguration securityConfiguration;

        // NOTE: If you set a new validity, you need to clear the 'oauth_access_token' table
        // in the database. Only new tokens get the new validity.
        @Value("${myapp.security.oauth.access-token-validity-seconds:43200}") // 12 hours by default
        private int accessTokenValiditySeconds;

        @Value("${myapp.security.oauth.refresh-token-validity-seconds:2592000}") // 30 days by default
        private int refreshTokenValiditySeconds;

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

        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients.inMemory()
                   .withClient(securityConfiguration.getMobileAppClientId())
                   .authorizedGrantTypes("password", "refresh_token")
                   .scopes("mobile_app")
                   .resourceIds(RESOURCE_ID)
                   .accessTokenValiditySeconds(accessTokenValiditySeconds)
                   .refreshTokenValiditySeconds(refreshTokenValiditySeconds)
                   .secret(passwordEncoder.encode(securityConfiguration.getMobileAppClientSecret()));
        }

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

我想要以下行为:

  • 如果用户使用Oauth2访问令牌具有角色ADMIN ,则必须可以访问所有执行器端点
  • 如果用户没有此ADMIN角色,则只能访问/health/info (如果ADMIN/health应显示默认情况下的额外信息)

目前的行为:

每个人都可以查看信息和健康端点,但作为ADMIN,您无法获得额外信息。 对于其他端点,如果我尝试使用ADMIN用户的访问令牌,则会获得401:

{
    "timestamp": "2018-01-30T13:45:26.625+0000",
    "status": 401,
    "error": "Unauthorized",
    "message": "Full authentication is required to access this resource.",
    "path": "/management/beans"
} 

如果我设置management.security.enabled=false则ADMIN用户具有访问权限,但所有非ADMIN用户也具有访问权限。

我应该改变什么来获得想要的行为?

我设法使它在ResourceServerConfigurationconfigure方法中使用以下内容:

http
            .requestMatchers()
                .antMatchers("/api/**")
                .and()
                .authorizeRequests()
                .antMatchers(HttpMethod.OPTIONS, "/api/**")
                .permitAll()
                .and()
            .requestMatchers()
                .antMatchers("/api/**")
                .and()
                .authorizeRequests()
                .and()
            .requestMatchers()
                .antMatchers("/management/**")
                .and()
                .authorizeRequests()
                .antMatchers("/management/health", "/management/info").permitAll()
                .antMatchers("/management/**").hasRole(UserRole.ADMIN.name())
            .anyRequest()
            .authenticated()

直接在http对象上使用多个antMatchers不起作用,您需要首先使用requestMatchers

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM