1. 程式人生 > >shiro許可權框架詳解06-shiro與web專案整合(下)

shiro許可權框架詳解06-shiro與web專案整合(下)

shiro和web專案整合,實現類似真實專案的應用

  • web專案中認證
  • web專案中授權
  • shiro快取
  • sessionManager使用
  • 驗證碼功能實現
  • 記住我功能實現

web專案中認證

實現方式

修改CustomRealmdoGetAuthenticationInfo 方法,從資料庫中獲取使用者資訊,CustomRealm 返回查詢到的使用者資訊,包括(加密後的密碼字串和salt以及上文中的選單)。

修改 doGetAuthenticationInfo 方法

@Autowired
private SysService sysService;

/**
 * 用於認證
*/
@Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { //第一步:通過token獲取身份資訊 String userCode = (String) token.getPrincipal(); //從資料庫中查詢賬號資訊是否存在 SysUser sysUser = null; try { sysUser = sysService.findSysUserByUserCode(userCode); } catch
(Exception e1) { e1.printStackTrace(); } //如果查詢不到返回null if(sysUser==null){ return null; } //第二步:通過獲取的身份資訊進行資料庫查詢 String password = sysUser.getPassword(); //組裝ActiveUser類 ActiveUser activeUser = new ActiveUser(); activeUser.setUserid(sysUser.getId()); activeUser.setUsercode(sysUser.getUsercode()); activeUser.setUsername(sysUser.getUsername()); //查詢選單資訊
List<SysPermission> menus = null; try { menus = sysService.findMenuListByUserId(sysUser.getUsercode()); } catch (Exception e) { e.printStackTrace(); } activeUser.setMenus(menus); //得到鹽 String salt = sysUser.getSalt(); //如果查詢到結果返回AuthenticationInfo AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(activeUser, password,ByteSource.Util.bytes(salt), ""); return authenticationInfo; }

設定憑證匹配器

在我們的資料庫儲存的是MD5雜湊值,在自定義的realm中需要自定義設定雜湊演算法以及雜湊次數。這裡和前面介紹的雜湊認證的配置方式類似。

<!-- 自定義的realm -->
<bean id="customRealm" class="cn.itcast.ssm.shiro.CustomRealm">
<!--將匹配器設定到realm中 -->
    <property name="credentialsMatcher" ref="credentialsMatcher" />
</bean>
<!--定義憑證匹配器 -->
<bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<!-- 設定hash雜湊演算法 -->
    <property name="hashAlgorithmName" value="md5" />
    <!-- 設定hash雜湊次數 -->
    <property name="hashIterations" value="1" />
</bean>

驗證認證功能

資料庫存在兩條使用者資料,具體如下:
這裡寫圖片描述
其中:張三 的密碼是 111111。當然也可以自己修改密碼:

SELECT MD5('密碼'+'鹽')

如果可能正常登入則沒有問題。

授權

實現方式

修改 CustomRealm 中的 doGetAuthorizationInfo 方法從資料庫中查詢授權資訊。
這裡講解註解式授權和jsp標籤授權方法。

/**
  * 用於授權
  */
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

    //獲取身份資訊,這個欄位是在認證通過後返回的,也就是通過執行認證方法返回的AuthenticationInfo類的第一個屬性
    ActiveUser activeUser = (ActiveUser) principals.getPrimaryPrincipal();

    //通過userId查詢資料庫獲取該身份資訊的所有許可權。
    List<SysPermission> permissionList = null;
    try {
        permissionList = sysService.findPermissionListByUserId(activeUser.getUserid());
       } catch (Exception e) {
        e.printStackTrace();
       }
    List<String> permissions = new ArrayList<>();
    if(permissionList!=null){
        for(SysPermission p:permissionList){
            permissions.add(p.getPercode());
        }
    }

    //查詢到許可權資訊,然後返回許可權資訊
    SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
    //將查詢到的授權資訊填充到SimpleAuthorizationInfo中
    simpleAuthorizationInfo.addStringPermissions(permissions);
    return simpleAuthorizationInfo;
}

controller類的AOP支援

<!--開啟aop,對類代理 -->
<aop:config proxy-target-class="true"></aop:config>
<!-- 開啟shiro註解支援 -->
<bean
     class="
org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
    <property name="securityManager" ref="securityManager" />
</bean>

在ItemsController類方法上添加註解

