web-dev-qa-db-de.com

Spring Boot: Oauth2: Zugriff wird verweigert (Benutzer ist anonym); Umleitung zum Authentifizierungs-Einstiegspunkt

Ich versuche Spring Boot oauth2 zu verwenden, um zustandslose Authentifizierung und Autorisierung durchzuführen. Ich habe jedoch Schwierigkeiten damit zu arbeiten.

Hier ist mein Code:

@EnableAutoConfiguration
@ComponentScan
//@EnableEurekaClient
//@EnableZuulProxy
@Configuration
public class AuthServiceApp {

  public static void main(String[] args) {
    SpringApplication.run(AuthServiceApp.class, args);
  }
}

Berechtigungskonfiguration:

@Configuration
@EnableAuthorizationServer
public class Oauth2ServerConfig extends AuthorizationServerConfigurerAdapter {

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

  @Autowired
  private DataSource dataSource;

  @Autowired
  private CustomUserDetailsService userDetailService;

  @Autowired
  private ClientDetailsService clientDetailsService;


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

  @Bean
  protected AuthorizationCodeServices authorizationCodeServices() {
    return new JdbcAuthorizationCodeServices(dataSource);
  }

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

  @Override
  public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    // @OFF
    endpoints
          .authorizationCodeServices(authorizationCodeServices())
          .authenticationManager(auth)
          .userDetailsService(userDetailService)
          .tokenStore(tokenStore());
    // @ON
  }


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

    // @OFF
    clients.jdbc(dataSource)
           .withClient("client")
           .secret("secret")
           .authorizedGrantTypes("password","refresh_token", "client_credentials")
           .authorities("USER")
           .scopes("read", "write")
           .autoApprove(true)
           .accessTokenValiditySeconds(60)
           .refreshTokenValiditySeconds(300);
    // @ON
  }
}

Ressourcenserver-Konfiguration:

@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
class ResourceServerConfig extends ResourceServerConfigurerAdapter {


  @Autowired
  private CustomAuthenticationEntryPoint customAuthenticationEntryPoint;

  @Autowired
  private CustomLogoutSuccessHandler customLogoutSuccessHandler;


  @Override
  public void configure(HttpSecurity http) throws Exception {
    // @OFF
          http
              .sessionManagement()
              .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
              .and()
              .exceptionHandling()
              .authenticationEntryPoint(customAuthenticationEntryPoint)
              .and()
              .logout()
              .logoutUrl("/oauth/logout")
              .logoutSuccessHandler(customLogoutSuccessHandler)
              .and()
              .csrf()
//            .requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/authorize"))
              .disable()
              .headers()
              .frameOptions().disable()
              .and()
              .authorizeRequests()
              .antMatchers("/identity/**").authenticated();
   // @ON
  }
}


@Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

  @Autowired
  private CustomUserDetailsService userDetailsService;

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

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

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    // @OFF
    http
        .csrf()
        .disable()
        .authorizeRequests()
        .antMatchers("/login").permitAll()
        .anyRequest().authenticated()
        .and()
        .formLogin().permitAll();
   // @ON
  }
}

Controller:

@RestController
@RequestMapping("/")
public class AuthController {

  @PreAuthorize("#oauth2.hasScope('read')")
  @GetMapping("/user")
  public Principal getUser(Principal user) {
     return user;
  }
}

Ich kann das Zugriffstoken mit POSTMAN erhalten. Ich verwende dasselbe Zugriffstoken im Header, um die Benutzerdetails als http://localhost:8082/identity/user abzurufen, bevor es abgelaufen ist. Ich erhalte jedoch eine Login-HTML-Antwort mit folgendem Login in der Konsole:

2017-05-24 22:55:16.070 DEBUG 16899 --- [nio-8082-exec-9] o.s.s.w.a.AnonymousAuthenticationFilter  : Populated SecurityContextHolder with anonymous token: 'org.sprin[email protected]9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.sprin[email protected]b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 301C6EDD36372CF9C553FCFCD4AA47E3; Granted Authorities: ROLE_ANONYMOUS'
2017-05-24 22:55:16.070 DEBUG 16899 --- [nio-8082-exec-9] o.s.security.web.FilterChainProxy        : /user at position 10 of 12 in additional filter chain; firing Filter: 'SessionManagementFilter'
2017-05-24 22:55:16.070 DEBUG 16899 --- [nio-8082-exec-9] o.s.security.web.FilterChainProxy        : /user at position 11 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2017-05-24 22:55:16.070 DEBUG 16899 --- [nio-8082-exec-9] o.s.security.web.FilterChainProxy        : /user at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2017-05-24 22:55:16.070 DEBUG 16899 --- [nio-8082-exec-9] o.s.s.w.u.matcher.AntPathRequestMatcher  : Checking match of request : '/user'; against '/login'
2017-05-24 22:55:16.070 DEBUG 16899 --- [nio-8082-exec-9] o.s.s.w.a.i.FilterSecurityInterceptor    : Secure object: FilterInvocation: URL: /user; Attributes: [authenticated]
2017-05-24 22:55:16.071 DEBUG 16899 --- [nio-8082-exec-9] o.s.s.w.a.i.FilterSecurityInterceptor    : Previously Authenticated: org.sprin[email protected]9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.sprin[email protected]b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 301C6EDD36372CF9C553FCFCD4AA47E3; Granted Authorities: ROLE_ANONYMOUS
2017-05-24 22:55:16.071 DEBUG 16899 --- [nio-8082-exec-9] o.s.s.access.vote.AffirmativeBased       : Voter: org.sp[email protected]55b4f25d, returned: -1
2017-05-24 22:55:16.071 DEBUG 16899 --- [nio-8082-exec-9] o.s.s.w.a.ExceptionTranslationFilter     : Access is denied (user is anonymous); redirecting to authentication entry point

