Spring Security實(shí)現(xiàn)身份認(rèn)證和授權(quán)的示例代碼
Spring Security 是一個(gè)開源的安全框架,提供了基于權(quán)限的訪問控制、身份認(rèn)證、安全性事件發(fā)布等功能。在 Spring Boot 應(yīng)用中使用 Spring Security 可以非常方便地實(shí)現(xiàn)用戶身份認(rèn)證和授權(quán)。
Spring Security 實(shí)現(xiàn)身份認(rèn)證的主要方式是使用認(rèn)證過濾器鏈,該過濾器鏈包含多個(gè)過濾器,用于對(duì)用戶進(jìn)行身份驗(yàn)證和授權(quán)。在 Spring Security 中,認(rèn)證和授權(quán)處理是通過過濾器鏈中的過濾器來實(shí)現(xiàn)的,最終返回一個(gè)認(rèn)證成功的用戶對(duì)象。本文將介紹 Spring Security 如何實(shí)現(xiàn)身份認(rèn)證和授權(quán),并提供示例代碼。
1. Spring Security 的身份認(rèn)證
Spring Security 的身份認(rèn)證是通過 AuthenticationManager 接口實(shí)現(xiàn)的。AuthenticationManager 接口是一個(gè)認(rèn)證管理器,用于對(duì)用戶進(jìn)行身份驗(yàn)證。在 Spring Security 中,AuthenticationManager 接口的默認(rèn)實(shí)現(xiàn)是 ProviderManager。
ProviderManager 是一個(gè)認(rèn)證管理器,它包含一個(gè)或多個(gè) AuthenticationProvider 實(shí)現(xiàn),用于對(duì)用戶進(jìn)行身份驗(yàn)證。AuthenticationProvider 接口是一個(gè)認(rèn)證提供者,用于驗(yàn)證用戶身份。在 Spring Security 中,AuthenticationProvider 的默認(rèn)實(shí)現(xiàn)是 DaoAuthenticationProvider。
DaoAuthenticationProvider 是一個(gè)認(rèn)證提供者,用于對(duì)用戶進(jìn)行身份驗(yàn)證。它需要一個(gè) UserDetailsService 實(shí)現(xiàn)來獲取用戶信息和密碼,然后使用 PasswordEncoder 進(jìn)行密碼校驗(yàn)。UserDetailsService 接口是一個(gè)用戶詳細(xì)信息服務(wù)接口,用于獲取用戶信息和密碼。PasswordEncoder 接口是一個(gè)密碼編碼器接口,用于對(duì)密碼進(jìn)行編碼和解碼。
下面是一個(gè)基本的 Spring Security 配置示例,用于實(shí)現(xiàn)身份認(rèn)證:
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { ? ? @Autowired ? ? private UserDetailsService userDetailsService; ? ? @Autowired ? ? private PasswordEncoder passwordEncoder; ? ? @Override ? ? protected void configure(HttpSecurity http) throws Exception { ? ? ? ? http.authorizeRequests() ? ? ? ? ? ? .antMatchers("/admin/**").hasRole("ADMIN") ? ? ? ? ? ? .antMatchers("/user/**").hasRole("USER") ? ? ? ? ? ? .anyRequest().authenticated() ? ? ? ? ? ? .and() ? ? ? ? ? ? .formLogin() ? ? ? ? ? ? .and() ? ? ? ? ? ? .logout() ? ? ? ? ? ? .and() ? ? ? ? ? ? .csrf().disable(); ? ? } ? ? @Override ? ? protected void configure(AuthenticationManagerBuilder auth) throws Exception { ? ? ? ? auth.userDetailsService(userDetailsService) ? ? ? ? ? ? .passwordEncoder(passwordEncoder); ? ? } ? }
在上面的代碼中,使用 @EnableWebSecurity 注解啟用 Spring Security。configure(HttpSecurity http) 方法用于配置訪問控制,指定哪些 URL 需要哪些角色才能訪問,以及任何請(qǐng)求都需要經(jīng)過身份驗(yàn)證。formLogin() 方法啟用基于表單的身份驗(yàn)證,logout() 方法啟用注銷支持,csrf().disable() 方法禁用 CSRF 保護(hù)。
configure(AuthenticationManagerBuilder auth) 方法用于配置身份驗(yàn)證,指定使用哪個(gè) UserDetailsService 實(shí)現(xiàn)來獲取用戶信息和密碼,以及使用哪個(gè) PasswordEncoder 實(shí)現(xiàn)進(jìn)行密碼校驗(yàn)。
2. Spring Security 的授權(quán)
Spring Security 的授權(quán)是通過 AccessDecisionManager 接口實(shí)現(xiàn)的。AccessDecisionManager 接口是一個(gè)訪問決策管理器,用于決定用戶是否有權(quán)限訪問某個(gè)資源。在 Spring Security 中,AccessDecisionManager 接口的默認(rèn)實(shí)現(xiàn)是 AffirmativeBased。
AffirmativeBased 是一個(gè)訪問決策管理器,它包含一個(gè)或多個(gè) AccessDecisionVoter 實(shí)現(xiàn),用于決定用戶是否有權(quán)限訪問某個(gè)資源。AccessDecisionVoter 接口是一個(gè)投票者,用于決定用戶是否有權(quán)限訪問某個(gè)資源。在 Spring Security 中,AccessDecisionVoter 的默認(rèn)實(shí)現(xiàn)是 RoleVoter。
RoleVoter 是一個(gè)投票者,用于根據(jù)用戶的角色決定用戶是否有權(quán)限訪問某個(gè)資源。在 Spring Security 中,我們可以通過實(shí)現(xiàn) AccessDecisionVoter 接口來自定義投票者,根據(jù)自己的需求來決定用戶是否有權(quán)限訪問某個(gè)資源。
下面是一個(gè)基本的 Spring Security 配置示例,用于實(shí)現(xiàn)授權(quán):
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { ? ? @Autowired ? ? private UserDetailsService userDetailsService; ? ? @Autowired ? ? private PasswordEncoder passwordEncoder; ? ? @Override ? ? protected void configure(HttpSecurity http) throws Exception { ? ? ? ? http.authorizeRequests() ? ? ? ? ? ? .antMatchers("/admin/**").hasRole("ADMIN") ? ? ? ? ? ? .antMatchers("/user/**").hasRole("USER") ? ? ? ? ? ? .anyRequest().authenticated() ? ? ? ? ? ? .and() ? ? ? ? ? ? .formLogin() ? ? ? ? ? ? .and() ? ? ? ? ? ? .logout() ? ? ? ? ? ? .and() ? ? ? ? ? ? .csrf().disable(); ? ? } ? ? @Override ? ? protected void configure(AuthenticationManagerBuilder auth) throws Exception { ? ? ? ? auth.userDetailsService(userDetailsService) ? ? ? ? ? ? .passwordEncoder(passwordEncoder); ? ? }
@Bean在上面的代碼中,使用 @Bean 注解創(chuàng)建了一個(gè)自定義的 AccessDecisionVoter 實(shí)例,用于自定義投票邏輯。在 configure(HttpSecurity http) 方法中,通過 accessDecisionManager() 方法將自定義的 AccessDecisionVoter 實(shí)例添加到訪問決策管理器中。
3. 完整的示例代碼
下面是一個(gè)完整的 Spring Security 配置示例代碼,用于實(shí)現(xiàn)身份認(rèn)證和授權(quán):
@Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { ? ? @Autowired ? ? private UserDetailsService userDetailsService; ? ? @Autowired ? ? private PasswordEncoder passwordEncoder; ? ? @Override ? ? protected void configure(HttpSecurity http) throws Exception { ? ? ? ? http.authorizeRequests() ? ? ? ? ? ? .antMatchers("/admin/**").hasRole("ADMIN") ? ? ? ? ? ? .antMatchers("/user/**").hasRole("USER") ? ? ? ? ? ? .anyRequest().authenticated() ? ? ? ? ? ? .and() ? ? ? ? ? ? .formLogin() ? ? ? ? ? ? .and() ? ? ? ? ? ? .logout() ? ? ? ? ? ? .and() ? ? ? ? ? ? .csrf().disable() ? ? ? ? ? ? .exceptionHandling() ? ? ? ? ? ? .accessDeniedPage("/403"); ? ? } ? ? @Override ? ? protected void configure(AuthenticationManagerBuilder auth) throws Exception { ? ? ? ? auth.userDetailsService(userDetailsService) ? ? ? ? ? ? .passwordEncoder(passwordEncoder); ? ? } ? ? @Bean ? ? public AccessDecisionVoter<Object> accessDecisionVoter(){ ? ? ? ? RoleHierarchyVoter roleHierarchyVoter = new RoleHierarchyVoter(roleHierarchy()); ? ? ? ? return roleHierarchyVoter; ? ? } ? ? @Bean ? ? public RoleHierarchyImpl roleHierarchy() { ? ? ? ? RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl(); ? ? ? ? roleHierarchy.setHierarchy("ROLE_ADMIN > ROLE_USER"); ? ? ? ? return roleHierarchy; ? ? } ? ? @Bean ? ? public PasswordEncoder passwordEncoder() { ? ? ? ? return new BCryptPasswordEncoder(); ? ? } }
在上面的代碼中,使用 @EnableWebSecurity 注解啟用 Spring Security。configure(HttpSecurity http) 方法用于配置訪問控制,指定哪些 URL 需要哪些角色才能訪問,以及任何請(qǐng)求都需要經(jīng)過身份驗(yàn)證。formLogin() 方法啟用基于表單的身份驗(yàn)證,logout() 方法啟用注銷支持,csrf().disable() 方法禁用 CSRF 保護(hù),并且使用 accessDeniedPage() 方法指定訪問被拒絕時(shí)跳轉(zhuǎn)的頁面。
configure(AuthenticationManagerBuilder auth) 方法用于配置身份驗(yàn)證,指定使用哪個(gè) UserDetailsService 實(shí)現(xiàn)來獲取用戶信息和密碼,以及使用哪個(gè) PasswordEncoder 實(shí)現(xiàn)進(jìn)行密碼校驗(yàn)。
accessDecisionVoter() 方法創(chuàng)建了一個(gè)自定義的 AccessDecisionVoter 實(shí)例,用于自定義投票邏輯。在這個(gè)例子中,我們使用了 RoleHierarchyVoter 類實(shí)現(xiàn)了一個(gè)基于角色繼承關(guān)系的投票邏輯。RoleHierarchyImpl 類用于定義角色繼承關(guān)系。
passwordEncoder() 方法用于創(chuàng)建一個(gè)密碼編碼器實(shí)例,這里我們使用了 BCryptPasswordEncoder 類實(shí)現(xiàn)密碼編碼。
最后,我們需要實(shí)現(xiàn) UserDetailsService 接口,用于獲取用戶信息和密碼。下面是一個(gè)簡(jiǎn)單的實(shí)現(xiàn)示例:
@Service public class UserDetailsServiceImpl implements UserDetailsService { ? ? @Autowired ? ? private UserRepository userRepository; ? ? @Override ? ? public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { ? ? ? ? User user = userRepository.findByUsername(username) ? ? ? ? ? ? ? ? .orElseThrow(() -> new UsernameNotFoundException("User not found with username: " + username)); ? ? ? ? return new org.springframework.security.core.userdetails.User( ? ? ? ? ? ? ? ? user.getUsername(), ? ? ? ? ? ? ? ? user.getPassword(), ? ? ? ? ? ? ? ? user.getRoles().stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList())); ? ? } }
在上面的代碼中,我們使用 UserRepository 類獲取用戶信息和密碼,并將其包裝成一個(gè) UserDetails 實(shí)例返回。在這個(gè)例子中,我們使用了 org.springframework.security.core.userdetails.User 類實(shí)現(xiàn)了 UserDetails 接口。
結(jié)語
Spring Security 是一個(gè)非常強(qiáng)大的安全框架,可以為 Spring Boot 應(yīng)用提供完整的身份認(rèn)證和授權(quán)功能。本文介紹了 Spring Security 如何實(shí)現(xiàn)身份認(rèn)證和授權(quán),并提供了示例代碼。使用 Spring Security 可以非常方便地保護(hù)應(yīng)用程序,防止惡意攻擊和數(shù)據(jù)泄露。
到此這篇關(guān)于Spring Security實(shí)現(xiàn)身份認(rèn)證和授權(quán)的示例代碼的文章就介紹到這了,更多相關(guān)Spring Security身份認(rèn)證和授權(quán)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringAOP切入點(diǎn)規(guī)范及獲取方法參數(shù)的實(shí)現(xiàn)
這篇文章主要介紹了SpringAOP切入點(diǎn)規(guī)范及獲取方法參數(shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06Java Map 通過 key 或者 value 過濾的實(shí)例代碼
這篇文章主要介紹了Java Map 通過 key 或者 value 過濾的實(shí)例代碼,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2018-06-06詳解Jenkins 實(shí)現(xiàn)Gitlab事件自動(dòng)觸發(fā)Jenkins構(gòu)建及釘釘消息推送
這篇文章主要介紹了Jenkins 實(shí)現(xiàn)Gitlab事件自動(dòng)觸發(fā)Jenkins構(gòu)建及釘釘消息推送,應(yīng)該會(huì)對(duì)大家學(xué)習(xí)Jenkins有所啟發(fā)2021-04-04解決IDEA使用Spring Initializr創(chuàng)建項(xiàng)目時(shí)無法連接到https://start.spring.io的問
這篇文章主要介紹了解決IDEA使用Spring Initializr創(chuàng)建項(xiàng)目時(shí)無法連接到https://start.spring.io的問題,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04Java后端Cookie實(shí)現(xiàn)(時(shí)間戳)代碼實(shí)例
這篇文章主要介紹了Java后端Cookie實(shí)現(xiàn)(時(shí)間戳)代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-12-12深入學(xué)習(xí)java內(nèi)存化和函數(shù)式協(xié)同
這篇文章主要介紹了深入學(xué)習(xí)java內(nèi)存化和函數(shù)式協(xié)同,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,,需要的朋友可以參考下2019-06-06SpringBoot同一接口多個(gè)實(shí)現(xiàn)類配置的實(shí)例詳解
這篇文章主要介紹了SpringBoot同一接口多個(gè)實(shí)現(xiàn)類配置的實(shí)例詳解,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-11-11