//商品資訊方法
@RequestMapping("/queryItems")
@RequiresPermissions("item:query")//通過註解的方式進行授權
public ModelAndView queryItems(HttpServletRequest request) throws Exception {

    System.out.println(request.getParameter("id"));

    //呼叫service查詢商品列表
    List<ItemsCustom> itemsList = itemsService.findItemsList(null);

    ModelAndView modelAndView = new ModelAndView();
    modelAndView.addObject("itemsList", itemsList);
    // 指定邏輯檢視名
    modelAndView.setViewName("itemsList");

    return modelAndView;
}

jsp標籤授權

在jsp頁面新增shiro taglib

<%@ taglib uri="http://shiro.apache.org/tags" prefix="shiro" %>

shiro包括的jsp標籤

標籤名稱 標籤條件(均顯示標籤內容)
<shiro:authenticated> 登入之後
<shiro:notAuthenticated> 不在登入狀態時
<shiro:guest> 使用者在沒有RememberMe時
<shiro:user> 使用者在RememberMe時
<shiro:hasAnyRoles name="abc,123" > 在有abc或者123角色時
<shiro:hasRole name="abc"> 擁有角色abc
<shiro:lacksRole name="abc"> 沒有角色abc
<shiro:hasPermission name="abc"> 擁有許可權資源abc
<shiro:lacksPermission name="abc"> 沒有abc許可權資源
<shiro:principal> 顯示使用者身份名稱
<shiro:principal property="username"/> 顯示使用者身份中的屬性值

修改itemsList.jsp檔案

    <!-- 具有item:update許可權才顯示修改連結,沒有的話不顯示。相當於if(hasPermission(item:update)) -->
<shiro:hasPermission name="item:update">
    <a href="${pageContext.request.contextPath }/items/editItems.action?id=${item.id}">修改</a>
</shiro:hasPermission>

授權測試

當呼叫controller的一個方法時,由於該方法加了@RequiresPermissions("item:query") 註解,shiro會呼叫realm獲取資料庫中的許可權資訊,看 item:query 是否在許可權資料中存在,如果不存在就拒絕訪問,如果存在就授權通過

當展現一個jsp頁面時,頁面中如果遇到 <shiro:hasPermission name="item:update"> 標籤,shiro呼叫realm獲取資料庫中的許可權資訊,看 item:update 是否在許可權資料中存在,如果不存在就不顯示標籤包含內容,如果存在則顯示。

在這裡只要遇到註解或shiro jsp標籤授權,就會呼叫realm查詢資料庫,在這裡需要引入快取解決。

shiro快取

針對授權時頻繁查詢資料庫的問題,引入shiro快取。

快取流程

使用者認證通過。
使用者第一次授權:呼叫realm查詢資料庫。
使用者第二次授權:不呼叫realm查詢資料庫,直接從快取中讀取授權資訊。

使用 ehcache

新增Ehcache的jar包
這裡寫圖片描述
配置Ehcache配置檔案:
新建shiro-ehcache.xml

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
    <!--diskStore:快取資料持久化的目錄 地址  -->
    <diskStore path="E:\develop\ehcache" />
    <defaultCache 
        maxElementsInMemory="1000" 
        maxElementsOnDisk="10000000"
        eternal="false" 
        overflowToDisk="false" 
        diskPersistent="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120" 
        diskExpiryThreadIntervalSeconds="120"
        memoryStoreEvictionPolicy="LRU">
    </defaultCache>
</ehcache>

配置cacheManager

<!--securityManager安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    <property name="realm" ref="customRealm" />
    <property name="cacheManager" ref="cacheManager"/>
</bean>
<!-- 定義shiro快取管理器 -->
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
        <property name="cacheManagerConfigFile" value="classpath:shiro-ehcache.xml"/>
</bean>

清空快取

當用戶許可權修改後,使用者再次登入shiro會自動呼叫realm從資料庫獲取許可權資料,如果在修改許可權後想立即清除快取則可以呼叫realm的clearCache方法清除。
CustomRealm 中定義clearCached方法:

    /**
     * 清除快取方法
     */
    public void clearCache(){
        PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();
        super.clearCache(principals);   

    }

驗證碼功能實現

實現方式

shiro使用FormAuthenticationFilter進行表單認證,驗證碼校驗的功能應該加在FormAuthenticationFilter中,在認證之前進行驗證碼校驗。

自定義FormAuthenticationFilter

public class CustomFormAuthenticationFilter extends FormAuthenticationFilter{

