предисловие
Недавно был проведен рефакторинг проекта, содержащегомного клиентов, такие как браузеры, мобильные приложения, мобильные общедоступные учетные записи 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…