Клиентский режим OAuth2 — это режим авторизации OAuth2. Он подходит для сценариев авторизации между клиентом и сервером, например, когда сторонним приложениям требуется доступ к защищенным ресурсам. Клиентский режим не требует участия пользователя. Клиент запрашивает токен доступа от сервера авторизации посредством собственной аутентификации личности, а затем использует токен доступа для доступа к защищенным ресурсам.
Процесс работы в клиентском режиме выглядит следующим образом:
Spring Security OAuth2 предоставляет полную реализацию OAuth2, включая сервер авторизации и сервер ресурсов. Ниже представлена подробная документация и примеры реализации клиентского режима с использованием Spring Security OAuth2:
Прежде чем мы начнем, нам нужно добавить зависимости для Spring Security OAuth2 и Spring Security Web. В проекте Maven в файл pom.xml можно добавить следующие зависимости:
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.5.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>5.5.0</version>
</dependency>
Нам нужна Настройка сервер авторизации,чтобы клиент мог отправить запрос на сервер авторизации,и получить токен доступа. Ниже представлена конфигурация сервера авторизации:
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private TokenStore tokenStore;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client")
.secret("{noop}secret")
.authorizedGrantTypes("client_credentials")
.scopes("read", "write")
.accessTokenValiditySeconds(3600);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager)
.tokenStore(tokenStore);
}
@Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
}
В приведенном выше коде мы настраиваем клиента, идентификатор которого — «клиент», Secret — «секретный», режим авторизации — режим клиента, а область авторизации — «чтение» и «запись». Мы также настроили период действия токена на 3600 секунд и указали метод хранения токена InMemoryTokenStore.
Нам нужна настройка ресурсов сервера, чтобы клиент мог использовать токен доступа для доступа к защищенному ресурсу. Ниже приведена конфигурация сервера ресурсов:
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/api/**").authenticated()
.anyRequest().permitAll();
}
}
В приведенном выше коде мы настраиваем, что только запросы с токеном доступа могут получать доступ к ресурсам в разделе «/api».
Нам нужна Настройка клиент,чтобы сервер авторизации мог аутентифицировать клиента,и выдайте токен доступа. В этом примере,Мы используем память для хранения информации о клиенте.
@Configuration
public class ClientConfig {
@Bean
public ClientDetailsService clientDetailsService() {
InMemoryClientDetailsServiceBuilder builder = new InMemoryClientDetailsServiceBuilder();
builder.withClient("client")
.secret("{noop}secret")
.authorizedGrantTypes("client_credentials")
.scopes("read", "write")
.accessTokenValiditySeconds(3600);
return builder.build();
}
@Bean
public ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter() {
ClientCredentialsTokenEndpointFilter filter = new ClientCredentialsTokenEndpointFilter("/oauth/token");
filter.setAuthenticationManager(new AuthenticationManager() {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String clientId = (String) authentication.getPrincipal();
String clientSecret = (String) authentication.getCredentials();
ClientDetails clientDetails = clientDetailsService().loadClientByClientId(clientId);
if (clientDetails == null) {
throw new ClientRegistrationException("Unknown client " + clientId);
}
if (!clientDetails.getClientSecret().equals(clientSecret)) {
throw new BadCredentialsException("Bad credentials for client " + clientId);
}
return new UsernamePasswordAuthenticationToken(clientId, clientSecret, clientDetails.getAuthorities());
}
});
return filter;
}
}
В приведенном выше коде мы определяем клиента хранилища памяти, идентификатор которого — «клиент», а секрет — «секретный». Клиенты могут проходить аутентификацию с использованием режима авторизации «client_credentials» и получать разрешения «чтение» и «запись». Мы также определяем фильтр конечной точки токена учетных данных клиента, который аутентифицирует клиента с использованием учетных данных клиента и отправляет токен клиенту.
Клиент может получить токен доступа, используя к Защищенные ресурсы предоставляются ресурсными серверами. В этом примере мы предоставляем простой REST API, для доступа к которому требуется аутентификация. Мы можем использовать Spring MVC пишет контроллер REST для реализации этого API.
@RestController
@RequestMapping("/api")
public class ApiController {
@GetMapping("/hello")
public String hello() {
return "Hello World!";
}
}
В этом примере мы определяем конечную точку REST под названием «hello», которая возвращает «Hello World!» Для доступа к этой конечной точке требуется аутентификация.
Чтобы протестировать нашего клиента, мы можем использовать Postman для отправки HTTP-запроса. ПОЛУЧИТЬ запрос,проситьизURLдля"http://localhost:8080/api/hello",И нам нужно добавить поле Авторизация в заголовок запроса,Значение «Носитель {access_token}", где access_token — токен доступа, который мы получили от сервера авторизации. Если все в порядке, мы увидим «Hello» в Postman Мир!» Ответ.