spring安全框架Security(二)

好,咱們往下看,接着就是應用咱們實際項目裏的自定義用戶權限了html

    Java代碼 java

<security:authentication-manager>  
     <security:authentication-provider user-service-ref="customUserDetailsService">  
         <security:password-encoder ref="passwordEncoder" />  
     </security:authentication-provider>  
</security:authentication-manager>  
  
    <!-- 對密碼進行MD5編碼 -->  
<bean id="passwordEncoder" class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" />  
<bean id="customUserDetailsService" class="org.yzsoft.springmvcdemo.util.CustomUserDetailsService" />


  首先是<security:authentication-manager>是指定咱們自定義的身份驗證策略,這裏咱們用customUserDetailsService這個bean,就是指向咱們CustomUserDetailsService.java這個類。而後<security:password-encoder>指定咱們密碼使用MD5進行編碼,調用Spring Security自帶的MD5加密類。固然,還有加鹽MD5或咱們本身寫的加密算法等安全性更加高的密碼策略。這個按項目實際使用配置吧。
web

而後看到咱們的CustomUserDetailsService.java算法

    Java代碼 spring

package org.yzsoft.springmvcdemo.util;  
  
import java.util.ArrayList;  
import java.util.Collection;  
import java.util.List;  
  
import org.apache.log4j.Logger;  
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.dao.DataAccessException;  
import org.springframework.security.core.GrantedAuthority;  
import org.springframework.security.core.authority.GrantedAuthorityImpl;  
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;  
import org.yzsoft.springmvcdemo.serviceimpl.UsersServiceImpl;  
import org.yzsoft.springmvcdemo.vo.TUsers;  
  
/** 
 * 一個自定義的類用來和數據庫進行操做. 即之後咱們要經過數據庫保存權限.則須要咱們繼承UserDetailsService 
 *  
 * @author  
 *  
 */  
public class CustomUserDetailsService implements UserDetailsService {  
  
    protected static Logger logger = Logger.getLogger("service");//log4j,不用解釋了吧。。  
    @Autowired  
    private UsersServiceImpl usersService;  
  
    public UsersServiceImpl getUsersService() {  
        return usersService;  
    }  
  
    public void setUsersService(UsersServiceImpl usersService) {  
        this.usersService = usersService;  
    }  
  
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {  
  
        UserDetails user = null;  
  
        try {  
  
            // 搜索數據庫以匹配用戶登陸名.  
            // 咱們能夠經過dao使用Hibernate來訪問數據庫  
            System.out.println(username + "   用戶頁面輸入的用戶名");  
            TUsers tusers = this.usersService.findByUsername(username);  
            System.out.println(tusers.getUsername() + "   數據庫取出的用戶名");  
            // Populate the Spring User object with details from the dbUser  
            // Here we just pass the username, password, and access level  
            // getAuthorities() will translate the access level to the correct  
            // role type  
            // 用戶名、密碼、是否啓用、是否被鎖定、是否過時、權限  
            user = new User(tusers.getUsername(), tusers.getPassword().toLowerCase(), true, true, true, true, getAuthorities(Integer.parseInt(tusers.getRole())));  
               
               
        } catch (Exception e) {  
            logger.error("用戶信息錯誤!");  
            throw new UsernameNotFoundException("異常處理:檢索用戶信息未經過!");  
        }  
           
        return user;  
    }  
  
    /** 
     * 得到訪問角色權限列表 
     *  
     * @param access 
     * @return 
     */  
    public Collection<GrantedAuthority> getAuthorities(Integer role) {  
        System.out.println("取得的權限是  :" + role);  
        List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>();  
  
        // 全部的用戶默認擁有ROLE_USER權限  
        if (role == 0) {  
            System.out.println("普通用戶");  
            logger.debug("取得普通用戶權限-->");  
            authList.add(new GrantedAuthorityImpl("ROLE_USERS"));  
        }  
        // 若是參數role爲1.則擁有ROLE_ADMIN權限  
        if (role == 1) {  
            logger.debug("取得ADMIN用戶權限-->");  
            authList.add(new GrantedAuthorityImpl("ROLE_ADMIN"));  
        }  
        System.out.println(authList.size()+"  權限列表長度");  
        return authList;  
    }  
}


    這裏就是把咱們從數據庫裏面取得的用戶權限和Spring Security的配置進行橋接,還記得上面配置文件裏的ROLE_ADMIN吧,就是從這裏來的,很奇怪的是,這個必須設置成ROLE_ 開頭纔有效。。鬱悶。。。數據庫

