shiro許可權框架詳解06-shiro與web專案整合(下)
shiro和web專案整合,實現類似真實專案的應用
- web專案中認證
- web專案中授權
- shiro快取
- sessionManager使用
- 驗證碼功能實現
- 記住我功能實現
web專案中認證
實現方式
修改CustomRealm
的 doGetAuthenticationInfo
方法,從資料庫中獲取使用者資訊,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>
修改 LoginController
的 login
方法
@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-shiro與web專案整合(下)
shiro和web專案整合,實現類似真實專案的應用 web專案中認證 web專案中授權 shiro快取 sessionManager使用 驗證碼功能實現 記住我功能實現 web專案中認證 實現方式 修改CustomRealm 的 doGe
shiro許可權框架詳解06-shiro與web專案整合(上)
shiro和web專案整合,實現類似真實專案的應用 本文中使用的專案架構是springMVC+mybatis,所以我們是基於搭建好的專案進行改造的。 將shiro整合到web應用中 登入 退出 認證資訊在頁面展現,也就是顯示選單 shiro的過濾器
(轉)shiro權限框架詳解06-shiro與web項目整合(下)
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
Spring與Web專案整合的原理
引言: 在剛開始我們接觸IOC時,我們載入並啟用SpringIOC是通過如下程式碼手動載入 applicationContext.xml 檔案,new出context物件,完成Bean的建立和屬性的注入。 public class TestIOC { @Test public
Axis2與Web專案整合及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