Однонаправленный вход (англ. Single sign-on, сокр. SSO), также известный как единственный вход, представляет собой свойство, которое обеспечивает контроль доступа к множеству взаимосвязанных, но независимых друг от друга программным системам. При наличии этого свойства пользователь получает доступ ко всем системам при одном входе, без необходимости входить в каждую систему отдельно. Эта функция обычно реализуется с помощью протокола легковесного каталога (LDAP), при этом информация о пользователе хранится в базе данных LDAP на сервере. Аналогично, единственный выход (single sign-off) означает, что одинаковый выходной запрос позволяет завершить доступ к нескольким системам.
1. Доступ к
client1
2. client1
направляет запрос на sso-server
3. Подтверждение разрешения
4. Возврат кода авторизации code
обратно на client1
5. client1
использует код авторизации для запроса токена
6. Возврат токена JWT
7. client1
анализирует токен и осуществляет вход
8. client1
обращается к client2
9. client2
направляет запрос на sso-server
10. Подтверждение разрешения
11. Возврат кода авторизации code
обратно на client2
12. client2
использует код авторизации для запроса токена
13. Возврат токена JWT
14. client2
анализирует токен и осуществляет входСостояние входа пользователя сохраняется в центре аутентификации sso-server
, а также входные формы и проверка учетных данных выполняются центром аутентификации sso-server
(токены, возвращаемые client1
и client2
, различны, но пользовательская информация, извлеченная из них, принадлежит одному и тому же пользователю).
### sso-server
@Configuration
@EnableAuthorizationServer
public class SsoAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
/**
* Настройки клиента
* @param clients
* @throws Exception
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("merryyou1")
.secret("merryyousecrect1")
.authorizedGrantTypes("authorization_code", "refresh_token")
.scopes("all")
.and()
.withClient("merryyou2")
.secret("merryyousecrect2")
.authorizedGrantTypes("authorization_code", "refresh_token")
.scopes("all");
}
/**
* Настройка jwtTokenStore
* @param endpoints
* @throws Exception
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(jwtTokenStore()).accessTokenConverter(jwtAccessTokenConverter());
}
``` /**
* Разрешения springSecurity, для доступа к merryyou tokenkey требуется аутентификация
* @param security
* @throws Exception
*/
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.tokenKeyAccess("isAuthenticated()");
}```java
/**
* JWTtokenStore
* @return
*/
@Bean
public TokenStore jwtTokenStore() {
return new JwtTokenStore(jwtAccessTokenConverter());
}
/**
* Создание JWT токена
* @return
*/
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter(){
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("merryyou");
return converter;
}
}
@Configuration
public class SsoSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin().loginPage("/authentication/require")
.loginProcessingUrl("/authentication/form")
.and().authorizeRequests()
.antMatchers("/authentication/require",
"/authentication/form",
"/**/*.js",
"/**/*.css",
"/**/*.jpg",
"/**/*.png",
"/**/*.woff2")
.permitAll()
.anyRequest().authenticated()
.and()
.csrf().disable();
// http.formLogin().and().authorizeRequests().anyRequest().authenticated();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
}
@Component
public class SsoUserDetailsService implements UserDetailsService {
@Autowired
private PasswordEncoder passwordEncoder;
``` @Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return new User(username, passwordEncoder.encode("123456"), AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER"));
}
}
server:
port: 8082
context-path: /uaa
spring:
freemarker:
allow-request-override: false
allow-session-override: false
cache: true
charset: UTF-8
check-template-location: true
content-type: text/html
enabled: true
expose-request-attributes: false
expose-session-attributes: false
expose-spring-macro-helpers: true
prefer-file-system-access: true
suffix: .ftl
template-loader-path: classpath:/templates/
@SpringBootApplication
@RestController
@EnableOAuth2Sso
public class SsoClient1Application {
``` @GetMapping("/user")
public Authentication user(Authentication user) {
return user;
}
public static void main(String[] args) {
SpringApplication.run(SsoClient1Application.class, args);
}
}
auth-server: http://localhost:8082/uaa # адрес сервера sso
server:
context-path: /client1
port: 8083
security:
oauth2:
client:
client-id: merryyou1
client-secret: merryyousecrect1
user-authorization-uri: ${auth-server}/oauth/authorize # адрес для запроса авторизации
access-token-uri: ${auth-server}/oauth/token # адрес для запроса токена
resource:
jwt:
key-uri: ${auth-server}/oauth/token_key # адрес для получения ключа для декодирования jwt токена
Результат:
Добавлен sso-resource (поддерживает ресурсный сервер sso-client1)
Добавлено автоматическое разрешение SsoAuthorizationServerConfig
(autoApprove(true)) предоставлено laungcisin
Добавлен способ запуска с помощью docker-compose
, необходимо добавить 127.0.0.1 sso-login sso-taobao sso-tmall sso-resource
в локальный файл hosts. Адрес для доступа: http://sso-taobao:8083/client1## Настройка окружения
Создайте Dockerfile и загрузите свой собственный образ в Docker Hub
https://www.jianshu.com/p/48349dafe8be
http://www.merryyou.cn/
http://www.merryyou.cn/2018/04/22/springbootdockergitjenkins_реализация_быстрой_компоновки_и_установки_сервисов/
https://gitee.com/merryyou/sso-merryyou
Spring Security и OAuth2 (ресурсный сервер) https://www.jianshu.com/p/6dd03375224d
Настройка передачи токена с помощью Zuul Обсуждение того, как использовать Spring Cloud Security OAuth2 и Zuul для настройки безопасного аутентифицирующего сервиса и ресурсного сервиса, а также передачи OAuth2 токена между сервисами с помощью Oauth2RestTemplate и встроенных Zuul-прокси Spring Cloud безопасность: интеграция OAuth2 для реализации аутентификации и единого входа https://www.jianshu.com/p/24577532555d?utm_source=oschina-app
http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html
OAuth между "клиентом" и "поставщиком услуг" устанавливает авторизационный слой (authorization layer). "Клиент" не может напрямую войти в "поставщик услуг", он может войти только в авторизационный слой, тем самым отделяя пользователя от клиента. "Клиент" использует токен для входа в авторизационный слой, который отличается от пароля пользователя. Пользователь может указать разрешения и срок действия токена при входе. После входа "клиента" в авторизационный слой, "поставщик услуг" открывает данные пользователя на основе разрешений и срока действия токена.## OAuth 2.0 определяет четыре способа авторизации. Режим авторизационного кода (authorization code) Режим упрощенного доступа (implicit) Режим пароля пользователя (resource owner password credentials) Режим клиента (client credentials)
Авторизационный код (Authorization Code) — это наиболее полный и строго регламентированный метод аутентификации. Его особенностью является взаимодействие клиентского сервера с сервером аутентификации поставщика услуг. Этапы этого процесса следующие:
(A) Пользователь заходит на клиентский сайт, который направляет его на сервер аутентификации.
(B) Пользователь выбирает, разрешить ли доступ клиенту.
(C) Если пользователь разрешает доступ, сервер аутентификации перенаправляет пользователя на предварительно определенный URI перенаправления (Redirection URI) клиента и прикрепляет к нему код авторизации.
(D) Клиент получает код авторизации и использует предварительно определенный URI перенаправления для запроса токена у сервера аутентификации. Этот шаг выполняется на сервере клиента и недоступен для пользователя.
(E) Сервер аутентификации проверяет код авторизации и URI перенаправления, подтверждает их корректность и отправляет клиенту токен доступа (Access Token) и токен обновления (Refresh Token).В шаге (A) URI запроса аутентификации клиента включает следующие параметры: response_type: тип запроса аутентификации, обязательный параметр, значение которого всегда "code" client_id: идентификатор клиента, обязательный параметр redirect_uri: URI перенаправления, необязательный параметр scope: область разрешений, необязательный параметр state: состояние клиента, может быть любым значением, которое будет возвращено сервером аутентификации без изменений.Упрощенный метод Упрощенный метод (Implicit Grant Type) не требует участия сервера клиента и позволяет пользователю напрямую запросить токен у сервера аутентификации, пропуская шаг с кодом авторизации. Поэтому он получил такое название. Все шаги выполняются в браузере, и токен доступен пользователю, а также не требуется аутентификация клиента.
Этапы этого процесса следующие:
(A) Клиент направляет пользователя на сервер аутентификации.
(B) Пользователь решает, разрешить ли доступ клиенту.
(C) Если пользователь разрешает доступ, сервер аутентификации перенаправляет пользователя на предварительно определенный URI перенаправления клиента и включает в него токен доступа в части URI-хэша.
(D) Браузер направляет запрос на сервер ресурсов, не включая хэш URI из предыдущего шага.
(E) Сервер ресурсов возвращает страницу, содержащую код для извлечения токена из URI-хэша.
(F) Браузер выполняет код из предыдущего шага и извлекает токен.(G) Браузер передает токен клиенту. Парольный режим Парольный режим (Resource Owner Password Credentials Grant) предполагает, что пользователь предоставляет клиенту свои имя пользователя и пароль. Клиент использует эти данные для запроса доступа у "поставщика услуг". В этом режиме пользователь должен передать свой пароль клиенту, но клиент не должен хранить этот пароль. Этот режим обычно используется в ситуациях, когда пользователь полностью доверяет клиенту, например, когда клиент является частью операционной системы или выпущен известной компанией. Аутентификационный сервер следует использовать этот режим только в случае, если другие режимы аутентификации недоступны. Клиентский режим Клиентский режим (Client Credentials Grant) означает, что клиент аутентифицируется по своему собственному имени, а не имени пользователя, у "поставщика услуг". Точнее говоря, клиентский режим не относится к проблемам, которые OAuth-фреймворк решает. В этом режиме пользователи регистрируются напрямую у клиента, а клиент аутентифицируется у "поставщика услуг" по своему собственному имени, чтобы получить доступ к услугам. В этом случае вопрос авторизации отсутствует.Обновление токена Если при доступе пользователя "токен доступа" клиента истек, то необходимо использовать "токен обновления" для получения нового токена доступа.
Клиент отправляет HTTP-запрос для обновления токена, содержащий следующие параметры:
grant_type: указывает используемый метод аутентификации, значение должно быть "refresh_token", обязательный параметр. refresh_token: представляет собой ранее полученный токен обновления, обязательный параметр. scope: указывает область доступа, которую клиент пытается получить, не может превышать предыдущую область доступа. Если параметр не указан, то предполагается, что область доступа остается прежней.
Детальное описание конфигурационного файла Docker Compose https://www.jianshu.com/p/2217cfed29d7
vim /etc/sysconfig/iptables *filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT -A INPUT -p icmp -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 21 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 8081 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 8082 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 8083 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 8084 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 8085 -j ACCEPT -A INPUT -p tcp -m state --state NEW -m tcp --dport 3306 -j ACCEPT -A INPUT -j REJECT --reject-with icmp-host-prohibited -A FORWARD -j REJECT --reject-with icmp-host-prohibited COMMITОтключение брандмауэра
service iptables stop
service iptables save
systemctl restart iptables.service
depends_on при запуске сервиса не будет ждать завершения запуска зависимых сервисов. То есть, основная функция depends_on — это автоматическое включение зависимости SERVICE, а запуск сервисов в соответствии с их зависимостями практически не имеет смысла в реальной жизни, так как многие зависимые сервисы часто запускаются медленно. После запуска можно заметить, что сначала запускается SSO, а затем Client1. Однако службы в SSO завершают запуск примерно через cq секунд, что приводит к неудачному запуску Client1.
В производственной среде часто возникает необходимость строго контролировать последовательность запуска служб. Однако Docker Compose сам по себе не обладает этой функцией. Для реализации контроля последовательности запуска Docker Compose рекомендует использовать: wait-for-it dockerize wait-for
https://blog.csdn.net/aaronsimon/article/details/82711610
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Комментарии ( 0 )