這裏我剛開始有一個疑惑,咱們看這2句apache

    Java代碼 安全

TUsers tusers = this.usersService.findByUsername(username);  
user = new User(tusers.getUsername(), tusers.getPassword().toLowerCase(), true, true, true, true, getAuthorities(Integer.parseInt(tusers.getRole())));


    這裏根本不須要用戶輸入的密碼,只要了用戶名,而後直接根據用戶名去取權限,就直接設置進Spring Security的User對象裏面去,我不由一身冷汗,這不至關於說有了用戶名就直接去查數據庫麼,並且是不用密碼的。。。。session

    但通過查看官方文檔和網上的解釋,這才放心,原來是這樣的,Spring Security的確是直接根據用戶名去查,可是查得出來的Spring Security  User對象以後,它會根據這個對象的屬性值去數據庫查詢與這個對象匹配的數據,咱們這裏設置的是(用戶名,密碼,是否啓用、是否被鎖定、是否過時、權限。。。),那麼若是數據庫存在這個對象,就返回真,不然返回假,這樣也就不用擔憂了,徹底可靠。就是咱們在前臺要作好限制,不能給用戶不輸密碼就訪問, 否則擠爆你數據庫鏈接。。。。。
mvc

    最後登錄頁面index.jsp

    Java代碼 

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>  
<%  
String path = request.getContextPath();  
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";  
%>  
  
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">  
<html>  
  <head>  
    <base href="<%=basePath%>">  
      
    <title>My JSP 'index.jsp' starting page</title>  
    <meta http-equiv="pragma" content="no-cache">  
    <meta http-equiv="cache-control" content="no-cache">  
    <meta http-equiv="expires" content="0">      
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">  
    <meta http-equiv="description" content="This is my page">   
  </head>  
    
  <body>  
    用戶登錄 <br>  
     ${SPRING_SECURITY_LAST_EXCEPTION.message}  
      <form action="j_spring_security_check" method="post">  
        USERNAME:<input type="text" name="j_username" value="${sessionScope['SPRING_SECURITY_LAST_USERNAME']}" /><br/>  
        PASSWORD:<input type="password" name="j_password" value="" /><br/>  
        <input type="checkbox" name="_spring_security_remember_me" />兩週以內沒必要登錄(這個功能沒有作的)<br/>  
        <input type="submit">       
    </form>  
  </body>  
</html>


    這裏我仍是使用Spring Security默認的j_username和j_password,表單目標也用默認的j_spring_security_check,會默認跳到Spring Security進行攔截。其餘的應該不用解釋了吧。。。。

    最後 ,咱們整理一下Spring Security的整個控制過程:

        ——>用戶登錄

        ——> <security:authentication-manager> 攔截

        ——>交給customUserDetailsService處理,而且聲明密碼採用MD5策略

        ——>根據輸入的用戶名去數據庫查這條記錄,驗證身份

        ——>取出該條記錄的用戶權限(鎖定、禁用、過時和實際權限等)

        ——>根據取得的權限列表去security:intercept-url匹配、受權,而後判斷是否放行。

    這就完成了一整個的權限控制流程。

    接下來咱們來測試一下看是否真的生效了:

        一、測試匿名訪問頁面,直接地址欄訪問:

 

 

 

 

 

        二、普通用戶登錄



  

 

 

 

        三、而後訪問後臺管理頁面,跳回了登錄頁



 

        四、管理員用戶登錄

 

 

    退出後成功跳轉回登錄頁,點擊後退再執行其餘操做,這時候session已經註銷了的,不能執行,又跳回了登錄頁。是咱們想要的效果,OK,成功了。


    好 了,Spring Security的簡單使用就講到這裏,其實這只是Spring Security的一小部分,並且這裏我尚未用權限表對用戶權限進行專門的管理,不少東西仍是用Spring Security 默認的,還有Spring Security CAS (單點登錄)以及更加高級的權限控制和更完善的Spring Security 配置,之後咱們再慢慢去研究吧。發現Spring Security 這個技術不只簡化了咱們的用戶權限管理,要知道咱們作管理系統的時候這是個大問題,也差很少顛覆了我一向以來用戶權限管理的觀念,可是掌握了這種思惟之 後,又發現,其實,程序並非只有一種實現方式,它激發了我寫程序時要去尋找多種解決方案的想法。學習的路上,就是要不斷推翻本身固有的思惟,去見識多種 新事物,纔能有進步。

相關文章
相關標籤/搜索