org.springframework.security.access.AccessDeniedException: Access is denied
    at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.Java:84) ~[spring-security-core-4.2.2.RELEASE.jar:4.2.2.RELEASE]

Es scheint jedoch, als wäre ich beim ersten Aufruf authentifiziert worden, um das Zugriffstoken zu oauth/token zu erhalten:

2017-05-24 22:54:35.966 DEBUG 16899 --- [nio-8082-exec-6] o.s.s.w.a.i.FilterSecurityInterceptor    : Secure object: FilterInvocation: URL: /oauth/token; Attributes: [fullyAuthenticated]
2017-05-24 22:54:35.966 DEBUG 16899 --- [nio-8082-exec-6] o.s.s.w.a.i.FilterSecurityInterceptor    : Previously Authenticated: org.springframew[email protected]50c8f5e8: Principal: [email protected]: Username: client; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: USER; Credentials: [PROTECTED]; Authenticated: true; Details: org.sprin[email protected]21a2c: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: 2F070B741A55BD1E47933621D9127780; Granted Authorities: USER
2017-05-24 22:54:35.966 DEBUG 16899 --- [nio-8082-exec-6] o.s.s.access.vote.AffirmativeBased       : Voter: org.sp[email protected]61f8721f, returned: 1
2017-05-24 22:54:35.966 DEBUG 16899 --- [nio-8082-exec-6] o.s.s.w.a.i.FilterSecurityInterceptor    : Authorization successful
2017-05-24 22:54:35.966 DEBUG 16899 --- [nio-8082-exec-6] o.s.s.w.a.i.FilterSecurityInterceptor    : RunAsManager did not change Authentication object
2017-05-24 22:54:35.966 DEBUG 16899 --- [nio-8082-exec-6] o.s.security.web.FilterChainProxy        : /oauth/token reached end of additional filter chain; proceeding with original chain
2017-05-24 22:54:35.967 DEBUG 16899 --- [nio-8082-exec-6] .s.o.p.e.FrameworkEndpointHandlerMapping : Looking up handler method for path /oauth/token
2017-05-24 22:54:35.968 DEBUG 16899 --- [nio-8082-exec-6] .s.o.p.e.FrameworkEndpointHandlerMapping : Returning handler method [public org.springframework.http.ResponseEntity<org.springframework.security.oauth2.common.OAuth2AccessToken> org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(Java.security.Principal,Java.util.Map<Java.lang.String, Java.lang.String>) throws org.springframework.web.HttpRequestMethodNotSupportedException]
2017-05-24 22:54:35.975 DEBUG 16899 --- [nio-8082-exec-6] .o.p.p.ResourceOwnerPasswordTokenGranter : Getting access token for: client
2017-05-24 22:54:35.975 DEBUG 16899 --- [nio-8082-exec-6] o.s.s.authentication.ProviderManager     : Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
Hibernate: select user0_.id as id1_1_, user0_.enabled as enabled2_1_, user0_.name as name3_1_, user0_.password as password4_1_, user0_.username as username5_1_ from user user0_ where user0_.username=?
Hibernate: select roles0_.user_id as user_id1_2_0_, roles0_.role_id as role_id2_2_0_, role1_.id as id1_0_1_, role1_.role as role2_0_1_ from user_role roles0_ inner join role role1_ on roles0_.role_id=role1_.id where roles0_.user_id=?
2017-05-24 22:54:36.125  INFO 16899 --- [nio-8082-exec-6] o.s.s.o.p.token.store.JdbcTokenStore     : Failed to find access token for token 180c2528-b712-4088-9cce-71e9cc7ccb94
2017-05-24 22:54:36.232 DEBUG 16899 --- [nio-8082-exec-6] o.s.s.w.a.ExceptionTranslationFilter     : Chain processed normally
2017-05-24 22:54:36.232 DEBUG 16899 --- [nio-8082-exec-6] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed

Möglicherweise konfiguriere ich etwas falsch. Was fehlt mir hier?

6
cosmos

Ich hatte ein ähnliches Problem und stellte fest, dass der OAuth2AuthenticationProcessingFilter nicht von der Filterkette aufgerufen wurde und aufgrund dessen der Benutzer nicht authentifiziert wurde und daher als anonym behandelt wurde.

Ich verwende die Version Spring-boot 1.5.3 und fügte in application.yml die folgende Zeile hinzu, um die Bestellung zu korrigieren.

security.oauth2.resource.filter-order=3

Es muss eine Protokollanweisung vorhanden sein, aus der hervorgeht, dass es aufgerufen wird

DEBUG 34386 --- [nio-8082-exec-1] o.s.security.web.FilterChainProxy        : /foo at position 5 of 11 in additional filter chain; firing Filter: 'OAuth2AuthenticationProcessingFilter'

Referenz - https://github.com/spring-projects/spring-security-oauth/issues/993

12
Rites

Ich war mit dem gleichen Problem konfrontiert und konnte dieses Problem beheben, indem ich die automatische Konfiguration der Frühjahrskonfiguration explizit deaktivierte:

@EnableAutoConfiguration(exclude = [OAuth2AutoConfiguration::class,
   SecurityAutoConfiguration::class, SecurityFilterAutoConfiguration::class])
0
Michael Gloegl

Benutzen

.authorizedGrantTypes("password","refresh_token", "client_credentials")

sie müssen den Zugang zu öffnen

/auth/token

in der Sicherheitskonfiguration Ihres Autorisierungsservers

@Override
protected void configure(HttpSecurity http) throws Exception {
    code...
    http
        .antMatcher("/**")
        .authorizeRequests()
            .antMatchers("/oauth/token").permitAll()
        .anyRequest().authenticated()
    code...     
} 
0
ejazazeem