簡體   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