Pelbagai Penyedia Pengesahan dalam Keselamatan Musim Semi

1. Gambaran keseluruhan

Dalam artikel ringkas ini, kita akan fokus menggunakan pelbagai mekanisme untuk mengesahkan pengguna di Spring Security.

Kami akan melakukannya dengan mengkonfigurasi pelbagai penyedia pengesahan.

2. Penyedia Pengesahan

An AuthenticationProvider merupakan abstraksi untuk semasa mengambil maklumat pengguna dari repositori tertentu (seperti pangkalan data, LDAP, sumber parti adat ketiga, dan lain-lain). Ia menggunakan maklumat pengguna yang diambil untuk mengesahkan bukti kelayakan yang diberikan.

Ringkasnya, apabila beberapa penyedia pengesahan ditentukan, penyedia akan ditanyakan mengikut urutan yang dinyatakan.

Untuk demonstrasi pantas, kami akan mengkonfigurasi dua penyedia pengesahan - penyedia pengesahan tersuai dan penyedia pengesahan dalam memori.

3. Pergantungan Maven

Mari kita tambahkan kebergantungan Spring Security yang diperlukan ke dalam aplikasi web kami:

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

Dan, tanpa 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 

Versi terbaru dari kebergantungan ini boleh didapati di spring-security-web, spring-security-core, dan spring-security-config.

4. Penyedia Pengesahan Tersuai

Sekarang mari kita membuat pembekal pengesahan adat dengan melaksanakan AuthneticationProvider antara muka .

Kami akan melaksanakan kaedah pengesahan - yang mencuba pengesahan. Objek Pengesahan input mengandungi kredensial nama pengguna dan kata laluan yang diberikan oleh pengguna.

The ketulenan kaedah mengembalikan sepenuhnya penduduk Pengesahan objek jika pengesahan berjaya. Sekiranya pengesahan gagal, ia akan membuat pengecualian dari jenis 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); } }

Secara semula jadi, ini adalah pelaksanaan sederhana untuk tujuan contoh kita di sini.

5. Mengkonfigurasi Penyedia Autentikasi Pelbagai

Sekarang mari kita tambahkan CustomAuthenticationProvider dan penyedia pengesahan dalam memori ke konfigurasi Spring Security kami.

5.1. Konfigurasi Java

Di kelas konfigurasi kami, sekarang mari kita buat dan tambahkan penyedia pengesahan menggunakan AuthenticationManagerBuilder .

Pertama, CustomAuthenticationProvider dan kemudian, penyedia pengesahan dalam memori dengan menggunakan inMemoryAuthentication () .

Kami juga memastikan bahawa akses ke pola URL “ / api / ** ” perlu disahkan:

@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. Konfigurasi XML

Sebagai alternatif, jika kita ingin menggunakan konfigurasi XML dan bukannya konfigurasi Java:

6. Permohonan

Seterusnya, mari buat titik akhir REST ringkas yang dijamin oleh dua penyedia pengesahan kami.

Untuk mengakses titik akhir ini, nama pengguna dan kata laluan yang sah mesti diberikan. Penyedia pengesahan kami akan mengesahkan kelayakan dan menentukan sama ada membenarkan akses atau tidak:

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

7. Menguji

Akhirnya, sekarang mari kita menguji akses ke aplikasi selamat kita. Akses akan dibenarkan hanya jika kelayakan yang sah diberikan:

@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. Kesimpulannya

Dalam tutorial ringkas ini, kami telah melihat bagaimana pelbagai penyedia pengesahan dapat dikonfigurasi dalam Spring Security. Kami telah mendapatkan aplikasi mudah menggunakan penyedia pengesahan tersuai dan penyedia pengesahan dalam memori.

Dan kami juga telah membuat ujian bertulis untuk mengesahkan bahawa akses ke aplikasi kami memerlukan bukti kelayakan yang dapat disahkan oleh sekurang-kurangnya salah satu penyedia pengesahan kami.

Seperti biasa, kod sumber penuh pelaksanaan boleh didapati di GitHub.