    /**
     * 原AuthenticationFilter驗證方法
     */
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {

        //獲取正確的驗證碼和使用者輸入的驗證碼進行比對
        HttpServletRequest httpServletRequest = (HttpServletRequest)request;

        HttpSession session = httpServletRequest.getSession();

        //從session獲取正確驗證碼
        String validateCode = (String) session.getAttribute("validateCode");
        //取出頁面的驗證碼
        String randomcode = (String) httpServletRequest.getParameter("randomcode");
        if(validateCode!=null && randomcode!=null && !validateCode.equals(randomcode)){
            //驗證碼不相同,給shiroLoginFailure屬性設定值
            request.setAttribute("shiroLoginFailure","randomcodeError");
            //拒絕訪問,不再校驗賬號和密碼
            return true;
        }

        return super.onAccessDenied(request, response);
    }

}

配置自定義的FormAuthenticationFilter

在applicationContext-shiro.xml檔案中配置

    <!-- 自定義form認證過濾器 -->
    <bean id="formAuthenticationFilter" class="cn.itcast.ssm.shiro.CustomFormAuthenticationFilter">
        <!--表單中賬號的name屬性的值-->
        <property name="usernameParam" value="account"/>
        <!--表單中賬號的password屬性的值-->
        <property name="passwordParam" value="accountPassword"/>
    </bean>

修改 shiroFilter 配置

    <!-- web.xml中shiro的filter對應的bean -->
    <!-- shiro的web過濾器 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager" />
        <!-- logiUrl認證提交地址,如果沒有認證通過將會請求此地址進行認證,請求此地址將由formAuthenticationFilter進行表單認證 -->
        <property name="loginUrl" value="/login.action" />
        <!-- 認證成功後統一跳轉到first.action,建議不配置,shiro認證成功自動到上一個連結 -->
        <property name="successUrl" value="/first.action" />
        <!-- 通過unauthorizedUrl指定沒有許可權時跳轉頁面 -->
        <property name="unauthorizedUrl" value="/refuse.jsp" />
        <!-- 自定義filter配置 -->
        <property name="filters">
            <map>
                <entry key="authc" value-ref="formAuthenticationFilter"/>
            </map>
        </property>

修改 LoginControllerlogin 方法

    @RequestMapping("/login")
    public String login(HttpServletRequest request)throws Exception{

        //如果登入失敗從request中獲取認證異常資訊,shiroLoginFailure就是shiro異常類的全限定名
        String exceptionClassName = (String) request.getAttribute("shiroLoginFailure");
        if(exceptionClassName!=null){
            if(UnknownAccountException.class.getName().equals(exceptionClassName)){
                throw new CustomException("賬號不存在");
            }else if(IncorrectCredentialsException.class.getName().equals(exceptionClassName)){
                throw new CustomException("使用者名稱或密碼錯誤");
            }else if("randomcodeError".equals(exceptionClassName)){
                throw new CustomException("驗證碼錯誤");
            }else{
                throw new Exception();//最終在異常處理器生成未知錯誤
            }
        }
        //此方法不處理登入成功(認證成功),shiro認證成功會自動跳轉到上一個請求路徑。
        //登入失敗還到login頁面
        return "login";
    }

在登入頁面新增驗證碼

    <TR>
        <TD>使用者名稱:</TD>
        <TD colSpan="2"><input type="text" id="usercode" name="account" style="WIDTH: 130px" />   </TD>
    </TR>
    <TR>
        <TD>密 碼:</TD>
        <TD><input type="password" id="pwd" name="accountPassword" style="WIDTH: 130px" /></TD>
    </TR>
    <TR>
        <TD>驗證碼:</TD>
        <TD><input id="randomcode" name="randomcode" size="8" /> <img id="randomcode_img" src="${baseurl}validatecode.jsp" alt="" width="56" height="20" align='absMiddle' /> <a href=javascript:randomcode_refresh()>重新整理</a></TD>
    </TR> 

實現記住我功能

使用者登入選擇”記住我”選項,本次登入成功會向cookie寫身份資訊,下次登入從cookie中取出身份資訊實現自動登入。

使用者身份資訊相關類實現 java.io.Serializable 介面

向cookie記錄身份資訊的物件需要實現序列號介面,如下:

public class ActiveUser implements java.io.Serializable {
public class SysPermission implements java.io.Serializable{

配置 rememberMeManager

<!--配置記住我cookie-->
<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie">
    <!-- rememerMe是cookie名稱 -->
    <constructor-arg value="rememberMe"/>
    <property name="maxAge" value="2592000"/>
</bean>
<!-- rememberMeManager管理器,寫cookie,取出cookie生成使用者資訊 -->
<bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager">
        <property name="cookie" ref="rememberMeCookie"/>
</bean>

新增到securityManager中

