Простий єдиний вхід із Spring Security OAuth2 (застарілий стек)

1. Огляд

У цьому підручнику ми обговоримо, як реалізувати єдиний вхід - єдиний вхід - за допомогою Spring Security OAuth та Spring Boot.

Ми будемо використовувати три окремі програми:

  • Сервер авторизації - який є центральним механізмом автентифікації
  • Дві клієнтські програми: програми, що використовують єдиний ввід

Простіше кажучи, коли користувач намагається отримати доступ до захищеної сторінки в клієнтській програмі, він буде перенаправлений на автентифікацію спочатку через сервер автентифікації.

І ми збираємось використовувати тип надання коду авторизації з OAuth2 для керування делегуванням автентифікації.

Примітка . Ця стаття використовує успадкований проект Spring OAuth. Для версії цієї статті, що використовує новий стек Spring Security 5, перегляньте нашу статтю Простий єдиний вхід із Spring Security OAuth2.

2. Клієнтська програма

Почнемо з нашої програми для клієнтів; ми, звичайно, використаємо Spring Boot, щоб мінімізувати конфігурацію:

2.1. Залежності Maven

По-перше, нам знадобляться такі залежності в нашому pom.xml :

 org.springframework.boot spring-boot-starter-web   org.springframework.boot spring-boot-starter-security   org.springframework.security.oauth.boot spring-security-oauth2-autoconfigure 2.0.1.RELEASE   org.springframework.boot spring-boot-starter-thymeleaf   org.thymeleaf.extras thymeleaf-extras-springsecurity4 

2.2. Конфігурація безпеки

Далі, найважливіша частина, конфігурація безпеки нашої клієнтської програми:

@Configuration @EnableOAuth2Sso public class UiSecurityConfig extends WebSecurityConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http.antMatcher("/**") .authorizeRequests() .antMatchers("/", "/login**") .permitAll() .anyRequest() .authenticated(); } }

Основною частиною цієї конфігурації є, звичайно, анотація @ EnableOAuth2Sso, яку ми використовуємо, щоб увімкнути функцію єдиного входу.

Зверніть увагу, що нам потрібно розширити WebSecurityConfigurerAdapter - без нього всі шляхи будуть захищені - тому користувачі будуть перенаправлені для входу при спробі отримати доступ до будь-якої сторінки. У нашому випадку тут сторінки з індексом та логіном - це єдині сторінки, до яких можна отримати доступ без автентифікації.

Нарешті, ми також визначили компонент RequestContextListener для обробки обсягу запитів.

І application.yml :

server: port: 8082 servlet: context-path: /ui session: cookie: name: UISESSION security: basic: enabled: false oauth2: client: clientId: SampleClientId clientSecret: secret accessTokenUri: //localhost:8081/auth/oauth/token userAuthorizationUri: //localhost:8081/auth/oauth/authorize resource: userInfoUri: //localhost:8081/auth/user/me spring: thymeleaf: cache: false

Кілька коротких приміток:

  • ми вимкнули базову автентифікацію за замовчуванням
  • accessTokenUri - це URI для отримання токенів доступу
  • userAuthorizationUri - це URI авторизації, на який будуть перенаправлені користувачі
  • userInfoUri URI кінцевої точки користувача для отримання поточних даних про користувача

Також зауважте, що в нашому прикладі тут ми розгорнули наш сервер авторизації, але, звичайно, ми можемо використовувати й інших сторонніх провайдерів, таких як Facebook або GitHub.

2.3. Передній кінець

Тепер давайте поглянемо на інтерфейсну конфігурацію нашої клієнтської програми. Ми не будемо зосереджуватись на цьому тут, головним чином тому, що ми вже охоплювали сайт.

Наш клієнтський додаток має дуже простий інтерфейс; ось index.html :

 Login

І securedPage.html :

 Welcome, Name

На сторінці securedPage.html потрібна була автентифікація користувачів. Якщо неавторизований користувач намагається отримати доступ до securedPage.html , його спочатку перенаправлять на сторінку входу.

3. Сервер авторизації

А тепер давайте обговоримо наш сервер авторизації тут.

3.1. Залежності Maven

Спочатку нам потрібно визначити залежності в нашому pom.xml :

 org.springframework.boot spring-boot-starter-web   org.springframework.security.oauth spring-security-oauth2 2.3.3.RELEASE 

3.2. Конфігурація OAuth

Важливо розуміти, що ми збираємось запустити тут сервер авторизації та сервер ресурсів як єдиний блок, що розгортається.

Почнемо з конфігурації нашого сервера ресурсів, який одночасно є нашим основним завантажувальним додатком:

@SpringBootApplication @EnableResourceServer public class AuthorizationServerApplication extends SpringBootServletInitializer { public static void main(String[] args) { SpringApplication.run(AuthorizationServerApplication.class, args); } }

Потім ми налаштуємо наш сервер авторизації:

@Configuration @EnableAuthorizationServer public class AuthServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private BCryptPasswordEncoder passwordEncoder; @Override public void configure( AuthorizationServerSecurityConfigurer oauthServer) throws Exception { oauthServer.tokenKeyAccess("permitAll()") .checkTokenAccess("isAuthenticated()"); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient("SampleClientId") .secret(passwordEncoder.encode("secret")) .authorizedGrantTypes("authorization_code") .scopes("user_info") .autoApprove(true) .redirectUris( "//localhost:8082/ui/login","//localhost:8083/ui2/login"); } }

Зверніть увагу , як ми тільки що дозволяє простий клієнт , використовуючи authorization_code типу гранту.

Також зверніть увагу, як для параметра autoApprove встановлено значення true, щоб нас не перенаправляли та не просували вручну затверджувати будь-які області.

3.3. Конфігурація безпеки

По-перше, ми вимкнемо базову автентифікацію за замовчуванням за допомогою нашого application.properties :

server.port=8081 server.servlet.context-path=/auth

Тепер перейдемо до конфігурації та визначимо простий механізм входу у форму:

@Configuration @Order(1) public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.requestMatchers() .antMatchers("/login", "/oauth/authorize") .and() .authorizeRequests() .anyRequest().authenticated() .and() .formLogin().permitAll(); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.inMemoryAuthentication() .withUser("john") .password(passwordEncoder().encode("123")) .roles("USER"); } @Bean public BCryptPasswordEncoder passwordEncoder(){ return new BCryptPasswordEncoder(); } }

Зверніть увагу, що ми використовували просту автентифікацію в пам’яті, але ми можемо просто замінити її користувацьким userDetailsService .

3.4. Кінцева точка користувача

Нарешті, ми створимо свою кінцеву точку користувача, яку ми використовували раніше в нашій конфігурації:

@RestController public class UserController { @GetMapping("/user/me") public Principal user(Principal principal) { return principal; } }

Звичайно, це поверне дані користувача із поданням JSON.

4. Висновок

У цьому короткому посібнику ми зосередилися на реалізації єдиного входу за допомогою Spring Security Oauth2 та Spring Boot.

Як завжди, повний вихідний код можна знайти на GitHub.