В настоящее время мы внедрили централизованный сервер авторизации с использованием протоколов oauth2.0 и потока паролей.Я опубликую user, pwd, secret и clientID на конечной точке сервера аутентификации, получу JWT и буду в пути.
В настоящее время в этом существующем «клиентском» приложении у меня есть образец весенней безопасности, которыйнастраивает трафик на основе ролей.
Что мне нужно сделать, это (я думаю) - Когда я войду в приложение, я получу токен.Этот токен хранится в сеансе, и всякий раз, когда я получаю доступ к странице в этом приложении, я либо подтверждаю, что токен по-прежнему исправен, либо обновляю токен, чтобы продолжить доступ к защищенному контенту.
Я предполагаю, что мне нужносделать следующее:
- Добавить сервер ресурсов в мое существующее приложение (@EnableResourceServer), чтобы трафик проходил через процесс oauth2.0.
- Настройте указанный сервер ресурсов (аналогичнов мой класс конфигурации WebSecurityConfigurerAdapter), чтобы токен был проверен
- Оставьте все остальное (роли, файловую структуру и т. д.) таким же
Как мне это сделать с помощью Spring?Я посмотрел учебные пособия, и большинство из них - это либо решения для домашнего ресурса, либо для сервера аутентификации, либо есть минимальное объяснение того, как что-то можно настроить.
Файл свойств:
security.oauth2.client.client-id= clientid
security.oauth2.client.client-secret= clientsecret
security.oauth2.client.access-token-uri= http://localhost:1234/oauth/token
security.oauth2.client.user-authorization-uri= http://localhost:1234/oauth/authorize
security.oauth2.resource.service-id=res_id
security.oauth2.resource.user-info-uri= http://localhost:1234/me
security.oauth2.resource.token-info-uri= http://localhost:1234/oauth/check_token
security.oauth2.resource.token-type= Bearer
Текущий WebSecurityConfigurerAdapter:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@ComponentScan("com.testproj")
public class CustomWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Autowired
private CustomAuthenticationProvider authProvider;
@Override
protected void configure(HttpSecurity http) throws Exception {
// Authentication control
http
.authorizeRequests()
.antMatchers("/login.xhtml**").permitAll() // All everyone to see login page
.antMatchers("/login").permitAll() // All everyone to see login page
.antMatchers("/views/**").hasAnyAuthority("USER", "ADMIN")
.antMatchers("/javax.faces.resource/**").permitAll() // All everyone to see resources
.antMatchers("/resources/**").permitAll() // All everyone to see resources
.anyRequest().authenticated(); // Ensure any request to application is authenticated
// Login control
http
.formLogin()
.loginPage("/login.xhtml")
.loginProcessingUrl("/login")
.successForwardUrl("/views/home.xhtml")
.failureUrl("/login.xhtml?error=true");
// not needed as JSF 2.2 is implicitly protected against CSRF
http
.csrf().disable();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authProvider);
}
}
Пользовательский аутентификатор:
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Autowired
private AppUserDAO appUserDAO;
private String accessTokenUri = "http://localhost:1234/oauth/token";
private String clientId = "clientid";
private String clientSecret = "clientsecret";
public AccessTokenProvider userAccessTokenProvider() {
ResourceOwnerPasswordAccessTokenProvider accessTokenProvider = new ResourceOwnerPasswordAccessTokenProvider();
return accessTokenProvider;
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
final String username = authentication.getName();
final String password = authentication.getCredentials().toString();
List<String> scopes = new ArrayList<String>();
scopes.add("read");
final ResourceOwnerPasswordResourceDetails resource = new ResourceOwnerPasswordResourceDetails();
resource.setUsername(username);
resource.setPassword(password);
resource.setAccessTokenUri(accessTokenUri);
resource.setClientId(clientId);
resource.setClientSecret(clientSecret);
resource.setGrantType("password");
resource.setScope(scopes);
// Generate an access token
final OAuth2RestTemplate template = new OAuth2RestTemplate(resource, new DefaultOAuth2ClientContext(new DefaultAccessTokenRequest()));
template.setAccessTokenProvider(userAccessTokenProvider());
OAuth2AccessToken accessToken = null;
try {
accessToken = template.getAccessToken();
System.out.println("Grabbed access token from " + accessTokenUri);
}
catch (OAuth2AccessDeniedException e) {
if (e.getCause() instanceof ResourceAccessException) {
final String errorMessage = String.format(
"While authenticating user '%s': " + "Unable to access accessTokenUri '%s'.", username,
accessTokenUri);
throw new AuthenticationServiceException(errorMessage, e);
}
throw new BadCredentialsException(String.format("Access denied for user '%s'.", username), e);
}
catch (OAuth2Exception e) {
throw new AuthenticationServiceException(
String.format("Unable to perform OAuth authentication for user '%s'.", username), e);
}
// Determine roles for user
List<GrantedAuthority> grantList = ...
// Create custom user for the principal
User user = .....
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user, null /*dont store password*/, grantList);
return token;
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
Сервер ресурсов:
@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
????
}
Редактировать :
Поэтому я переместил свойКонфигурация httpsecurity в конфигурацию моего сервера ресурсов, и я получаю сообщение «Отказано в доступе» при попытке перейти на страницу /views/home.xhtml.
В журнале указывается, что принципал является анонимным (в отличие отsecurityconfig)
Secure object: FilterInvocation: URL: /views/home.xhtml; Attributes: [#oauth2.throwOnError(hasAuthority('USER'))]
Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@fc4a062: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true;
Edit 2
Это может быть вопрос о том, что возможно с oauth2, потому что я немного схожу с ума.
В соответствии со спецификацией oauth существует 4 компонента - Auth-сервер, сервер ресурсов, клиент и владелец ресурса
Наверное, мой вопрос - могу ли я на самом деле объединить сервер ресурсов и клиент?Владелец ресурса будет входить в мое приложение (клиент), получать авторизацию от сервера авторизации для просмотра своих ресурсов на сервере / клиенте ресурсов.
Мне бы очень хотелось найти хороший пример этого - кажется, такокончательный и общий.