2017-03-24 9 views
1

私のアプリケーションにOAuth2認証を設定したいと思います。 私は次の構成を有している:なぜ私はAuthenticationCredentialsNotFoundExceptionを取得していますか?

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

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

} 

@Configuration 
@EnableAuthorizationServer 
@RequiredArgsConstructor(onConstructor = @__(@Autowired)) 
public class OAuth2AuthServerConfig extends AuthorizationServerConfigurerAdapter { 

    private static final String[] GRANT_TYPES = {"password", "refresh_token"}; 
    private static final String[] SCOPES = {"read", "write"}; 

    private final SecurityConfigurationProperties securityConfigurationProperties; 

    private final AuthenticationProvider authenticationProvider; 

    private final OAuth2AccessTokenRepository oAuth2AccessTokenRepository; 
    private final OAuth2RefreshTokenRepository oAuth2RefreshTokenRepository; 

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

    @Override 
    public void configure(final ClientDetailsServiceConfigurer clients) throws Exception { 
     clients.inMemory() 
       .withClient(securityConfigurationProperties.getClientId()) 
       .authorizedGrantTypes(GRANT_TYPES) 
       .authorities(UserRole.USER.getName()) 
       .scopes(SCOPES) 
       .secret(securityConfigurationProperties.getClientSecret()) 
       .accessTokenValiditySeconds(securityConfigurationProperties.getAccessTokenTime()) 
       .refreshTokenValiditySeconds(securityConfigurationProperties.getRefreshTokenTime()); 
    } 

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

    @Bean 
    public AuthenticationManager authenticationManager() { 
     return new ProviderManager(Collections.singletonList(authenticationProvider)); 
    } 

    @Bean 
    public TokenStore tokenStore() { 
     return new MongoTokenStore(oAuth2AccessTokenRepository, oAuth2RefreshTokenRepository); 
    } 

    @Bean 
    @Primary 
    public DefaultTokenServices tokenServices() { 
     final DefaultTokenServices tokenServices = new DefaultTokenServices(); 
     tokenServices.setTokenStore(tokenStore()); 
     tokenServices.setSupportRefreshToken(true); 
     tokenServices.setAuthenticationManager(authenticationManager()); 

     return tokenServices; 
    } 
} 


@Configuration 
@EnableResourceServer 
@RequiredArgsConstructor(onConstructor = @__(@Autowired)) 
public class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter { 

    private static final String RESOURCE_ID = "api"; 

    private final TokenStore tokenStore; 

    @Override 
    public void configure(final ResourceServerSecurityConfigurer resources) { 
     resources.resourceId(RESOURCE_ID) 
       .tokenStore(tokenStore); 
    } 

    @Override 
    public void configure(final HttpSecurity http) throws Exception { 
     http.anonymous().disable() 
       .authorizeRequests() 
       .anyRequest().authenticated() 
       .and() 
       .exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler()); 
    } 
} 

@Configuration 
@EnableWebSecurity 
@RequiredArgsConstructor(onConstructor = @__(@Autowired)) 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 

    private final ApiUserDetailsService apiUserDetailsService; 
    private final AuthenticationProvider authenticationProvider; 

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

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http.csrf().disable() 
       .anonymous().disable() 
       .authorizeRequests() 
       .antMatchers("/").authenticated(); 
    } 
} 

また、私は私のカスタムAuthenticationProviderあります

@Service 
@RequiredArgsConstructor(onConstructor = @__(@Autowired)) 
public class UserAuthenticationProvider implements AuthenticationProvider { 

    private final UserRepository userRepository; 
    private final PasswordEncoder passwordEncoder; 

    @Override 
    public Authentication authenticate(final Authentication authentication) 
      throws AuthenticationException { 
     final String email = authentication.getName(); 
     final String password = authentication.getCredentials().toString(); 

     return userRepository.findByEmail(email) 
       .filter(user -> passwordEncoder.matches(password, user.getPassword())) 
       .map(this::signInUser) 
       .orElseThrow(() -> new BadCredentialsException("Failed to authenticate")); 
    } 

    @Override 
    public boolean supports(final Class<?> authentication) { 
     return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication); 
    } 

    private Authentication signInUser(final User user) { 
     final ApiUser springSecurityUser = 
       new ApiUser(user.getEmail(), user.getPassword(), user.getRoles()); 
     final Authentication authentication = new UsernamePasswordAuthenticationToken(springSecurityUser, 
         user.getId(), springSecurityUser.getAuthorities()); 

     SecurityContextHolder.getContext().setAuthentication(authentication); 

     return authentication; 
    } 
} 

をすべては私が/ OAuthの/トークンエンドポイントからのアクセスとリフレッシュトークンを取得していますが、私は」ときに、トークンのために働きますリソースにアクセスしようとしています@PreAuthorize注釈が間違っています。そのため

