1. 程式人生 > >Spring整合shiro框架來進行驗證登入並且給使用者授權

Spring整合shiro框架來進行驗證登入並且給使用者授權

使用shiro驗證登入的流程主要就是,現在配置檔案配置好那些過濾器,然後在controller驗證登入的方法中獲取到使用者名稱密碼,把它交給shiro提供的物件 AuthenticationToken,然後呼叫它的subject.login(token); 然後跳轉到realm方法當中,然後在這個類當中去從資料庫獲取使用者名稱密碼,交給shiro進行比對,如果丟擲異常就說明沒有認證成功,沒拋異常說明認證成功,所以在controller方法當中進行trychach來判斷它是否認證成功跳轉到相應的頁面

引入jar包

<dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-all</artifactId>
            <version>1.2.2</version>
        </dependency>

在web.xml中配置spring框架提供的用於整合shiro框架的過濾器 ,切記要把shiro的過濾器放到最上面,因為誰在最上面誰就最先載入

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
  <display-name>bos-web</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  
  <!-- 配置spring框架提供的用於整合shiro框架的過濾器 -->
  <filter>
      <filter-name>shiroFilter</filter-name>
      <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  </filter>
  <filter-mapping>
      <filter-name>shiroFilter</filter-name>
      <url-pattern>/*</url-pattern>
  </filter-mapping>

這時候啟動tomcat伺服器,丟擲異常:spring工廠中不存在一個名稱為“shiroFilter”的bean物件,所以得在spring工廠裡注入一個同名的物件

在spring配置檔案中配置bean,id為shiroFilter

     <!-- 配置shiro框架的過濾器工廠物件 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <!-- 注入安全管理器物件 -->
        <property name="securityManager" ref="securityManager"/>
        <!-- 注入相關頁面訪問URL -->
        <property name="loginUrl" value="/login.jsp"/>    //登入頁面
        <property name="successUrl" value="/index.jsp"/>   //登入成功後跳的頁面
        <property name="unauthorizedUrl" value="/unauthorized.jsp"/>   //許可權不足跳的頁面
        <!--注入URL攔截規則 -->
        <property name="filterChainDefinitions">
            <value>
                /css/** = anon                    //anno代表的是匿名過濾器,就是不登入也可以訪問的頁面,**代表的是萬用字元
                /js/** = anon
                /images/** = anon
                /validatecode.jsp* = anon
                /login.jsp = anon
                /userAction_login.action = anon              //把登入訪問後臺的方法也過濾掉
                /page_base_staff.action = perms["staff-list"]      //perms這個過濾器代表的是是否具有引號裡的那個許可權,有許可權才能訪問

                                                                                             //引號裡面的東西是個許可權名字可以隨便寫
                /* = authc                       //authc代表的是有沒有登入,沒有登入就不讓訪問,就會跳登入頁面
            </value>
        </property>
    </bean>
    
    <!-- 註冊安全管理器物件 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="bosRealm"/>
    </bean>
    
    <!-- 註冊realm -->
    <bean id="bosRealm" class="com.itheima.bos.realm.BOSRealm"></bean>

後臺程式碼,我這是用的struts的方式所有沒有那些springmvc的註解,如果你們用的springmvc的話自己稍微加修改就行了,主要是看邏輯

     /**
     * 使用者登入,使用shiro框架提供的方式進行認證操作
     */
    public String login(){
        //從Session中獲取生成的驗證碼
        String validatecode = (String) ServletActionContext.getRequest().getSession().getAttribute("key");
        //校驗驗證碼是否輸入正確
        if(StringUtils.isNotBlank(checkcode) && checkcode.equals(validatecode)){
            //使用shiro框架提供的方式進行認證操作
            Subject subject = SecurityUtils.getSubject();//獲得當前使用者物件,狀態為“未認證”
            AuthenticationToken token = new UsernamePasswordToken(model.getUsername(),MD5Utils.md5(model.getPassword()));//建立使用者名稱密碼令牌物件,這個方法裡的倆引數就是前臺傳的使用者名稱密碼,用springmvc的,用你們的方式獲取使用者名稱密碼就行.
            try{
                subject.login(token);       //這就是讓shiro進行驗證是否登入成功,它沒有返回值,所以用trycatch,拋異常就登入失敗,沒拋異常                                                          //就登入成功,這句話會跳轉到自己寫的realm類當中驗證是否登入成功
            }catch(Exception e){
                e.printStackTrace();
                return LOGIN;                 //沒登陸成功跳轉到登入頁面
            }
            User user = (User) subject.getPrincipal();            //登入成功後取出user物件存入session當中.
            ServletActionContext.getRequest().getSession().setAttribute("loginUser", user);
            return HOME;                                             //跳轉到主頁面
        }else{
            //輸入的驗證碼錯誤,設定提示資訊,跳轉到登入頁面
            this.addActionError("輸入的驗證碼錯誤!");
            return LOGIN;
        }
    }

 realm類, 就是從登入方法的這句程式碼跳進來進行驗證是否登入成功subject.login(token);

在這裡面注入dao層介面進行判斷是否與登入頁面輸入的賬號密碼一致

package com.itheima.bos.realm;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import com.itheima.bos.dao.IUserDao;
import com.itheima.bos.domain.User;

public class BOSRealm extends AuthorizingRealm{
    @Autowired
    private IUserDao userDao;
    
    //認證方法
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("自定義的realm中認證方法執行了。。。。");
        UsernamePasswordToken passwordToken = (UsernamePasswordToken)token;//轉成一個shiro提供的使用者類
        //獲得頁面輸入的使用者名稱
        String username = passwordToken.getUsername();
        //根據使用者名稱查詢資料庫中的密碼
        User user = userDao.findUserByUsername(username);   //從資料庫進行查詢使用者是否存在
        if(user == null){
            //頁面輸入的使用者名稱不存在
            return null;
        }
        //簡單認證資訊物件
        AuthenticationInfo info = new SimpleAuthenticationInfo(user, user.getPassword(), this.getName());
        //框架負責比對資料庫中的密碼和頁面輸入的密碼是否一致,由shiro進行判斷密碼是否一致
        return info;
    }

    //授權方法   這個方法呼叫的時機是在spring配置檔案中,有的頁面給它加了相應的許可權,當你訪問這個頁面的時候它就會呼叫這個方//法來驗證你當前使用者是否有相應的許可權
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

         SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();  
        //為使用者授權  我這寫的是硬編碼,可以改成從資料庫查詢當前使用者有啥許可權,然後新增進來
        info.addStringPermission("staff-list");
        return info ;
    }
}