Apache Shiro入門總結

一:數據庫表結構
   users:用戶表,包含用戶名、密碼、角色ID。
   roles:角色表,包含角色名。
   permission:權限表,包含權限字符串(user:add),權限描述。
   role_permission:中間表,包含角色和權限的id。

二: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定義無權限時的跳轉路徑。
urls區域中,左邊爲訪問的url路徑,右邊爲過濾器,能夠有多個造成過濾器鏈。shiro提供了一些默認的過濾器。
anon org.apache.shiro.web.filter.authc.AnonymousFilter
authc org.apache.shiro.web.filter.authc.FormAuthenticationFilter
authcBasic org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
logout org.apache.shiro.web.filter.authc.LogoutFilter
noSessionCreation org.apache.shiro.web.filter.session.NoSessionCreationFilter
perms org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
port org.apache.shiro.web.filter.authz.PortFilter
rest org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter
roles org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
ssl org.apache.shiro.web.filter.authz.SslFilter
user org.apache.shiro.web.filter.authc.UserFilter
若是要驗證才能訪問的路徑,能夠用authc或user。authc必須是驗證過的,不能是"remember me",而user能夠是"remember me",只要Subject包含principal就行。


七:登陸 安全

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");
	}
八:方法級的權限控制
使用上面的url配置能夠基於路徑進行粗顆粒度的權限控制,shiro提供了一些註釋,配合其餘AOP框架,能夠實現方法級的權限控制。如:
@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>
相關文章
相關標籤/搜索