1. 程式人生 > >Spring Security身份認證之UserDetailsService

Spring Security身份認證之UserDetailsService

        之前我們採用了配置檔案的方式從資料庫中讀取使用者進行登入。雖然該方式的靈活性相較於靜態賬號密碼的方式靈活了許多,但是將資料庫的結構暴露在明顯的位置上,絕對不是一個明智的做法。本文通過Java程式碼實現UserDetailsService介面來實現身份認證。


    1.1 UserDetailsService在身份認證中的作用

    Spring Security中進行身份驗證的是AuthenticationManager介面,ProviderManager是它的一個預設實現,但它並不用來處理身份認證,而是委託給配置好的AuthenticationProvider,每個AuthenticationProvider會輪流檢查身份認證。檢查後或者返回Authentication物件或者丟擲異常。


    驗證身份就是載入響應的UserDetails,看看是否和使用者輸入的賬號、密碼、許可權等資訊匹配。此步驟由實現AuthenticationProvider的DaoAuthenticationProvider(它利用UserDetailsService驗證使用者名稱、密碼和授權)處理。包含 GrantedAuthority 的 UserDetails物件在構建 Authentication物件時填入資料。



1.2 配置UserDetailsService

    1.2.1 更改Spring-Security.xml中身份的方式,使用自定義的UserDetailsService。

<security:authentication-manager> 
	<security:authentication-provider user-service ref="favUserDetailService">     
	</security:authentication-provider>
</security:authentication-manager>
<bean id="favUserDetailService" class="com.favccxx.favsecurity.security.FavUserDetailService" />

    1.2.2 新建FavUserDetailsService.java,實現UserDetailsService介面。為了降低學習的難度,這裡並沒有與資料庫進行整合,而是採用模擬從資料庫中獲取使用者的方式進行身份驗證。示例程式碼如下:

package com.favccxx.favsecurity.security;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

public class FavUserDetailService implements UserDetailsService {
	private static final Logger logger = LogManager.getLogger(FavUserDetailService.class);  
	/**  * 根據使用者名稱獲取使用者 - 使用者的角色、許可權等資訊   */
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {      
		UserDetails userDetails = null;     
		try {           
			com.favccxx.favsecurity.pojo.User favUser = new com.favccxx.favsecurity.pojo.User();            
			favUser.setUsername("favccxx");        
			favUser.setPassword("favccxx");         
			Collection<GrantedAuthority> authList = getAuthorities();         
			userDetails = new User(username, favUser.getPassword().toLowerCase(),true,true,true,true,authList);     
		}catch (Exception e) {         
			e.printStackTrace();        
		}       
		return userDetails; 
	}
	/**  * 獲取使用者的角色許可權,為了降低實驗的難度,這裡去掉了根據使用者名稱獲取角色的步驟     * @param    * @return   */ 
	private Collection<GrantedAuthority> getAuthorities(){        
		List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>();       
		authList.add(new SimpleGrantedAuthority("ROLE_USER"));      
		authList.add(new SimpleGrantedAuthority("ROLE_ADMIN"));     
		return authList;    
	}
}


    1.2.3 啟動應用伺服器,只要使用者名稱和密碼不全是favccxx,就會產生下面的錯誤。



    使用者名稱和密碼都輸入favccxx,則登陸成功



1.3 跟蹤UserDetailsService。

    身份認證的呼叫流程圖如下,使用者可下載Spring Security原始碼跟蹤除錯。