내 응용 프로그램에 대해 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
annotation 오류가 발생했습니다. 그것은 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();
}
아마 누군가가 같은 구성으로 이미 예외를했다.