简体   繁体   中英

Oauth2 Resource server overlap Spring Security configuration

I am trying to configure Spring Security and OAuth2 on java config. I am using Spring Security version 4.0.4.RELEASE and OAuth2 version 2.0.11.RELEASE.

Spring Security config works well. Also I can get an access token with OAuth2 AuthorizationServer, but my ResourceServer does not work correctly. When I set the annotation @EnableResourceServer I can only check my access token and other URLs I cannot open (Security configuration and AuthorizationServer configuration do not work). I see the following error:

<oauth>
  <error_description>
     An Authentication object was not found in the SecurityContext
  </error_description>
  <error>unauthorized</error>
</oauth>

If I remove an annotation @EnableResourceServer, my ResourceServer does not check an access token. It just redirects to the authentication page.

This is my code:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
public class GlobalSecurityConfig extends GlobalMethodSecurityConfiguration {

    @Bean(name = "passwordEncoder")
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }


    @Autowired
    @Qualifier("authUserDetailsService")
    private UserDetailsService userDetailsService;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .userDetailsService(userDetailsService)
                .passwordEncoder(passwordEncoder());
    }

    @Autowired
    @Qualifier("permissionEvaluator")
    private PermissionEvaluator permissionEvaluator;


    @Bean
    public DefaultMethodSecurityExpressionHandler expressionHandler() {
        DefaultMethodSecurityExpressionHandler handler = new DefaultMethodSecurityExpressionHandler();
        handler.setDefaultRolePrefix("");
        handler.setPermissionEvaluator(permissionEvaluator);
        return handler;
    }

    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        return expressionHandler();
    }

}

SecurityConfig:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean(name = "clientAuthenticationEntryPoint")
    public OAuth2AuthenticationEntryPoint oauthAuthenticationEntryPoint() {
        OAuth2AuthenticationEntryPoint entry = new OAuth2AuthenticationEntryPoint();
        entry.setRealmName("myapp/client");
        entry.setTypeName("Basic");
        return entry;
    }

    @Autowired
    @Qualifier("webExpressionHandler")
    private DefaultWebSecurityExpressionHandler expressionHandler;


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

    @Bean
    public SessionRegistry sessionRegistry() {
        return new SessionRegistryImpl();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring()
                .antMatchers("/html/**", "/webapi/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .requestMatchers().antMatchers("/admin/**", "/**")
                .and()

                .authorizeRequests()

                .expressionHandler(expressionHandler)

                .antMatchers("/admin/**").access("hasRole('ADMINISTRATOR')")
                .antMatchers("/1/admin/**").access("hasRole('ADMINISTRATOR')")
                .antMatchers("/profile**").authenticated()
                .antMatchers("/oauth/authorize").authenticated()
                .and()
                .formLogin().loginPage("/login")
                .failureUrl("/login?error=1")
                .loginProcessingUrl("/login-attempt")
                .defaultSuccessUrl("/", false)
                .and()
                .sessionManagement()
                .sessionFixation().migrateSession()
                .and()

                .logout()
                .logoutUrl("/logout")
                .logoutSuccessUrl("/")

                .and()
                .exceptionHandling()
                .accessDeniedPage("/access-denied")
                .and()
                .csrf();
    }
}

Oauth config:

@Configuration
public class Oauth {

    @Configuration
    @EnableResourceServer
    public static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

        private static final String RESOURCE_ID = "my_oauth_server";

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

        @Override
        public void configure(HttpSecurity http) throws Exception {
            http
                    .anonymous().disable()
                    .sessionManagement()
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                    .and()
                    .authorizeRequests()

                    .regexMatchers("/api/v0/.*").authenticated()
                    .antMatchers("/**").denyAll()
            ;

        }
    }

    @Configuration
    @EnableAuthorizationServer
    protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
        @Autowired
        private AuthenticationManager authenticationManager;

        @Autowired
        private AuthorizationCodeServices verificationCodeService;

        @Autowired
        @Qualifier("clientDetails")
        private ClientDetailsService clientDetailsService;

        @Autowired
        @Qualifier("tokenStore")
        private TokenStore tokenStore;

        @Bean(name = "tokenServices")
        public DefaultTokenServices tokenServices() {
            DefaultTokenServices tokenServices = new DefaultTokenServices();
            tokenServices.setTokenStore(tokenStore);
            tokenServices.setSupportRefreshToken(true);
            tokenServices.setClientDetailsService(clientDetailsService);
            return tokenServices;
        }

        @Bean
        public ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter() throws Exception {
            ClientCredentialsTokenEndpointFilter filter = new ClientCredentialsTokenEndpointFilter();
            filter.setAuthenticationManager(authenticationManager);
            return filter;
        }

        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients.withClientDetails(clientDetailsService);
        }

        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints.authenticationManager(authenticationManager);
            endpoints.authorizationCodeServices(verificationCodeService);
            endpoints.tokenServices(tokenServices());
            endpoints.reuseRefreshTokens(true);
        }


        @Override
        public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
            oauthServer.tokenKeyAccess("permitAll()");
            oauthServer.checkTokenAccess("permitAll()");
            oauthServer.realm("myapp/client");
            oauthServer.addTokenEndpointAuthenticationFilter(clientCredentialsTokenEndpointFilter());
            oauthServer.allowFormAuthenticationForClients();
        }
    }
}

So, ResourceServer config overlap other configuration. How can I fix it? I would be thankful for any help.

I see that you want to protect some endpoints with an access token, and other endpoints with normal form login.

Can you try restricting the applicability of your ResourceServerConfiguration to apply only to certain endpoints by something like: http.requestMatcher(new AntPathRequestMatcher("/api/v0/**"))... . Do the same for SecurityConfig but for the endpoints you want it to take care of.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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