Множество доставчици на удостоверяване в пролетната сигурност

1. Общ преглед

В тази кратка статия ще се съсредоточим върху използването на множество механизми за удостоверяване на потребителите в Spring Security.

Ще направим това, като конфигурираме множество доставчици на удостоверяване.

2. Доставчици на удостоверяване

Един AuthenticationProvider е абстракция за извличане на информация за потребителите от определен хранилище (като база данни, LDAP, източник обичай трето лице и т.н.). Той използва извлечената потребителска информация за проверка на предоставените идентификационни данни.

Просто казано, когато са дефинирани множество доставчици на удостоверяване, доставчиците ще бъдат запитвани в реда, в който са декларирани.

За бърза демонстрация ще конфигурираме два доставчика на удостоверяване - персонализиран доставчик на удостоверяване и доставчик на удостоверяване в паметта.

3. Зависимости на Maven

Нека първо добавим необходимите зависимости Spring Security в нашето уеб приложение:

 org.springframework.boot spring-boot-starter-web   org.springframework.boot spring-boot-starter-security  

И без Spring Boot:

 org.springframework.security spring-security-web 5.2.2.RELEASE   org.springframework.security spring-security-core 5.2.2.RELEASE   org.springframework.security spring-security-config 5.2.2.RELEASE 

Най-новата версия на тези зависимости може да бъде намерена в spring-security-web, spring-security-core и spring-security-config.

4. Персонализиран доставчик на удостоверяване

Нека сега създадем персонализиран доставчик на удостоверяване чрез внедряване на интерфейса AuthneticationProvider .

Ще приложим метода за удостоверяване - който прави опит за удостоверяване. Входният обект за удостоверяване съдържа идентификационни данни за потребителско име и парола, предоставени от потребителя.

В автентичността метод връща изцяло населен Authentication обект, ако удостоверяването е успешно. Ако удостоверяването е неуспешно, то извежда изключение от типа AuthenticationException :

@Component public class CustomAuthenticationProvider implements AuthenticationProvider { @Override public Authentication authenticate(Authentication auth) throws AuthenticationException { String username = auth.getName(); String password = auth.getCredentials() .toString(); if ("externaluser".equals(username) && "pass".equals(password)) { return new UsernamePasswordAuthenticationToken (username, password, Collections.emptyList()); } else { throw new BadCredentialsException("External system authentication failed"); } } @Override public boolean supports(Class auth) { return auth.equals(UsernamePasswordAuthenticationToken.class); } }

Естествено, това е просто изпълнение за целите на нашия пример тук.

5. Конфигуриране на множество доставчици на удостоверяване

Нека сега добавим CustomAuthenticationProvider и доставчик на удостоверяване в паметта към нашата конфигурация Spring Security.

5.1. Конфигурация на Java

В нашия конфигурационен клас нека сега създадем и добавим доставчиците на удостоверяване с помощта на AuthenticationManagerBuilder .

Първо CustomAuthenticationProvider и след това доставчик на удостоверяване в паметта чрез inMemoryAuthentication () .

Ние също така се уверяваме, че достъпът до URL образеца „ / api / ** “ трябва да бъде удостоверен:

@EnableWebSecurity public class MultipleAuthProvidersSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired CustomAuthenticationProvider customAuthProvider; @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(customAuthProvider); auth.inMemoryAuthentication() .withUser("memuser") .password(encoder().encode("pass")) .roles("USER"); } @Override protected void configure(HttpSecurity http) throws Exception { http.httpBasic() .and() .authorizeRequests() .antMatchers("/api/**") .authenticated(); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }

5.2. XML конфигурация

Като алтернатива, ако искаме да използваме XML конфигурация вместо Java конфигурация:

6. Приложението

След това нека създадем проста крайна точка REST, която е защитена от нашите двама доставчици на удостоверяване.

За достъп до тази крайна точка трябва да се предоставят валидно потребителско име и парола. Нашите доставчици на удостоверяване ще валидират идентификационните данни и ще определят дали да разрешат достъп или не:

@RestController public class MultipleAuthController { @GetMapping("/api/ping") public String getPing() { return "OK"; } }

7. Тестване

И накрая, нека сега тестваме достъпа до нашето защитено приложение. Достъпът ще бъде разрешен само ако са предоставени валидни идентификационни данни:

@Autowired private TestRestTemplate restTemplate; @Test public void givenMemUsers_whenGetPingWithValidUser_thenOk() { ResponseEntity result = makeRestCallToGetPing("memuser", "pass"); assertThat(result.getStatusCodeValue()).isEqualTo(200); assertThat(result.getBody()).isEqualTo("OK"); } @Test public void givenExternalUsers_whenGetPingWithValidUser_thenOK() { ResponseEntity result = makeRestCallToGetPing("externaluser", "pass"); assertThat(result.getStatusCodeValue()).isEqualTo(200); assertThat(result.getBody()).isEqualTo("OK"); } @Test public void givenAuthProviders_whenGetPingWithNoCred_then401() { ResponseEntity result = makeRestCallToGetPing(); assertThat(result.getStatusCodeValue()).isEqualTo(401); } @Test public void givenAuthProviders_whenGetPingWithBadCred_then401() { ResponseEntity result = makeRestCallToGetPing("user", "bad_password"); assertThat(result.getStatusCodeValue()).isEqualTo(401); } private ResponseEntity makeRestCallToGetPing(String username, String password) { return restTemplate.withBasicAuth(username, password) .getForEntity("/api/ping", String.class, Collections.emptyMap()); } private ResponseEntity makeRestCallToGetPing() { return restTemplate .getForEntity("/api/ping", String.class, Collections.emptyMap()); }

8. Заключение

В този бърз урок видяхме как могат да бъдат конфигурирани множество доставчици на удостоверяване в Spring Security. Подсигурихме просто приложение, използвайки персонализиран доставчик на удостоверяване и доставчик на удостоверяване в паметта.

Освен това сме написали тестове, за да потвърдим, че достъпът до нашето приложение изисква идентификационни данни, които могат да бъдат потвърдени от поне един от нашите доставчици на удостоверяване.

Както винаги, пълният изходен код на внедряването може да бъде намерен в GitHub.