2017-07-15 4982 views
0

我正在使用spring security oauth2實施授權。我有單獨的授權服務器和資源服務器。爲什麼permitAll()不起作用,並要求在請求中提供認證對象?

資源服務器代碼:

OauthResourceServerConfig.java

import org.springframework.beans.factory.annotation.Value; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.context.annotation.Primary; 
import org.springframework.security.config.annotation.web.builders.HttpSecurity; 
import org.springframework.security.config.http.SessionCreationPolicy; 
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; 
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; 
import org.springframework.security.oauth2.provider.authentication.BearerTokenExtractor; 
import org.springframework.security.oauth2.provider.authentication.TokenExtractor; 
import org.springframework.security.oauth2.provider.token.AccessTokenConverter; 
import org.springframework.security.oauth2.provider.token.RemoteTokenServices; 
import org.springframework.security.web.util.matcher.AntPathRequestMatcher; 


@Configuration 
@EnableResourceServer 
public class OAuthResourceConfig extends ResourceServerConfigurerAdapter { 

    private TokenExtractor tokenExtractor = new BearerTokenExtractor(); 

    @Override 
    public void configure(HttpSecurity http) throws Exception { 
     http. 
     exceptionHandling() 
     .and() 
     .csrf() 
     .requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/authorize")) 
     .disable() 
     .headers() 
     .frameOptions().disable().disable() 
     .sessionManagement() 
     .sessionCreationPolicy(SessionCreationPolicy.STATELESS) 
     .and() 
     .authorizeRequests() 
     .antMatchers("/secure/**").permitAll() //<<<<<<<<<<<<<<<<<<<<<<<<<< 
     .antMatchers("/hello/**").authenticated(); // <<<<<<<<<<<<<<<<<<<<< 
    } 

    @Bean 
    public AccessTokenConverter accessTokenConverter() { 
     return new CustomAccessTokenConverter(); 
    } 

    @Bean 
    @Primary 
    public RemoteTokenServices remoteTokenServices(final @Value("${auth.server.url}") String checkTokenUrl, 
      final @Value("${auth.server.clientId}") String clientId, 
      final @Value("${auth.server.clientsecret}") String clientSecret) { 

     final RemoteTokenServices remoteTokenServices = new RemoteTokenServices(); 
     remoteTokenServices.setCheckTokenEndpointUrl(checkTokenUrl); 
     remoteTokenServices.setClientId(clientId); 
     remoteTokenServices.setClientSecret(clientSecret); 
     remoteTokenServices.setAccessTokenConverter(accessTokenConverter()); 
     return remoteTokenServices; 
    } 
} 

控制器:

@Controller 
@RequestMapping("/secure") 
public class SecureController { 

    @RequestMapping(method = RequestMethod.GET) 
    @ResponseBody 
    public String sayHello() { 


     return "Secure Hello!"; 
    } 

} 

授權服務器代碼:

Oauth2Configuration.java

import javax.sql.DataSource; 

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.beans.factory.annotation.Qualifier; 
import org.springframework.boot.bind.RelaxedPropertyResolver; 
import org.springframework.context.EnvironmentAware; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.core.env.Environment; 
import org.springframework.security.authentication.AuthenticationManager; 
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; 
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; 
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; 
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; 
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; 
import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter; 
import org.springframework.security.oauth2.provider.token.TokenEnhancer; 
import org.springframework.security.oauth2.provider.token.TokenStore; 
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore; 

import com.pedagogy.authserver.security.Authorities; 

@Configuration 
public class OAuth2Configuration { 


