Введение: эта статья является первой в серии «Проектирование и реализация аутентификации, аутентификации и контроля разрешений API в архитектуре микросервисов». Ожидается, что в этой серии будет четыре статьи, объясняющие реализацию аутентификации, аутентификации и контроля разрешений API в микросервисах.
1. Предпосылки
В последнее время я разрабатываю службы, связанные с разрешениями.После микросервисной системы исходное отдельное приложение представляет собой метод разрешений безопасности на основе сеанса, который не может соответствовать требованиям аутентификации и аутентификации существующей архитектуры микросервисов. В архитектуре микрослужб приложение разделено на несколько микроприложений, каждое микроприложение должно аутентифицировать доступ, и каждое микроприложение должно указать текущего пользователя доступа и его разрешения. Особенно, когда источником доступа является не только браузер, но и вызов других сервисов, метод аутентификации в монолитной архитектуре приложения не особо подходит. В архитектуре микросервисов следует учитывать различные сценарии аутентификации, такие как сценарии доступа к внешним приложениям, аутентификация пользователя-службы и аутентификация службы-службы.
Например, когда пользователь A получает доступ к User Service, если пользователь A не вошел в систему, ему сначала необходимо войти в систему и запросить токен авторизации. После получения токена A будет нести токен для запроса доступа к файлу, так что личность A необходимо проверить, и A сможет получить доступ к файлу.
Чтобы адаптироваться к изменениям в архитектуре и требованиям, модуль авторизации авторизации изолирован как базовая микросервисная система для предоставления сервисов для других бизнес-сервисов.
2. Изменения в архитектуре системы
Упрощенные изменения разрешений при переходе от архитектуры с одним приложением к распределенной архитектуре показаны на следующих двух рисунках.
(1) Схема архитектуры упрощенной версии одного приложения:
(2) Схема архитектуры упрощенной версии распределенного приложения:
Преимущество распределенной архитектуры, особенно микросервисной, в том, что бизнес-логика может быть четко разделена, так что каждый микросервис может взять на себя одну функцию, ведь чем проще, тем стабильнее.
Однако микросервисы также приносят немало проблем. Например, для выполнения бизнес-операции необходимо вызвать множество микросервисов, поэтому использование системы разрешений для управления вызовами пользователей к различным микросервисам представляет для нас проблему. Когда вызов бизнес-микросервисов связан с системой разрешений, их пропускная способность не может быть снижена, когда есть проблема с системой разрешений, их бизнес-вызовы не могут быть заблокированы, и, конечно, бизнес-логика не может быть изменена. Системой разрешений быстрого доступа для новых бизнес-микросервисов относительно легко управлять, поэтому как быстро получить доступ к существующим микросервисам компании, не меняя их архитектуру, также является для нас большой проблемой.
3. Технические решения
Это в основном включает в себя два требования: одно — аутентификация и аутентификация, авторизация запрошенного удостоверения пользователя и аутентификация законности; другое — управление полномочиями на уровне API, после первой точки, когда удостоверение пользователя аутентифицируется. После того, как это законно, проверьте, является ли конкретный запрос пользователя имеет разрешение на выполнение операции.
3.1 Аутентификация и аутентификация
Для первого требования автор исследовал некоторые решения реализации:
-
распределенный
Session
план
Принцип схемы распределенного сеанса в основном заключается в хранении информации об аутентификации пользователя в общем хранилище и обычно использовании сеанса пользователя в качестве ключа для реализации простой распределенной хэш-карты. Когда пользователи обращаются к микросервисам, пользовательские данные могут быть извлечены из общего хранилища. В некоторых случаях эта схема очень хороша, статус входа пользователя не прозрачен. Это также высокодоступное и масштабируемое решение. Недостатком этого решения является то, что для общего хранилища требуется определенный механизм защиты, поэтому доступ к нему должен осуществляться через защищенную ссылку, а реализация решения обычно довольно сложна. -
на основе
OAuth2 Token
план
С появлением Restful API и микросервисов, основанных наToken
Сертификация становится все более распространенной. Токен и идентификатор сеанса — это разные вещи, а не только ключ. Токен обычно содержит соответствующую информацию о пользователе, и проверка личности может быть завершена путем проверки токена. Пользователь вводит регистрационную информацию и отправляет ее службе проверки подлинности для проверки подлинности. AuthorizationServer проверяет правильность информации для входа и возвращает такую информацию, как основная информация о пользователе, объем полномочий и действительное время, а клиент сохраняет интерфейс. Пользователь помещает токен в заголовок HTTP-запроса и инициирует соответствующие вызовы API. Вызванный микросервис, проверяющийToken
. ResourceServer возвращает связанные ресурсы и данные.
Здесь выбирается второй вариант, исходя изOAuth2 Token
Преимущества сертификации заключаются в следующем:
- На стороне сервера без сохранения состояния: механизму токена не нужно хранить информацию о сеансе на стороне сервера, поскольку сам токен содержит всю информацию, относящуюся к пользователю.
- Производительность выше, поскольку больше нет необходимости обращаться к базе данных или удаленному сервису для проверки разрешений при проверке токена, что, естественно, может значительно повысить производительность.
- Многие приложения теперь ориентированы как на мобильные устройства, так и на Интернет.
OAuth2 Token
Механизм может поддерживать мобильные устройства. - Последний момент тоже очень важен, OAuth2 используется в связке со Spring Security, документация по Spring Security OAuth2 написана более подробно.
oauth2 разделен на 4 режима в соответствии с различными сценариями использования:
- Код авторизации
- Упрощенный режим (неявный)
- Режим пароля (учетные данные пароля владельца ресурса)
- Режим клиента (учетные данные клиента)
Для студентов, которые не знакомы с четырьмя вышеупомянутыми режимами oauth2, вы можете самостоятельно использовать Baidu oauth2.В статье Ruan Yifeng есть объяснение. Обычно используются режим пароля и режим клиента.
3.2 Контроль разрешений на операции
Что касается второго требования, автор в основном смотрел на Spring Security и Shiro.
-
Shiro
Shiro — это мощная и гибкая платформа безопасности с открытым исходным кодом, которая очень аккуратно обрабатывает аутентификацию, авторизацию, управление сеансами и шифрование паролей. Широ легко начать, и вы можете быстро или точно контролировать детализацию. Обладая высокой степенью свободы, Широ можно использовать вместе со Spring или отдельно. -
Spring Security
Экология весеннего сообщества очень сильна. Spring Security обладает всеми функциями Shiro, за исключением того, что его нельзя отделить от Spring. Более того, Spring Security также поддерживает Oauth и OpenID, а Shiro нужно реализовать это вручную. Разрешения Spring Security более детализированы. Но Spring Security слишком сложна.
Глядя на комментарии в Интернете, кажется, что это однобоко по отношению к Широ. предложено большинствомSpring Security
Проблема в том, что он более сложный и трудный для понимания, а документ слишком длинный. Автор всесторонне оценил сложность и требования к разрешению, которые должны быть реализованы, а также результаты предыдущего обзора требований и, наконец, выбралSpring Security
.
4. Архитектура системы
4.1 Компоненты
Компоненты конечного использования системы аутентификации следующие:
OAuth2.0 JWT Token
Spring Security
Spring boot
4.2 Шаги
Основные шаги:
- Настройка сервера ресурсов и сервера аутентификации
- Настроить весеннюю безопасность
Вышеуказанные шаги являются относительно общими.Требования, упомянутые в предыдущем разделе, относятся к основному содержанию системы аутентификации.Автор напишет другую статью, чтобы объяснить это позже.
4.3 endpoint
Предоставленная конечная точка:
/oauth/token?grant_type=password #请求授权token
/oauth/token?grant_type=refresh_token #刷新token
/oauth/check_token #校验token
/logout #注销token及权限相关信息
4.4 зависимости maven
Основной пакет jar, файл pom.xml, выглядит следующим образом:
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-security</artifactId>
<version>1.2.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
<version>1.2.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jersey</artifactId>
<version>1.5.3.RELEASE</version>
</dependency>
4.5 Конфигурационный файл AuthorizationServer
Конфигурация AuthorizationServer в основном переопределяет следующие три метода, предназначенные для конечных точек, клиентов и конфигураций безопасности.
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
//配置客户端认证
clients.withClientDetails(clientDetailsService(dataSource));
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
//配置token的数据源、自定义的tokenServices等信息
endpoints.authenticationManager(authenticationManager)
.tokenStore(tokenStore(dataSource))
.tokenServices(authorizationServerTokenServices())
.accessTokenConverter(accessTokenConverter())
.exceptionTranslator(webResponseExceptionTranslator);
}
4.6 Конфигурация ResourceServer
Конфигурация сервера ресурсов, которая переопределяет конфигурацию по умолчанию. Для поддержки выхода из системы, вот пользовательскийCustomLogoutHandler
и воляlogoutSuccessHandler
указан для возврата статуса httpHttpStatusReturningLogoutSuccessHandler
.
@Override
public void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.requestMatchers().antMatchers("/**")
.and().authorizeRequests()
.antMatchers("/**").permitAll()
.anyRequest().authenticated()
.and().logout()
.logoutUrl("/logout")
.clearAuthentication(true)
.logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler())
.addLogoutHandler(customLogoutHandler());
4.7 Выполнение конечной точки
- Сначала выполните конечную точку для получения авторизации.
method: post
url: http://localhost:12000/oauth/token?grant_type=password
header:
{
Authorization: Basic ZnJvbnRlbmQ6ZnJvbnRlbmQ=,
Content-Type: application/x-www-form-urlencoded
}
body:
{
username: keets,
password: ***
}
Вышеупомянутое создает почтовый запрос, и конкретный запрос написан очень подробно. Имя пользователя и пароль — это информация, предоставляемая клиентом серверу для проверки личности пользователя. Авторизация в заголовке — это закодированная строка сохраненного clientId и clientSecret.
Возвращаемые результаты следующие:
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJYLUtFRVRTLVVzZXJJZCI6ImQ2NDQ4YzI0LTNjNGMtNGI4MC04MzcyLWMyZDYxODY4ZjhjNiIsImV4cCI6MTUwODQ0Nzc1NiwidXNlcl9uYW1lIjoia2VldHMiLCJqdGkiOiJiYWQ3MmIxOS1kOWYzLTQ5MDItYWZmYS0wNDMwZTdkYjc5ZWQiLCJjbGllbnRfaWQiOiJmcm9udGVuZCIsInNjb3BlIjpbImFsbCJdfQ.5ZNVN8TLavgpWy8KZQKArcbj7ItJLLaY1zBRaAgMjdo",
"token_type": "bearer",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJYLUtFRVRTLVVzZXJJZCI6ImQ2NDQ4YzI0LTNjNGMtNGI4MC04MzcyLWMyZDYxODY4ZjhjNiIsInVzZXJfbmFtZSI6ImtlZXRzIiwic2NvcGUiOlsiYWxsIl0sImF0aSI6ImJhZDcyYjE5LWQ5ZjMtNDkwMi1hZmZhLTA0MzBlN2RiNzllZCIsImV4cCI6MTUxMDk5NjU1NiwianRpIjoiYWE0MWY1MjctODE3YS00N2UyLWFhOTgtZjNlMDZmNmY0NTZlIiwiY2xpZW50X2lkIjoiZnJvbnRlbmQifQ.mICT1-lxOAqOU9M-Ud7wZBb4tTux6OQWouQJ2nn1DeE",
"expires_in": 43195,
"scope": "all",
"X-KEETS-UserId": "d6448c24-3c4c-4b80-8372-c2d61868f8c6",
"jti": "bad72b19-d9f3-4902-affa-0430e7db79ed",
"X-KEETS-ClientId": "frontend"
}
Видно, что после проверки логина и пароля клиент получает ответ от сервера авторизации, в основном включая доступжетон, обновитьтокен. И это указывает на то, что тип токена является предъявителем, а время истечения срока действия expires_in. Автор добавил пользовательскую информацию в токен jwt как UserId и ClientId.
2. Конечная точка аутентификации
method: post
url: http://localhost:12000/oauth/check_token
header:
{
Authorization: Basic ZnJvbnRlbmQ6ZnJvbnRlbmQ=,
Content-Type: application/x-www-form-urlencoded
}
body:
{
token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJYLUtFRVRTLVVzZXJJZCI6ImQ2NDQ4YzI0LTNjNGMtNGI4MC04MzcyLWMyZDYxODY4ZjhjNiIsImV4cCI6MTUwODQ0Nzc1NiwidXNlcl9uYW1lIjoia2VldHMiLCJqdGkiOiJiYWQ3MmIxOS1kOWYzLTQ5MDItYWZmYS0wNDMwZTdkYjc5ZWQiLCJjbGllbnRfaWQiOiJmcm9udGVuZCIsInNjb3BlIjpbImFsbCJdfQ.5ZNVN8TLavgpWy8KZQKArcbj7ItJLLaY1zBRaAgMjdo
}
Выше приведена подробная информация о запросе check_token. Следует отметить, что автор поместил в тело только что авторизованный токен, здесь может быть несколько методов, которые не будут здесь распространяться.
{
"X-KEETS-UserId": "d6448c24-3c4c-4b80-8372-c2d61868f8c6",
"user_name": "keets",
"scope": [
"all"
],
"active": true,
"exp": 1508447756,
"X-KEETS-ClientId": "frontend",
"jti": "bad72b19-d9f3-4902-affa-0430e7db79ed",
"client_id": "frontend"
}
После проверки правильности маркера возвращается ответ, как показано выше. Основная информация в соответствующем токене также отображается в ответе.
3. Обновить токен
Поскольку старение токена, как правило, не очень продолжительное, а обновлениеЦикл токена, как правило, будет очень долгим. Чтобы не влиять на работу пользователя, вы можете использовать обновлениеtoken для динамического обновления токена.
method: post
url: http://localhost:12000/oauth/token?grant_type=refresh_token&refresh_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJYLUtFRVRTLVVzZXJJZCI6ImQ2NDQ4YzI0LTNjNGMtNGI4MC04MzcyLWMyZDYxODY4ZjhjNiIsInVzZXJfbmFtZSI6ImtlZXRzIiwic2NvcGUiOlsiYWxsIl0sImF0aSI6ImJhZDcyYjE5LWQ5ZjMtNDkwMi1hZmZhLTA0MzBlN2RiNzllZCIsImV4cCI6MTUxMDk5NjU1NiwianRpIjoiYWE0MWY1MjctODE3YS00N2UyLWFhOTgtZjNlMDZmNmY0NTZlIiwiY2xpZW50X2lkIjoiZnJvbnRlbmQifQ.mICT1-lxOAqOU9M-Ud7wZBb4tTux6OQWouQJ2nn1DeE
header:
{
Authorization: Basic ZnJvbnRlbmQ6ZnJvbnRlbmQ=
}
Его ответ и /oauth/token аналогичны обычному ответу и не будут здесь перечислены.
4. Отменить токен
method: get
url: http://localhost:9000/logout
header:
{
Authorization: Basic ZnJvbnRlbmQ6ZnJvbnRlbmQ=
}
Если выход выполнен успешно, будет возвращено значение 200. Конечная точка выхода в основном предназначена для очистки маркера и SecurityContextHolder.
5. Резюме
Эта статья представляет собой обзор серии статей «Проектирование и реализация аутентификации, аутентификации и управления разрешениями API в микросервисной архитектуре», начиная с возникших проблем и представляя предысторию проекта. Выбор технологии определяется путем изучения существующей технологии и ее сочетания с фактической ситуацией текущего проекта. Наконец, показана окончательная реализация системы. Реализация этой системы будет объяснена позже из деталей реализации. Следите за дальнейшими статьями.