    <!--securityManager安全管理器 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="realm" ref="customRealm" />
        <property name="cacheManager" ref="cacheManager"/>
        <!-- 記住我 -->
        <property name="rememberMeManager" ref="rememberMeManager"/>
    </bean>

修改登入頁面

<TR>
    <TD></TD>
    <TD><input type="checkbox" name="rememberMe">記住我</TD>
</TR> 

修改rememberMe的input名稱

在前面的配置中修改了賬號和密碼的input的name屬性,”記住我”的name屬性值也可以修改

    <!-- 自定義form認證過濾器 -->
    <bean id="formAuthenticationFilter" class="cn.itcast.ssm.shiro.CustomFormAuthenticationFilter">
        <!--表單中賬號的name屬性的值-->
        <property name="usernameParam" value="account"/>
        <!--表單中賬號的password屬性的值-->
        <property name="passwordParam" value="accountPassword"/>
        <!-- 修改記住我的name屬性的值 -->
        <property name="rememberMeParam" value="rememberMe"/>
    </bean>

測試記住我功能

選擇自動登入後,需要檢視cookie是否有rememberMe
這裡寫圖片描述

使用UserFilter

在前一篇部落格中有說明UserFilter的功能如下:

user:例如/admins/user/**=user沒有引數表示必須存在使用者, 身份認證通過或通過記住我認證通過的可以訪問,當登入操作時不做檢查

我們修改applicationContext-shiro.xml配置檔案

    <!-- shiro的web過濾器 -->
    <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
        <property name="securityManager" ref="securityManager" />
        <!-- logiUrl認證提交地址,如果沒有認證通過將會請求此地址進行認證,請求此地址將由formAuthenticationFilter進行表單認證 -->
        <property name="loginUrl" value="/login.action" />
        <!-- 認證成功後統一跳轉到first.action,建議不配置,shiro認證成功自動到上一個連結 -->
        <property name="successUrl" value="/first.action" />
        <!-- 通過unauthorizedUrl指定沒有許可權時跳轉頁面 -->
        <property name="unauthorizedUrl" value="/refuse.jsp" />
        <!-- 自定義filter配置 -->
        <property name="filters">
            <map>
                <entry key="authc" value-ref="formAuthenticationFilter"/>
            </map>
        </property>

        <!-- 過濾器鏈定義,從上向下順序執行,一般將/**放在最後面 -->
        <property name="filterChainDefinitions">
            <value>
                <!--靜態資源可以匿名訪問 -->
                /images/** = anon
                /js/** = anon
                /styles/** = anon
                /validatecode.jsp = anon
                <!-- 請求logout.action地址,shiro去清除session -->
                /logout.action = logout
                <!-- 配置需要授權的url,查詢商品需要有商品查詢許可權 -->
                <!-- /items/queryItems.action = perms[item:query] /items/editItems.action 
                    = perms[item:update] -->

                <!-- 配置記住我或認證通過可以訪問地址 -->
                /index.jsp = user
                /first.action = user
                /welcome.jsp = user
                <!-- /**=authc 表示所有的url都需要認證才能訪問 -->
                /** = authc
            </value>
        </property>
    </bean>

blog專案的下載地址

點選進入下載頁面

相關推薦

shiro許可權框架06-shiroweb專案整合()

shiro和web專案整合,實現類似真實專案的應用 web專案中認證 web專案中授權 shiro快取 sessionManager使用 驗證碼功能實現 記住我功能實現 web專案中認證 實現方式 修改CustomRealm 的 doGe

shiro許可權框架06-shiroweb專案整合(上)

shiro和web專案整合,實現類似真實專案的應用 本文中使用的專案架構是springMVC+mybatis,所以我們是基於搭建好的專案進行改造的。 將shiro整合到web應用中 登入 退出 認證資訊在頁面展現,也就是顯示選單 shiro的過濾器

(轉)shiro權限框架06-shiroweb項目整合()

tex web項目 ssd ndis form認證 lec rfi 出身 javadoc http://blog.csdn.net/facekbook/article/details/54962975 shiro和web項目整合,實現類似真實項目的應用 web項目中

(轉) shiro權限框架04-shiro認證

software protected .get 打開 net 文件的 apach stc cdc http://blog.csdn.net/facekbook/article/details/54906635 shiro認證 本文介紹shiro的認證功能 認證流程

(轉)shiro權限框架05-shiro授權

roles ktr ase sub turn stp exc protected user http://blog.csdn.net/facekbook/article/details/54910606 本文介紹 授權流程 授權方式 授權測試 自定義授權rea

SpringWeb專案整合的原理

引言:   在剛開始我們接觸IOC時,我們載入並啟用SpringIOC是通過如下程式碼手動載入 applicationContext.xml 檔案,new出context物件,完成Bean的建立和屬性的注入。 public class TestIOC { @Test public

Axis2Web專案整合及Axis2在Web專案整合Spring

Axis2簡介:          Axis2是一套嶄新的WebService引擎,該版本是對Axis1.x重新設計的產物。Axis2不僅支援SOAP1.1和SOAP1.2,還集成了非常流行的REST WebService,同時還支援spring、JSON等技術。

shiro許可權框架-(二)Springboot整合

首先引入shiro與Spring的依賴。 Shiro和Spring整合的依賴 <dependency> <groupId>org.apache.shiro<

2.SecurityManager(shiro許可權管理門面)

SecurityManager 介面主要作用 為什麼要先說SecurityManager呢?因為我覺得他是shiro的主要入口,幾乎所有相關的許可權操作,都由他代理了。 1.可以說是所有配置的入口,簡化配置,方便使用。 2.一個介面就可以實現,驗證的操作(

Freemarker 的 Shiro 標籤使用

一、引入依賴(已解決版本衝突) <!-- shiro-freemarker-tags start --> <dependency> <groupId>net.mingsoft</groupId> <artifactId>

MySQL使用者賬戶管理許可權管理

MySQL 的許可權表在資料庫啟動的時候就載入記憶體,當用戶通過身份認證後,就在記憶體中進行相應許可權的存取,這樣,此使用者就可以在資料庫中做許可權範圍內的各種操作了。 mysql 的許可權體系大致分為5個層級: 全域性層級 全域性許可權適用於一個給定伺服器中的所有資料庫。這些許可權儲存在mysql

shiro的配置

1.下載shiro http://shiro.apache.org/download.html 2.shiro架構的核心內容介紹 ①Subject:應用程式碼直接互動的物件是 Subject,與 Subject 的所有互動都會委託給 SecurityManager;

Shiro許可權框架之一 --------簡介

一. Shiro是什麼 Shiro是一個Java平臺的開源許可權框架,用於認證和訪問授權。具體來說,滿足對如下元素的支援: 使用者,角色,許可權(僅僅是操作許可權,資料許可權必須與業務需求緊密結合),資源(url)。 使用者分配角色,角色定義許可權。 訪問授權時支援角色或者許可

在前後端分離的SpringBoot專案整合Shiro許可權框架

出自 目錄 專案背景 解決方案 參考文章 專案背景        公司在幾年前就採用了前後端分離的開發模式,前端所有請求都使用ajax。這樣的專案結構在與CAS單點登入等許可權管理框架整合時遇到了很多問題,使得許可權部分的程式碼冗長醜陋,CAS的各種重定向也使得使

基於BOS系統的Shiro許可權框架基本使用

目錄 1.Shiro框架的基本概念 Shiro框架的核心功能有4個,即認證、授權、會話管理、加密,shiro基本使用這一方面我們主要討論認證與授權兩個基本用法。認證,顧名思義,即登陸時期資料庫使用者物件與表單的使

django開發之許可權管理(一)——許可權管理(許可權管理原理以及方案)、不使用許可權框架的原始授權方式

知識清單 1.瞭解基於資源的許可權管理方式 2. 掌握許可權資料模型 3. 掌握基於url的許可權管理(不使用許可權框架的情況下實現許可權管理) 許可權管理原理知識 什麼是許可權管理 只要有使用者參與的系統一般都要有許可權管理,許可權管理實現對使用者訪問系統的控制。按照安全規則或安全策略

Java 標準IO框架NIO框架

    在看這篇文章之前,可以先去看看我部落格中另一篇關於同步與非同步、阻塞與非阻塞的理解Java標準IO(BIO)    BIO全稱Blocking IO又叫做同步阻塞IO,它存在如下特點:面向流同步阻塞package com.xdong.bio.client; impo

shiro許可權框架__由淺入深 2

需求: 1、使用者是否已經登入 2、這個使用者有哪些許可權,說白了 就是可以看到哪些操作按鈕 需要一個統一的許可權資料管理中心、可以對每一次請求進行比對 Realm:Shiro 從 Realm 獲取安全資料(如使用者、角色、許可權),就是說SecurityManager 要驗證

shiro許可權框架__由淺入深 1

1、實現思路:工廠啟動時載入 .ini檔案許可權、使用者、角色資訊到一個集合中 2、通過 工廠獲取 SecurityManager 元件 3、通過 SecurityUtils.getSubject(); 獲取使用者元件 Subject:應用程式碼直接互動的物件是 Subject,也就是說 S

Shiro許可權框架簡介

       最近加入了gxpt專案組,被安排做許可權模組,所以也有幸第一次接觸到了Shiro框架。讓我們來一起領略Shiro的風采吧。 什麼是Apache Shiro?        Apache