    @Configuration 
    @EnableAuthorizationServer 
    protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter implements EnvironmentAware { 

     private static final String ENV_OAUTH = "authentication.oauth."; 
     //private static final String PROP_CLIENTID = "clientid"; 
     //private static final String PROP_SECRET = "secret"; 
     private static final String PROP_ACCESS_TOKEN_VALIDITY_SECONDS = "accessTokenValidityInSeconds"; 
     private static final String PROP_REFRESH_TOKEN_VALIDITY_SECONDS = "refreshTokenValidityInSeconds"; 

     private RelaxedPropertyResolver propertyResolver; 

     @Autowired 
     private DataSource dataSource; 

     @Autowired 
     private CustomUserDetailService userDetailsService; 

     @Bean 
     public TokenStore tokenStore() { 
      return new JdbcTokenStore(dataSource); 
     } 

     @Autowired 
     @Qualifier("authenticationManagerBean") 
     private AuthenticationManager authenticationManager; 

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

     @Bean 
     public TokenEnhancer tokenEnhancer() { 
      return new CustomTokenEnhancer(); 
     } 

     @Bean 
     public DefaultAccessTokenConverter accessTokenConverter() { 
      return new DefaultAccessTokenConverter(); 
     } 

     @Override 
     public void configure(AuthorizationServerSecurityConfigurer oauthServer) 
       throws Exception { 
      oauthServer 
       .tokenKeyAccess("permitAll()") 
       .checkTokenAccess("isAuthenticated()"); 
     } 


     @Override 
     public void configure(ClientDetailsServiceConfigurer clients) throws Exception { 
      clients 
        .inMemory() 

        .withClient("clientId") 
        .scopes("read", "write") 
        .authorities(Authorities.ROLE_ADMIN.name(), Authorities.ROLE_USER.name()) 
        .authorizedGrantTypes("password", "refresh_token") 
        .accessTokenValiditySeconds(propertyResolver.getProperty(PROP_ACCESS_TOKEN_VALIDITY_SECONDS, Integer.class, 80)) 
        .refreshTokenValiditySeconds(propertyResolver.getProperty(PROP_REFRESH_TOKEN_VALIDITY_SECONDS, Integer.class, 180)) 

        .and().inMemory() 
        .withClient("clientid") 
        .scopes("read", "write") 
        .authorities(Authorities.ROLE_ADMIN.name(), Authorities.ROLE_USER.name()) 
        .authorizedGrantTypes("client_credentials") 
        .secret("secret"); 

     } 

     @Override 
     public void setEnvironment(Environment environment) { 
      this.propertyResolver = new RelaxedPropertyResolver(environment, ENV_OAUTH); 
     } 

    } 

} 

SecurityConfiguration.java

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler; 
import org.springframework.security.authentication.AuthenticationManager; 
import org.springframework.security.authentication.dao.DaoAuthenticationProvider; 
import org.springframework.security.authentication.encoding.ShaPasswordEncoder; 
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration; 
import org.springframework.security.config.annotation.web.builders.HttpSecurity; 
import org.springframework.security.config.annotation.web.builders.WebSecurity; 
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 
import org.springframework.security.crypto.password.PasswordEncoder; 
import org.springframework.security.crypto.password.StandardPasswordEncoder; 
import org.springframework.security.oauth2.provider.expression.OAuth2MethodSecurityExpressionHandler; 


@Configuration 
@EnableWebSecurity 
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { 

    @Autowired 
    private CustomUserDetailService userDetailsService; 

    @Bean 
    public PasswordEncoder passwordEncoder() { 
     return new StandardPasswordEncoder(); 
    } 

    @Override 
    protected void configure(AuthenticationManagerBuilder auth) 
     throws Exception { 
     auth.authenticationProvider(authenticationProvider()); 
    } 

    @Bean 
    public DaoAuthenticationProvider authenticationProvider() { 
     DaoAuthenticationProvider authProvider 
      = new DaoAuthenticationProvider(); 
     authProvider.setUserDetailsService(userDetailsService); 
     authProvider.setPasswordEncoder(encoder()); 
     return authProvider; 
    } 

    @Bean 
    public ShaPasswordEncoder encoder() { 
     return new ShaPasswordEncoder(256); 
    } 

    @Override 
    public void configure(WebSecurity web) throws Exception {} 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http.csrf().disable(); 

    } 

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

    @EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true) 
    private static class GlobalSecurityConfiguration extends GlobalMethodSecurityConfiguration { 

     public GlobalSecurityConfiguration() { 
     } 
     @Override 
     protected MethodSecurityExpressionHandler createExpressionHandler() { 
      return new OAuth2MethodSecurityExpressionHandler(); 
     } 

    } 

} 

當我在做郵遞員http://localhost:8889/secure?lang=en電話,我得到錯誤:

{ 
    "error": "unauthorized", 
    "error_description": "An Authentication object was not found in the SecurityContext" 
} 

我已經配置/secure端點permitAll(),所以它不應該要求通過訪問令牌。爲什麼permitAll()在這種情況下不起作用?

我也嘗試通過允許所有請求,但它也沒有工作,並面對同樣的錯誤作出迴應。

@Override 
    public void configure(HttpSecurity http) throws Exception { 
    http.authorizeRequests().anyRequest().permitAll(); 
} 
+0

認證和授權是兩回事。 'permitAll'適用於授權。您仍然需要進行身份驗證。 – tsolakp

回答

0

我已經配置下面的網址,它現在正在工作。

.antMatchers("/hello/").permitAll() 
       .antMatchers("/secure3/").permitAll() 
       .antMatchers("/secure/**").authenticated() 
       .antMatchers("/secure2/**").authenticated(); 

我已經添加了那些安全*控制器進行測試並驗證它正在工作。