Ubah hala ke Halaman Berbeza selepas Masuk dengan Spring Security

1. Gambaran keseluruhan

Syarat umum untuk aplikasi web adalah mengarahkan jenis pengguna yang berlainan ke halaman yang berbeza setelah log masuk . Contohnya ialah mengalihkan pengguna standard ke halaman /homepage.html dan pengguna pentadbir ke halaman /console.html misalnya.

Artikel ini akan menunjukkan cara melaksanakan mekanisme ini dengan cepat dan selamat menggunakan Spring Security. Artikel ini juga dibina di atas tutorial Spring MVC yang berkaitan dengan penyediaan inti MVC yang diperlukan untuk projek ini.

2. Konfigurasi Keselamatan Musim Semi

Spring Security menyediakan komponen yang mempunyai tanggungjawab langsung untuk memutuskan apa yang harus dilakukan setelah pengesahan berjaya - AuthenticationSuccessHandler .

2.1. Konfigurasi Asas

Mari mula-mula mengkonfigurasi kelas @Configuration dan @Service asas :

@Configuration @EnableWebSecurity public class SecSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(final HttpSecurity http) throws Exception { http .authorizeRequests() // ... endpoints .formLogin() .loginPage("/login.html") .loginProcessingUrl("/login") .defaultSuccessUrl("/homepage.html", true) // ... other configuration } }

Bahagian konfigurasi ini untuk difokuskan adalah kaedah defaultSuccessUrl () . Setelah berjaya masuk, pengguna mana pun akan diarahkan ke homepage.html .

Tambahan pula, kita perlu mengkonfigurasi pengguna dan peranan mereka. Untuk tujuan artikel ini, kami akan menerapkan UserDetailService sederhana dengan dua pengguna, masing-masing mempunyai satu peranan tunggal. Untuk lebih lanjut mengenai topik ini, baca artikel kami Spring Security - Peranan dan Keistimewaan.

@Service public class MyUserDetailsService implements UserDetailsService { private Map roles = new HashMap(); @PostConstruct public void init() { roles.put("admin2", new User("admin", "{noop}admin1", getAuthority("ROLE_ADMIN"))); roles.put("user2", new User("user", "{noop}user1", getAuthority("ROLE_USER"))); } @Override public UserDetails loadUserByUsername(String username) { return roles.get(username); } private List getAuthority(String role) { return Collections.singletonList(new SimpleGrantedAuthority(role)); } } 

Perhatikan juga bahawa dalam contoh mudah ini, kami tidak akan menggunakan pengekod kata laluan, oleh itu kata laluan diawali dengan {noop} .

2.2. Menambah Pengendali Kejayaan Tersuai

Kami kini mempunyai dua pengguna dengan dua peranan yang berbeza: pengguna dan pentadbir . Setelah berjaya masuk, kedua-duanya akan dialihkan ke hompeage.html . Mari lihat bagaimana kita boleh melakukan pengalihan yang berbeza berdasarkan peranan pengguna.

Pertama, kita perlu menentukan pengendali kejayaan tersuai sebagai kacang:

@Bean public AuthenticationSuccessHandler myAuthenticationSuccessHandler(){ return new MySimpleUrlAuthenticationSuccessHandler(); } 

Dan kemudian ganti panggilan defaultSuccessUrl dengan kaedah successHandler , yang menerima pengendali kejayaan tersuai kami sebagai parameter:

@Override protected void configure(final HttpSecurity http) throws Exception { http .authorizeRequests() // endpoints .formLogin() .loginPage("/login.html") .loginProcessingUrl("/login") .successHandler(myAuthenticationSuccessHandler()) // other configuration } 

2.3. Konfigurasi XML

Sebelum melihat pelaksanaan pengendali kejayaan tersuai kami, mari kita lihat juga konfigurasi XML yang setara:

3. Penangan Kejayaan Pengesahan Tersuai

Selain antara muka AuthenticationSuccessHandler , Spring juga menyediakan lalai yang wajar untuk komponen strategi ini - AbstractAuthenticationTargetUrlRequestHandler dan pelaksanaan yang mudah - SimpleUrlAuthenticationSuccessHandler . Biasanya pelaksanaan ini akan menentukan URL setelah log masuk dan melakukan pengalihan ke URL tersebut.

Walaupun agak fleksibel, mekanisme untuk menentukan URL sasaran ini tidak membenarkan penentuan dilakukan secara terprogram - jadi kami akan melaksanakan antara muka dan menyediakan pelaksanaan khas penangan kejayaan. Pelaksanaan ini akan menentukan URL untuk mengarahkan pengguna ke selepas log masuk berdasarkan peranan pengguna.

Pertama sekali, kita perlu mengatasi kaedah onAuthenticationSuccess :

public class MySimpleUrlAuthenticationSuccessHandler implements AuthenticationSuccessHandler { protected Log logger = LogFactory.getLog(this.getClass()); private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException { handle(request, response, authentication); clearAuthenticationAttributes(request); } 

Kaedah khusus kami memanggil dua kaedah penolong:

protected void handle( HttpServletRequest request, HttpServletResponse response, Authentication authentication ) throws IOException { String targetUrl = determineTargetUrl(authentication); if (response.isCommitted()) { logger.debug( "Response has already been committed. Unable to redirect to " + targetUrl); return; } redirectStrategy.sendRedirect(request, response, targetUrl); } 

Di mana kaedah berikut berfungsi dengan betul dan memetakan pengguna ke URL sasaran:

protected String determineTargetUrl(final Authentication authentication) { Map roleTargetUrlMap = new HashMap(); roleTargetUrlMap.put("ROLE_USER", "/homepage.html"); roleTargetUrlMap.put("ROLE_ADMIN", "/console.html"); final Collection authorities = authentication.getAuthorities(); for (final GrantedAuthority grantedAuthority : authorities) { String authorityName = grantedAuthority.getAuthority(); if(roleTargetUrlMap.containsKey(authorityName)) { return roleTargetUrlMap.get(authorityName); } } throw new IllegalStateException(); } 

Perhatikan bahawa kaedah ini akan mengembalikan URL yang dipetakan untuk peranan pertama yang dimiliki pengguna. Oleh itu, jika pengguna mempunyai pelbagai peranan, URL yang dipetakan akan menjadi yang sesuai dengan peranan pertama yang diberikan dalam koleksi pihak berkuasa .

protected void clearAuthenticationAttributes(HttpServletRequest request) { HttpSession session = request.getSession(false); if (session == null) { return; } session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION); }

The determinTargetUrl - yang merupakan inti strategi - hanya melihat jenis pengguna (ditentukan oleh pihak berkuasa) dan memilih URL sasaran berdasarkan peranan ini .

Oleh itu, pengguna pentadbir - ditentukan oleh pihak berkuasa ROLE_ADMIN - akan diarahkan ke halaman konsol setelah log masuk, sementara pengguna standard - seperti yang ditentukan oleh ROLE_USER - akan diarahkan ke laman utama.

4. Kesimpulan

Seperti biasa, kod yang disajikan dalam artikel ini terdapat di GitHub. Ini adalah projek berasaskan Maven, jadi mudah diimport dan dijalankan sebagaimana adanya.