リンクはhttp://localhost:8080/users/me?access_token=8450e2f3-2ecb-4e88-b304-685b22c2ad65また、私は、ヘッダー

{ 
    "timestamp": 1490358162182, 
    "status": 403, 
    "error": "Forbidden", 
    "exception": "org.springframework.security.authentication.AuthenticationCredentialsNotFoundException", 
    "message": "Access Denied", 
    "path": "https://stackoverflow.com/users/me" 
} 

私のエンドポイントに"Authorization: Bearer 8450e2f3-2ecb-4e88-b304-685b22c2ad65"を追加しようとしました:

@PreAuthorize("hasRole('ROLE_USER')") 
@RequestMapping(value = RestPath.Users.ME, method = RequestMethod.GET, 
     produces = MediaType.APPLICATION_JSON_UTF8_VALUE) 
public ResponseEntity userInfo() { 
    return ResponseEntity.noContent().build(); 
} 

たぶん誰かが同じ構成で、すでにこのような例外がありました。

答えて

1

私の設定の主な問題はSecurityConfigurationクラスの問題でした。私は、この投稿https://stackoverflow.com/a/42836521/2055854に従って注釈@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)を追加しました。

@Configuration 
@EnableWebSecurity 
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) 
@RequiredArgsConstructor(onConstructor = @__(@Autowired)) 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 

    @Autowired 
    private AuthenticationProvider authenticationProvider; 

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

そして私はまた少し私の構成に変更しました:: は、今では見え予想通り

@Configuration 
public class OAuth2Config { 

    @Configuration 
    @EnableResourceServer 
    @RequiredArgsConstructor(onConstructor = @__(@Autowired)) 
    public static class OAuth2ResourceServerConfig extends ResourceServerConfigurerAdapter { 

     public static final String RESOURCE_ID = "api"; 

     private static final String AUTHORIZATION = "Authorization"; 
     private static final String BEARER = "Bearer"; 
     private static final String ACCESS_TOKEN = "access_token"; 

     private final TokenStore tokenStore; 

     @Override 
     public void configure(final ResourceServerSecurityConfigurer resources) { 
      resources.resourceId(RESOURCE_ID) 
        .tokenStore(tokenStore); 
     } 

     @Override 
     public void configure(final HttpSecurity http) throws Exception { 
      http.csrf().disable() 
        .authorizeRequests().anyRequest().permitAll() 
        .and() 
        .sessionManagement() 
        .sessionCreationPolicy(SessionCreationPolicy.STATELESS) 
        .and() 
        .exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler()); 
     } 
    } 


    @Configuration 
    @EnableAuthorizationServer 
    @RequiredArgsConstructor(onConstructor = @__(@Autowired)) 
    public static class OAuth2AuthServerConfig extends AuthorizationServerConfigurerAdapter { 

     private static final String[] GRANT_TYPES = {"password", "refresh_token"}; 
     private static final String[] SCOPES = {"read", "write"}; 

     private final SecurityConfigurationProperties securityConfigurationProperties; 

     private final AccessTokenRepository oAuth2AccessTokenRepository; 
     private final RefreshTokenRepository oAuth2RefreshTokenRepository; 

     private final AuthenticationProvider authenticationProvider; 
     private final UserDetailsService userDetailsService; 

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

     @Override 
     public void configure(final ClientDetailsServiceConfigurer clients) throws Exception { 
      clients.inMemory() 
        .withClient(securityConfigurationProperties.getClientId()) 
        .authorizedGrantTypes(GRANT_TYPES) 
        .authorities(UserRole.USER.getName()) 
        .secret(securityConfigurationProperties.getClientSecret()) 
        .scopes(SCOPES) 
        .resourceIds(OAuth2ResourceServerConfig.RESOURCE_ID) 
        .accessTokenValiditySeconds(securityConfigurationProperties.getAccessTokenTime()) 
        .refreshTokenValiditySeconds(securityConfigurationProperties.getRefreshTokenTime()); 
     } 

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

     public AuthenticationManager authenticationManager() { 
      return new ProviderManager(Collections.singletonList(authenticationProvider)); 
     } 

     @Bean 
     public TokenStore tokenStore() { 
      return new MongoTokenStore(oAuth2AccessTokenRepository, oAuth2RefreshTokenRepository); 
     } 

     @Bean 
     @Primary 
     public DefaultTokenServices tokenServices() { 
      final DefaultTokenServices tokenServices = new DefaultTokenServices(); 
      tokenServices.setTokenStore(tokenStore()); 
      tokenServices.setSupportRefreshToken(true); 
      tokenServices.setAuthenticationManager(authenticationManager()); 

      return tokenServices; 
     } 
    } 
} 

今、すべての作品を。

関連する問題