權限控制
常見的權限控制
1\URL 攔截權限控制
通過攔截器或者過濾器攔截客戶端發送的請求,在攔截器或者過濾器中判斷當前用戶是否具有訪問權限有就放行,沒有權限 跳轉到權限不足的提示頁面
2\方法註解權限控制
基於代理技術實現 有代理對象進行權限校驗
權限數據模型
1\權限表
2\角色表
就是權限的集合
3\用戶表
4\角色權限關係表
5\用戶角色關係表
shrio
核心功能
1\認證
2\授權
3\會話管理
4\加密
Authentication:身份認證 / 登錄,驗證用戶是不是擁有相應的身份;
Authorization:授權,即權限驗證,驗證某個已認證的用戶是否擁有某個權限;即判斷用戶是否能做事情,常見的如:驗證某個用戶是否擁有某個角色。或者細粒度的驗證某個用戶對某個資源是否具有某個權限;
maven 引用:
<!-- shiro依賴包 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-cas</artifactId> <version>1.2.3</version> <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-web</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-quartz</artifactId> <version>1.2.3</version> </dependency> <!-- shiro end -->
Application Code
應用程序代碼 開發人員開發
Subject
框架提供的接口 代表當前用戶對象
SecurityManager
框架提供的接口 代表安全管理器對象 ***********
Realm
開發人員可以編寫,框架也提供一些 類似DAO 用於訪問權限數據
使用
1\在項目中引入maven 依賴
2\在web.xml 配置一個過濾器
<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>
3\在spring 配置文件中配置beanid和上面的過濾器的名稱一樣
<!-- 配置shiro 框架的過濾器工廠對象 -->
<bean name="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean" > <!-- 注入安全管理器對象 --> <property name="securityManager" ref="securityManager"></property> <!-- 注入登錄頁面 --> <property name="loginUrl" value="/index.jsp"></property> <!-- 注入登錄成功頁面 --> <!-- <property name="successUrl" value="/index.jsp"></property> --> <!-- 注入無權限頁面 --> <property name="unauthorizedUrl" value="/error.jsp"></property> <!-- 注入URL攔截規則 --> <property name="filterChainDefinitions"> <value> /css/** = anon<!--css 放行 --> /js/** = authc<!-- js放行 --> /images/** = anon<!-- 圖片放行 --> /validatecode.jsp* = anon<!-- 驗證碼放行 --> /index.jsp = anon<!-- 主頁放行 --> /toLogin.do = anon<!-- 去登錄頁面請求 --> /user/login.do = anon<!-- 登錄請求 --> /user/** = perms["user-list"]<!-- staff的一切請求 --> /page.do = perms["page-list"]<!-- staff的一切請求 --> /* = authc <!-- 其他的一切請求 --> </value> </property> </bean> <!-- 註冊安全管理器對象 --> <bean name="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <!-- 注入realm --> <property name="realm" ref="bosRealm"></property> </bean> <!-- 註冊realm --> <bean name="bosRealm" class="com.stevezong.bos.realm.BosRealm"></bean>
過濾器名稱過濾器類描述
anonorg.apache.shiro.web.filter.authc.AnonymousFilter匿名過濾器
authcorg.apache.shiro.web.filter.authc.FormAuthenticationFilter當前用戶是否已經登錄
authcBasicorg.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter基本http驗證過濾,如果不通過,跳轉屋登錄頁面
logoutorg.apache.shiro.web.filter.authc.LogoutFilter登錄退出過濾器
noSessionCreationorg.apache.shiro.web.filter.session.NoSessionCreationFilter沒有session創建過濾器
permsorg.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter權限過濾器
portorg.apache.shiro.web.filter.authz.PortFilter端口過濾器,可以設置是否是指定端口如果不是跳轉到登錄頁面
restorg.apache.shiro.web.filter.authz.HttpMethodPermissionFilterhttp方法過濾器,可以指定如post不能進行訪問等
rolesorg.apache.shiro.web.filter.authz.RolesAuthorizationFilter角色過濾器,判斷當前用戶是否指定角色
sslorg.apache.shiro.web.filter.authz.SslFilter請求需要通過ssl,如果不是跳轉回登錄頁
userorg.apache.shiro.web.filter.authc.UserFilter如果訪問一個已知用戶,比如記住我功能,走這個過濾器
4\登錄Controller
//使用shiro 框架提供的方式進行認證操作 Subject subject = SecurityUtils.getSubject();//獲取當前用戶對象,狀態爲:未認證 AuthenticationToken token = new UsernamePasswordToken(username, MD5Utils.md5(password)); try { subject.login(token); } catch (Exception e) { e.printStackTrace(); result = "login"; } user = (User) subject.getPrincipal(); session.setAttribute("user", user); session.setMaxInactiveInterval(60*60*24); result = "redirect:../pages_common_index.do";
5\寫Realm
Exception 類型:
沒有這個用戶名
UnknownAccountException
密碼錯誤
IncorrectCredentialsException
package com.stevezong.bos.realm; import javax.annotation.Resource; 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 com.stevezong.bos.dao.UserMapper; import com.stevezong.bos.entity.User; public class BosRealm extends AuthorizingRealm{ @Resource UserMapper userMapper; //認證方法 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("自定義Realm"); //根據用戶名查詢數據庫中的密碼 //將AuthenticationToken 強轉爲 UsernamePasswordToken 方便使用 UsernamePasswordToken passwordToken = (UsernamePasswordToken) token; //根據用戶名查詢數據中的User對象 User user = userMapper.findByUsername(passwordToken.getUsername()); if(user == null) { //頁面輸入的用戶名不存在 return null; }else { //簡單認證信息對象(user對象,數據庫中的密碼,任意字符串) AuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(),this.getName()); //框架負責對比數據庫中的密碼和頁面輸入的密碼是否一致 return info; } } //授權方法 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) { // TODO 後期需要修改爲根據當前登錄永固查詢數據庫獲取實際對應的權限 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); info.addStringPermission("staff-list"); return info; } }
shiro 註解
1\
<!-- 開啓shiro的註解支持 --> <bean id="defaultAdvisorAutoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"> <!-- 必須改爲true,即使用cglib方式爲Action創建代理對象。默認值爲false,使用JDK創建代理對象,會造成問題 --> <property name="proxyTargetClass" value="true"></property> </bean> <!-- 使用shiro框架提供的切面類,用於創建代理對象 --> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"></bean>
2\在對應的方法上加上註解
@RequiresPermissions("權限名稱")
package com.stevezong.bos.controller; import javax.annotation.Resource; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.stevezong.bos.service.StaffService; import com.stevezong.bos.utils.BosResult; @Controller @RequestMapping("/staff") public class StaffDelController { @Resource(name = "staffService") StaffService staffService; @RequestMapping("/del.do") @ResponseBody @RequiresPermissions("staff-delete") public BosResult<Object> del(String ids){ BosResult<Object> result = new BosResult<Object>(); String[] idsArr = ids.split(","); int[] resultArr = new int[idsArr.length]; for(int i = 0; i<idsArr.length;i++) { resultArr[i] = staffService.updateDeltagById(idsArr[i]); } result.setStatus(0); result.setMsg("修改完成"); result.setData(resultArr); return result; } }
3\在ssm 框架中捕獲shiro 的權限不足異常
shiro jsp 標籤庫
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %> 用戶是否有這個權限 <shiro:hasPermission name="權限名">js,jsp,html 都可以</shiro:hasPermission> <shiro:hasPermission name="staff-list"> { id : 'button-delete', text : '作廢', iconCls : 'icon-cancel', handler : doDelete }, </shiro:hasPermission>
權限數據管理
曾刪改查
初始化權限數據
添加權限數據
權限分頁查詢