предисловие
Недавно был проведен рефакторинг проекта, содержащегомного клиентов, такие как браузеры, мобильные приложения, мобильные общедоступные учетные записи WeChat и т. д., по замыслу босса, ониУ каждого своя фоновая служба, но некоторые общественные услуги извлекаются, чтобы сделатьосновные услугиОн совместно используется фоновыми службами каждого клиента, а также используетсяspring cloud + consul + feign
реализоватьОбнаружение регистрации службы и вызовы между службами.
Босс решил напрямую изменить предыдущее управление безопасностью и полномочиями и решил использовать метод oauth2 для управления контролем полномочий между службами, что, вероятно, означает, что каждая клиентская служба переходит кВернуть access_token после запроса базовой службы на успешную аутентификацию., и приносить этот access_token каждый раз при вызове интерфейса службы в будущем, а базовая служба получает информацию аутентификации в соответствии с access_token.
В этой статье будет представлена реализация сервера авторизации oauth2 с использованиемspring-security-oauth2
Реализовать сервер авторизации oauth2, который будет отвечать заПолучить информацию об аутентификации клиента,Выполнить аутентификациюпроцесс, авторизация после успехаВыпустить access_token. Что касается того, как клиент вызывает и получает access_token, это не входит в задачу данной статьи, я напишу об этом в следующей статье~
Введение в oauth2
По поводу авторизации и аутентификации oauth2 в интернете есть много блогов и материалов, которые кратко упоминаются здесь.
Во-первых, полный процесс oauth2 должен включать следующие части:
- Сервер ресурсов, сервер ресурсов, третья сторона, например информация пользователя WeChat, защищенная WeChat.
- Владелец ресурса, владелец ресурса, например, пользователи WeChat
- Сервер авторизации, сервер авторизации, третья сторона, такая как WeChat, после согласия пользователя авторизовать нас, открытая платформа, предоставляющая нам доступ к серверам ресурсов
- Клиент, клиент, такой как разработчики WeChat, пользователи WeChat, после входа в WeChat, разработчики WeChat «побуждают» щелкнуть сервер авторизации запроса, чтобы авторизовать наших разработчиков, а разработчики WeChat могут перейти на сервер ресурсов для получения некоторой информации. о пользователях.
oauth2 определяет четыре метода авторизации:
- Обычно используется режим кода авторизации (код авторизации). Например, пользователи WeChat сначала входят в WeChat, запрашивают страницу авторизации, а после согласия на авторизацию дают код разработчику WeChat. С помощью этого кода разработчик может затем получите access_token, а затем запросите сервер ресурсов для получения информации о пользователе.
- Упрощенный режим (неявный)
- Режим пароля (учетные данные владельца ресурса) обычно не используется в сторонней аутентификации. Например, пользователи WeChat напрямую вводят имя пользователя и пароль WeChat разработчику, а затем разработчик передает имя пользователя и пароль WeChat для получения разрешения. WeChat конечно нельзя, это делается, но так как мы звоним между сервисами в одной компании, то можно использовать этот паттерн.
- Учетные данные клиента (учетные данные клиента) используются для некоторых служб проверки подлинности, не связанных с пользователями.
Более подробные сведения о процессах oauth2 выходят за рамки этой статьи.Вы можете обратиться к процессу аутентификации oauth2 в справочнике в конце этой статьи.
В заключении, здесь мы не используем стандартную практику oauth2, потому что обычно требуется сторонняя аутентификация и авторизация. Но здесь босс хочет поставитьОсновная служба действует как сторонний сервер ресурсов., чтобы упростить передачу информации об аутентификации пользователя в процессе вызова авторизации между каждой клиентской фоновой службой и основной службой.
После введения предыстории и теории давайте начнем использовать поддержку oauth2, предоставляемую Spring, для достижения следующего:
Устарело на spring-security-oauth2
Как упоминалось выше, эта статья в основном посвящена части oauth2, то есть процессу реализации сервера авторизации Authorization Server. Сначала я отправился в знаменитыйspring security
чтобы увидеть, как он реализует сервер авторизации для oauth2, и получил безжалостный результат, последнийspring security
модуль ужеНе предоставляет реализацию сервера авторизации.
фактическиspring security oauth2
Модуль реализует сервер авторизации oauth2, но официальный сказалspring security oauth2
Все модули устарели, мигрируйте наspring security
Модуль предоставляется, и руководство по миграции также предоставляется «интимно»
нажмите
Этот документ содержит руководство по переносу клиентов и серверов ресурсов OAuth 2.0 с Spring Security OAuth 2.x на Spring Security 5.2.x. Поскольку Spring Security не обеспечивает поддержку сервера авторизации, перенос сервера авторизации Spring Security OAuth выходит за рамки этого документ.
Общая идея заключается в том, что мы сделали spring-security-oauth2 устаревшим, который обеспечивает реализацию сервера авторизации oauth2, но мы не предоставляем сервер авторизации oauth2 в новом решении.
Да, вотПодавать жалобыSpring, конечно, потому что многие жалуются, Spring также официально строит новый модуль реализации сервера авторизации oauth2, и можно ожидать будущего.
Вы можете посмотреть историю сервера авторизации spring oauth2
stackoverflow.com/questions/5…
В заключении, нам нужно реализовать сервер авторизации oauth2, и временно нужно использовать устаревший модуль без других новых технологийspring-security-oauth
, соответствующий код также будет иметьзачеркнутый
Конфигурация информации о клиенте
Клиент здесь — это концепция в oauth2, похожая на информацию об appid и appsecret в разработке WeChat.В наших потребностях это относится к фоновым службам, соответствующим различным пользовательским клиентам, таким как сеть, мобильное приложение и мобильная учетная запись WeChat. После настройки их информации соответствующая им фоновая служба может разрешить серверу запрашивать информацию авторизации, такую как access_token, с их информацией.
spring-security-oauth
Модули обеспечивают удобную аннотацию@EnableAuthorizationServer
и адаптерAuthorizationServerConfigurerAdapter
Давайте настроим Сервер авторизации с помощью следующего кода:
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
// 配置web客户端
.withClient("web")
.secret(passwordEncoder.encode("**"))
// web端通过password形式认证
.authorizedGrantTypes("password")
.and()
// 配置微信公众号客户端
.withClient("wx_subscription")
.secret(passwordEncoder.encode("**"))
// 微信公众号客户端需要通过微信提供的code进行认证,所有自定义了认证方式,需要后面的支持
.authorizedGrantTypes("wx_subscription")
}
}
Поскольку нет необходимости в динамической модификации, она настраивается непосредственно в памяти.
Через приведенную выше конфигурацию пружина предоставила нам следующие вещи:
- Конечная точка авторизации аутентификации oauth2
- Генерация, выпуск и хранение токенов после аутентификации
Но как весна основана наpassword
,wx_subscription
Код для аутентификации необходимо настроить в следующем диспетчере аутентификации.
Конфигурация диспетчера аутентификации
закончить первымpassword
Форма аутентификации, все еще в классе адаптера выше, настраиваетAuthorizationServerEndpointsConfigurer
Конечная точка диспетчера аутентификации для этого диспетчера аутентификацииauthenticationManager
с нашим обычнымspring security
Диспетчер аутентификации, настроенный в это время, может быть одним и тем же.
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
// 设置这个开启password授权方式,通过spring security暴露
endpoints.authenticationManager(authenticationManager);
}
}
о вspring securtiy
выставляется в конфигеAuthenticationManager
:
@Configuration
@EnableWebSecurity
class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
//.. 省略用户名密码等认证配置
/**
* 暴露认证管理器给授权服务器使用
* @return
* @throws Exception
*/
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
контрольная работа
После приведенной выше конфигурации, если нет проблем с конфигурацией аутентификации, такой как ваше имя пользователя и пароль, вы можете запустить проект для тестирования следующего oauth2.password
Является ли метод аутентификации простым в использовании?
@Test
void testWebClient() {
ResourceOwnerPasswordResourceDetails resource = new ResourceOwnerPasswordResourceDetails();
resource.setClientId("web");
resource.setClientSecret("**");
resource.setAccessTokenUri("http://**/oauth/token");// Oauth2.0 服务端链接
resource.setScope(Arrays.asList(""));// 读写权限
resource.setUsername("**");
resource.setPassword("**");
resource.setGrantType("password");// Oauth2.0 使用的模式 为密码模式
AccessTokenRequest atr = new DefaultAccessTokenRequest();
OAuth2RestTemplate template = new OAuth2RestTemplate(resource, new DefaultOAuth2ClientContext(atr));
ResourceOwnerPasswordAccessTokenProvider provider = new ResourceOwnerPasswordAccessTokenProvider();
template.setAccessTokenProvider(provider);
System.out.println(template.getAccessToken());
}
Настройка пользовательских методов аутентификации, таких как официальная учетная запись WeChat.
Приведенная выше конфигурация завершает метод получения авторизации напрямую через имя пользователя и пароль, определенные в стандарте oauth2.
Но мы иногда аутентифицируемся не только по имени пользователя и паролю, но и по номеру мобильного телефона + проверочный код; официальный код аккаунта WeChat для аутентификации. Здесь мы настраиваем конфигурацию процесса аутентификации кода через общедоступную учетную запись WeChat.
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
// 设置这个开启password授权方式
endpoints.authenticationManager(authenticationManager);
// 增加自定义授权方式,这里可以增加新的认证方式,只要自定义TokenGranter即可
endpoints.tokenGranter(
new CompositeTokenGranter(
Arrays.asList(endpoints.getTokenGranter(), customTokenGranter(endpoints))
)
);
}
}
О настройкеTokenGranter
конфигурация, здесь, потому чтоAuthorizationServerEndpointsConfigurer
Некоторые внутренние методы , используют отражение для вызова необходимых методов и используютПрокси для ленивой загрузки, иначе будут какие-товопросы жизненного цикла
private TokenGranter customTokenGranter(AuthorizationServerEndpointsConfigurer endpoints) {
// 代理延迟加载
return new TokenGranter() {
private TokenGranter delegate;
// 第一次使用时才创建
@Override
public OAuth2AccessToken grant(String grantType, TokenRequest tokenRequest) {
if (delegate == null) {
try {
// private方法,需要使用getDeclaredMethod
Method tokenServicesMethod = endpoints.getClass().getDeclaredMethod("tokenServices"),
requestFactoryMethod = endpoints.getClass().getDeclaredMethod("requestFactory");
tokenServicesMethod.setAccessible(true);
requestFactoryMethod.setAccessible(true);
AuthorizationServerTokenServices tokenServices = (AuthorizationServerTokenServices) tokenServicesMethod.invoke(endpoints);
OAuth2RequestFactory requestFactory = (OAuth2RequestFactory) requestFactoryMethod.invoke(endpoints);
// 这里也加入了我们的认证管理器authenticationManager,所有后续通过code进行微信认证的过程也在spring security的AuthenticationManager中完成
delegate = new WxSubscriptionCodeTokenGranter(authenticationManager, tokenServices, clientDetailsService, requestFactory);
}catch (Exception e){
logger.error("创建自定义授权方式失败", e);
return null;
}
}
return delegate.grant(grantType, tokenRequest);
}
};
}
оWxSubscriptionCodeTokenGranter
Реализация базовой эталонной пружины обеспечиваетResourceOwnerPasswordTokenGranter
Класс можно реализовать, а метод аутентификации поменять на нашwx_subscription
Вот и все, я не буду вдаваться в подробности о коде вставки здесь.
На данный момент настройка сервера авторизации пользовательского метода аутентификации oauth2 завершена.
Суммировать
- Метод аутентификации oauth2 используется между распределенными сервисами, чтобы избежать передачи информации об аутентификации пользователя.Этот метод не кажется слишком много сейчас.Преимущества и недостатки можно обдумать и обсудить.
- Создание ленивой загрузки может быть выполнено через прокси, избегая некоторых сложных вызовов зависимостей метода жизненного цикла.
В этой статье лишь кратко рассказывается, как сервер авторизации использует Spring Security oauth2 в стандарте oauth2, и в будущем может быть написано о реализации сервера ресурсов и клиента.
Приглашаем всех критиковать и обсуждать~
Ссылаться на
О процессе аутентификации oauth2Блог Woo Woo.cn на.com/Invincible Code Farmer/…
Устаревание spring-security-oauth2stackoverflow.com/questions/5…
Документация для spring-security-oauth2проекты.spring.IO/spring-brush-ECU…