OAuth2.0 и динамична регистрация на клиенти (с помощта на наследствения стек Spring OAuth)

1. Въведение

В този урок ще подготвим динамична регистрация на клиента с OAuth2.0. OAuth2.0 е рамка за оторизация, която позволява получаване на ограничен достъп до потребителски акаунти в HTTP услуга. Клиентът OAuth2.0 е приложението, което иска достъп до акаунта на потребителя. Този клиент може да бъде външно уеб приложение, потребителски агент или просто роден клиент.

За да постигнем динамична клиентска регистрация, ще съхраним идентификационните данни в базата данни, вместо в твърдо кодирана конфигурация. Приложението, което ще разширим, първоначално беше описано в урока Spring REST API + OAuth2.

Забележка : тази статия използва наследения проект Spring OAuth.

2. Зависимости на Maven

Първо ще настроим следния набор от зависимости:

 org.springframework.boot spring-boot-starter-web   org.springframework spring-jdbc   org.springframework.security.oauth spring-security-oauth2 

Обърнете внимание, че използваме spring-jdbc, защото ще използваме DB за съхраняване на новорегистрираните потребители с пароли.

3. Конфигурация на сървъра OAuth2.0

Първо, трябва да конфигурираме нашия OAuth2.0 сървър за оторизация. Основната конфигурация е в следния клас:

@Configuration @PropertySource({ "classpath:persistence.properties" }) @EnableAuthorizationServer public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { // config }

Има няколко основни неща, които трябва да конфигурираме; нека започнем с ClientDetailsServiceConfigurer:

@Override public void configure(final ClientDetailsServiceConfigurer clients) throws Exception { clients.jdbc(dataSource()) // ... }

Това ще гарантира, че използваме постоянство, за да получаваме информация за клиента.

Нека, разбира се, да настроим този стандартен източник на данни:

@Bean public DataSource dataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName")); dataSource.setUrl(env.getProperty("jdbc.url")); dataSource.setUsername(env.getProperty("jdbc.user")); dataSource.setPassword(env.getProperty("jdbc.pass")); return dataSource; }

И така, сега нашето приложение ще използва базата данни като източник на регистрирани клиенти, вместо типичните твърдо кодирани в паметта клиенти.

4. Схемата на DB

Нека сега дефинираме SQL структурата за съхранение на нашите OAuth клиенти:

create table oauth_client_details ( client_id VARCHAR(256) PRIMARY KEY, resource_ids VARCHAR(256), client_secret VARCHAR(256), scope VARCHAR(256), authorized_grant_types VARCHAR(256), web_server_redirect_uri VARCHAR(256), authorities VARCHAR(256), access_token_validity INTEGER, refresh_token_validity INTEGER, additional_information VARCHAR(4096), autoapprove VARCHAR(256) );

Най-важните полета от oauth_client_details, върху които трябва да се съсредоточим, са:

  • client_id - за съхраняване на идентификатора на новорегистрирани клиенти
  • client_secret - за съхраняване на паролата на клиентите
  • access_token_validity - което показва дали клиентът все още е валиден
  • органи - да посочат какви роли са разрешени за конкретен клиент
  • обхват - разрешени действия, например писане на статуси във Facebook и т.н.
  • оторизиран_грант_типове , който предоставя информация как потребителите могат да влязат в конкретния клиент (в нашия пример това е формуляр за вход с парола)

Моля, обърнете внимание, че всеки клиент има връзка между потребители с едно към много, което естествено означава, че множество потребители могат да използват един клиент .

5. Нека упорстваме на някои клиенти

С SQL schema define можем най-накрая да създадем някои данни в системата - и основно да дефинираме клиент.

Ще използваме следния скрипт data.sql - който Spring Boot ще се стартира по подразбиране - за инициализиране на DB:

INSERT INTO oauth_client_details (client_id, client_secret, scope, authorized_grant_types, web_server_redirect_uri, authorities, access_token_validity, refresh_token_validity, additional_information, autoapprove) VALUES ("fooClientIdPassword", "secret", "foo,read,write, "password,authorization_code,refresh_token", null, null, 36000, 36000, null, true);

Описанието на най-важните полета в oauth_client_details е дадено в предишния раздел.

6. Тестване

За да тестваме динамичната регистрация на клиента, трябва да стартираме проекти spring-security-oauth-server и spring-security-oauth-resource съответно на портовете 8081 и 8082.

Сега най-накрая можем да напишем няколко теста на живо.

Да приемем, че сме регистрирали клиент с идентификатор на име fooClientIdPassword , който има достъп за четене на foos.

Първо, ще се опитаме да получим маркер за достъп от Auth Server, като използваме вече определен клиент:

@Test public void givenDBUser_whenRevokeToken_thenAuthorized() { String accessToken = obtainAccessToken("fooClientIdPassword", "john", "123"); assertNotNull(accessToken); }

И тук е логиката за получаване на маркер за достъп:

private String obtainAccessToken(String clientId, String username, String password) { Map params = new HashMap(); params.put("grant_type", "password"); params.put("client_id", clientId); params.put("username", username); params.put("password", password); Response response = RestAssured.given().auth().preemptive() .basic(clientId, "secret").and().with().params(params).when() .post("//localhost:8081/spring-security-oauth-server/oauth/token"); return response.jsonPath().getString("access_token"); }

7. Заключение

В този урок научихме как да регистрираме динамично неограничен брой клиенти с OAuth2.0 рамка.

Пълното изпълнение на този урок може да бъде намерено в GitHub - това е проект, базиран на Maven, така че трябва да е лесно да се импортира и да се изпълнява както е.

Моля, обърнете внимание, че за да тествате, ще трябва да добавите клиенти в DB и че конфигурацията .inMemory () вече няма да е валидна. Ако искате да използвате старата. inMemory () config, има втори файл, съдържащ конфигурация с твърдо кодирани клиенти.