二:SecurityManager和Subject
SecurityManager是shiro的核心,它是一個facade,全部的交互最終都經過SecurityManager執行。Subject表明當前應用的參與者,能夠是一個用戶,也能夠是第三方服務等其餘抽象參與者。通常的shiro操做都是操做Subject就行。下面是一些經常使用方法。 html
Subject currentUser = SecurityUtils.getSubject();//獲取當前用戶 currentUser.getSession(); //獲取會話 currentUser.checkPermission("printer:print");//檢查是否有對應權限 currentUser.checkRole("管理員");//檢查是否有對應角色 currentUser.logout(); //執行登出操做,移除對應的session以及權限數據。
三:Wildcard Permissions
shiro默認使用一種相似"printer:print:lp7200"的語法來標識權限。這三部分分別爲域、動做、實例。通常使用域+動做就能夠了,如刪除用戶,能夠用"user:delete"。
通配符"*"和","能夠用在任何一個部分。如"printer:*:lp7200,jet40",表示能夠在打印機lp7200、jet40上執行全部操做。 java
四:自定義Realm
Realm是一個用於訪問諸如用戶、角色、權限這類安全數據的組件。實際應用中這些數據通常保存在數據庫裏,所以須要自定義realm實現安全數據的訪問。雖然shiro自身提供了JdbcRealm,可是這須要數據庫表設計和shiro默認的一致,開發者可根據實際狀況選擇。 web
package com.my.shiro.dao; import java.util.HashSet; import java.util.List; import java.util.Set; import org.apache.shiro.authc.AccountException; 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.AuthorizationException; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import com.my.shiro.model.Permission; import com.my.shiro.model.User; public class MyJdbcRealm extends AuthorizingRealm { @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { if (principals == null) { throw new AuthorizationException("PrincipalCollection method argument cannot be null."); } String username = (String) getAvailablePrincipal(principals); User user = User.dao.getByUserName(username); int roleid = user.getInt("role_id"); List<Permission> perms = Permission.dao.getPermissions(roleid); Set<String> roleSet = new HashSet<String>(); roleSet.add(String.valueOf(roleid)); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roleSet); info.setStringPermissions(getPermissionSet(perms)); return info; } @Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException { UsernamePasswordToken upToken = (UsernamePasswordToken) token; String username = upToken.getUsername(); if (username == null) { throw new AccountException("Null usernames are not allowed by this realm."); } String password = User.dao.getPwdByUserName(username); if(password==null) throw new AccountException("account error..."); AuthenticationInfo info = new SimpleAuthenticationInfo(username, password, getName()); return info; } private Set<String> getPermissionSet(List<Permission> perms){ Set<String> set = new HashSet<String>(); for(Permission p:perms){ set.add(p.getStr("pkey")); } return set; } }
doGetAuthenticationInfo(AuthenticationToken token)是根據用戶名從數據庫獲取用戶名、密碼組成一個AuthenticationInfo,此時還未進行驗證,該對象用於以後和用戶提交的密碼(未加密、加密)進行匹配。
doGetAuthorizationInfo(PrincipalCollection principals)此時已經驗證成功,此方法根據用戶名獲取對應的角色和權限。 數據庫
五:web.xml配置 apache
<listener> <listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class> </listener>
<filter> <filter-name>ShiroFilter</filter-name> <filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class> </filter> <filter-mapping> <filter-name>ShiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>這個是shiro1.2後的filter配置。此filter建議放在其餘filter以前,使shiro能正常工做。
六:shiro.ini配置
包含main,users,roles,urls四個section。當使用數據庫存儲時,users,roles在這裏用不到。main用於配置SecurityManager及其依賴,如Realm。urls是web應用特有的,用於根據url設置訪問權限。 api
[main] myRealm=com.my.shiro.dao.MyJdbcRealm securityManager.realms=$myRealm user.loginUrl=/ perms.unauthorizedUrl=/common/unauthor.jsp [urls] /common/**=anon /security/**=user /admin/**=user,perms["admin:*"]user.loginUrl定義未驗證時的跳轉路徑,perms.unauthorizedUrl定義無權限時的跳轉路徑。
七:登陸 安全
public void doLogin(){ String username = getPara("username"); String password = getPara("password"); UsernamePasswordToken token = new UsernamePasswordToken(username, password); Subject user = SecurityUtils.getSubject(); try{ user.login(token); }catch (AuthenticationException e) { redirect(getRequest().getContextPath()+"/"); return; } //登陸成功 redirect(getRequest().getContextPath()+"/page/index"); }八:方法級的權限控制
@RequiresAuthentication @RequiresGuest @RequiresPermissions("account:create") @RequiresUser
默認的都是Logical.ALL,就是必須所有知足。當只需一個時可使用Logical.OR。
這些權限註釋能夠做用在類或者方法上,來控制類中個別或者所有方法的權限訪問。 session
九:JSP Taglib 權限控制 app
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<shiro:authenticated> <a href="updateAccount.jsp">Update your contact information</a>. </shiro:authenticated>