概述
上一篇文章中,引入 Spring Security 后,項目就被保護起來。但賬號只有一個 user,密碼也是每次啟動項目時生成的。這樣不符合實際項目需求,下面介紹其他配置賬號密碼的方式。Spring Security 有三種配置賬號和密碼的方式,分別是:
- 通過配置文件
- 通過配置類
- 自定義編寫實現類
下面分別說明三種方式。
通過配置文件
在項目的 application.properties 文件中加入下面兩行配置
spring.security.user.name=tom
spring.security.user.password=123456
分別對應了賬號和密碼,重啟項目,在訪問頁面輸入上面配置的賬號 tom 密碼 123456 就可以登錄成功。
這種方式可能項目中用的不多,但是 Spring Security 既然設計出來,可能在某些場景下還是用的到的。
通過配置類
如果之前有按照上面通過 配置文件用戶 賬號密碼了,要先清除在配置文件中配置的內容,以免干擾下面內容。如果沒有,則繼續。
在項目下創建一個 configuration 包,先添加一個配置類 SecurityConfig,里面添加一個 PasswordEncoder 的 Bean,用於密碼加密。如果項目中沒有這個 Bean 會報錯。其代碼如下:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @Configuration public class SecurityConfig { @Bean PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }
然后在創建一個配置類 MyWebSecurityConfigurerAdapter,並繼承 WebSecurityConfigurerAdapter,然后重寫父類中一個 configure 方法。其代碼如下:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.crypto.password.PasswordEncoder; @Configuration public class MyWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter { @Autowired private PasswordEncoder passwordEncoder; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { String password = passwordEncoder.encode("123456"); auth.inMemoryAuthentication().withUser("tom").password(password).roles("admin"); } }
先上一步創建的 PasswordEncoder 的 Bean 注入,在重寫的父類方法 configure,此方法的作用是在內存中創建一個名為 tom 的用戶,並對密碼123456 進行加密。
重啟項目后,重新測試登陸。
自定義編寫實現類
如果有按照上面 通過配置文件 或 通過配置類 方式配置用戶賬號密碼,要先清除在配置文件中配置的內容和編寫的代碼,以免干擾下面內容。如果沒有,則繼續。
第一步 實現 UserDetailService 接口
先在項目中創建一個 Service 包,在里面創建一個 MyUserDetailsService 類,並實現接口 UserDetailsService。其代碼如下:
@Service public class MyUserDetailsService implements UserDetailsService { @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // 1 通過接收到的 username 通過 dao 層從數據庫中查數據 Object oject = dao.getMyUserByName(username); // 2 如果沒查找則拋出 UsernameNotFoundException 異常 // 3 如果查到了就就將數據庫里查到的 object 對象轉換成 User 對象 List<GrantedAuthority> auths = AuthorityUtils.commaSeparatedStringToAuthorityList("read"); // 這一步是用戶權限 User user = new User("tom", "$2a$10$IA0vYLa0B/koVjbo.9s50eeiknFSkS00lqDCnjs9NDTr0ALrIrIOm", auths); return user; } }
重寫接口中的 loadUserByUsername 的方法,這里的參數 username 就是用戶在頁面上填寫的用戶名,Spring Security 會自動拿到用戶名,然后調用這個方法,這個方法返回用戶的一些屬性,其中就包括密碼,這里的密碼是在數據庫中查的,可以看上面的注釋中的偽代碼。Spring Security 會將此方法中查詢到的正確的用戶密碼和用戶在頁面上填寫的密碼做比對,如果匹配上就登陸成功,否則就失敗。密碼匹配的過程完全就 Spring Security 內置的方法自動完成。作為開發者要做的就是通過 username 從庫里查到正確的密碼,告訴 Spring Security 就行。
上面的代碼中的 tom 是用戶名,也就是 username,后面較長的字符串是密碼(密碼存入數據庫之前都會做加密處理,加密后的密碼較長),正常應該是數據庫里查詢到用戶名和用戶密碼,這里做了簡化處理。以某電商項目為例,其中的買家就是一個用戶,一個買家包含用戶名、密碼、地址、性別等信息。但無論這個買家有個多少個屬性,一定要有賬號和密碼,這個一個用戶最基本的兩個屬性。
第二步 配置密碼加密的 Bean
在項目下創建一個 configuration 包,先添加一個配置類 SecurityConfig,里面添加一個 PasswordEncoder 的 Bean,后面用於密碼加密。其代碼如下:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; @Configuration public class SecurityConfig { @Bean PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }
如果項目中沒有配置上面這個 Bean 會報錯。
第三步 配置 WebSecurityConfigurerAdapter
然后在創建一個配置類 MyWebSecurityConfigurerAdapter,並繼承 WebSecurityConfigurerAdapter,然后重寫父類中一個 configure 方法,這里需要用到前兩個 Bean。其代碼如下:
(其實做了前面兩步后,就可以運行項目了,第三步可以省略掉,這里為了便於理解才寫了第三步)
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.password.PasswordEncoder; @Configuration public class MyWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; @Autowired private PasswordEncoder passwordEncoder; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder); } }
然后重啟項目,輸入賬號 tom 和密碼 123456 就可以登陸成功。
以上就是配置賬號密碼的三種方式。一般在項目中運用第三種方式,也就是根據用戶名 username 從數據庫從查到用戶的密碼 password,然后 Spring Security 自動用數據庫查到的密碼和前端傳過來的密碼比對,判斷是否登陸成功。