#spring-mvc #spring-security #spring-security-oauth2
#spring-mvc #spring-безопасность #spring-security-oauth2
Вопрос:
У меня есть следующая конфигурация в Spring Security с OAuth2:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
//@EnableOAuth2Sso
public class FVSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user")
.password("secret")
.roles("USER", "ROLE1")
.and()
.withUser("admin")
.password("password")
.roles("ADMIN","USER");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.anonymous().disable()
.authorizeRequests()
.antMatchers("/api/admin/**").hasRole("ADMIN")
.antMatchers("/api/**").hasRole("USER")
.anyRequest().authenticated()
.and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler())
.and()
.formLogin();
}
Конфигурация сервера ресурсов:
@Configuration
@EnableAuthorizationServer
public class OAuth2Config extends AuthorizationServerConfigurerAdapter {
@Override
public void configure(ClientDetailsServiceConfigurer clients)
throws Exception {
clients.inMemory()
.withClient("sampleClient")
.authorizedGrantTypes("implicit")
.scopes("read")
.autoApprove(true)
.accessTokenValiditySeconds(30)
.and()
.withClient("user")
.secret("secret")
.scopes("read", "write")
.autoApprove(true)
.authorizedGrantTypes(
"password","authorization_code", "refresh_token")
.and()
.withClient("admin")
.secret("password")
.scopes("read", "write", "custom")
.autoApprove(true)
.authorizedGrantTypes(
"password","authorization_code", "refresh_token");
}
И следующий контроллер Rest
@RestController
public class OAuthTestController {
@PreAuthorize("hasRole('ROLE_ROLE1') and #oauth2.hasScope('read')")
@RequestMapping(value="/api/user/test1", method = RequestMethod.GET)
public String testGETWithRole() {
return "[GET] Needs role ROLE1";
}
@RequestMapping(value="/api/admin/test1", method = RequestMethod.GET)
public String testWithAdminRole() {
return "[GET] Needs Admin role";
}
И сервер ресурсов:
@Configuration
@EnableResourceServer
public class ResourceServer extends ResourceServerConfigurerAdapter {
private static final String RESOURCE_ID = "my_rest_api";
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(RESOURCE_ID).stateless(false);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.
anonymous().disable()
.requestMatchers().antMatchers("/api/**")
.and().authorizeRequests()
.antMatchers("/api/**").access("hasRole('USER')")
.antMatchers("/api/admin/**").access("hasRole('ADMIN')")
.and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
}
}
По сути, я ожидаю, что Spring будет использовать OAuth2 для аутентификации и использовать роли безопасности spring для разрешения доступа к ресурсам. Я сгенерировал токен администратора и затем токен пользователя. Я ожидаю, что при использовании токена администратора будет иметь доступ к ресурсу / api / admin, а при использовании токена пользователя — нет. Я только что заметил, что вход в форму запрашивается не всегда, поэтому я полагаю, что Spring запоминает аутентифицированного пользователя.
Когда я использовал токен администратора, мне было отказано в доступе. При отладке в источниках Spring я заметил, что аутентификация была экземпляром UserNamePasswordAuthenticationPassword с данными пользователя, а не администратора, как ожидалось. Я полагаю, это потому, что в прошлый раз я использовал эти учетные данные в форме входа. Это способ заставить spring использовать учетные данные для соответствующего токена или заставлять Spring показывать форму входа каждый раз?
PS Я использую Postman для тестирования API.
Спасибо.
Комментарии:
1. где у вас есть конфигурация вашего сервера ресурсов? Я вижу только конфигурацию сервера авторизации.
2. @bilak, я обновил сообщение с помощью сервера ресурсов.