原文: http://zhangxiao.org/2016/jfinal-shiro-integration2/
續上一篇 《JFianl整合Shiro(一)》
我準備在這裏,具體的描述下JFianl整合Shiro的基本流程。
我如今使用是java
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-web</artifactId> <version>1.2.4</version> </dependency>
<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> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> <dispatcher>INCLUDE</dispatcher> <dispatcher>ERROR</dispatcher> </filter-mapping>
如下是我經常使用的shiro.iniweb
[main] #sessionId相關設定 sessionIdCookie=org.apache.shiro.web.servlet.SimpleCookie sessionIdCookie.name=jshop-admin-web sessionIdCookie.path=/ sessionIdCookie.maxAge=1800 sessionIdCookie.httpOnly=true #sessionManager sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager sessionManager.sessionIdCookie = $sessionIdCookie sessionManager.sessionIdCookieEnabled = true sessionManager.globalSessionTimeout = 3600000 #Realm dbRealm = com.yourdomain.module.shiro.Realm #Cache cacheManager = org.apache.shiro.cache.MemoryConstrainedCacheManager #--------------- securityManager.sessionManager=$sessionManager securityManager.realm = $dbRealm securityManager.cacheManager = $cacheManager #[filters] 這個已經被取消,併入main中 #自定義驗證過濾器 app_auth= com.yourdomain.module.shiro.AuthorizeFilter #登陸頁面 app_auth.loginUrl = /auth/login #未受權頁面 app_auth.unauthorizedUrl=/auth/unauthorized [urls] /test/** = anon /public/** = anon /uploads/** = anon /passport/* = anon /** = app_auth
這倆個彷佛沒啥好說的。ajax
它定義了一個新的緩存管理實例. 緩存在Shiro的構架體系中是一個很是重要的部分 - 它減小了和數據存貯之間持續往返的通信。這個例子是使用了在單個JVM上比較好使的MemoryConstrainedCacheManager。若是對你的應用是部署在多個服務器(好比服務器集羣)的話,你將會想使用一個集羣緩存管理器的實現來替代。數據庫
它是很關鍵的一個地方,這是是須要本身實現的。它做爲shiro的一個組件,可讓shiro訪問到你的系統中的用戶、角色、權限等數據。express
這是很是重要的一個節點,來配置哪些路徑映射哪些過濾器來進行鑑權,能夠用逗號分開,配置多個過濾器。apache
這裏的anon是shiro內置的一個過濾器,表示不須要進行鑑權。固然仍是不少的shiro內置鑑權過濾器.在後面簡單介紹下緩存
1.2之後,filters被併入[main]節點,若是繼續保留也沒事兒,只是會出個警告而已。app_auth是我本身實現的一個filter系統中主要使用這個filter進行鑑權。安全
org.apache.shiro.web.filter.authc.AnonymousFilter服務器
org.apache.shiro.web.filter.authc.FormAuthenticationFiltersession
org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
org.apache.shiro.web.filter.authc.LogoutFilter
org.apache.shiro.web.filter.session.NoSessionCreationFilter
org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
org.apache.shiro.web.filter.authz.PortFilter
org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter
org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
org.apache.shiro.web.filter.authz.SslFilter
org.apache.shiro.web.filter.authc.UserFilter
com.yourdomain.module.shiro.Realm
public class Realm extends AuthorizingRealm
主要是在登陸的時候,進行用戶身份驗證
/** * 獲取用戶驗證信息 * @param authcToken 所需驗證的token * @return null or 身份信息 * @throws AuthenticationException 驗證異常 */ protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException { UsernamePasswordToken token = (UsernamePasswordToken) authcToken; SysAdmin admin = AdminService.getByUsername(token.getUsername()); if (admin != null) { if(!admin.getPassword().equals(String.valueOf(token.getPassword()))){ throw new AuthenticationException("密碼錯誤"); } Db.update("update sys_admin set loginTime=?,loginCount=loginCount+1 where id=?",new Date(),admin.getId()); return new SimpleAuthenticationInfo(admin, admin.getPassword(),admin.getUsername()); } else { throw new AuthenticationException("用戶不存在"); } }
在第一次鑑權的時候進行調用,獲取並保存到chache中(沒有配置cache是否是每次都得調用?)
/** * 獲取用戶受權信息 * @param principals 用戶身份 * @return null or 受權信息 */ protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { SysAdmin userInPrincipal = (SysAdmin) principals.getPrimaryPrincipal(); //根據用戶獲取權限 List<String> stringPermissions = AdminService.getPermissions(userInPrincipal.getId()); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); //stringPermissions結構: //user //user:list //user:add //user:edit //... info.addStringPermissions(stringPermissions); return info; }
我這裏返回的:字符串權限表達式(字符串通配符權限),對於各自所對應的資源(主要就是url路徑),我是保存在數據庫中,方便進行配置,而後再加上緩存。在自定義filter中將url轉換成對應的表達式,而後進行鑑權。
public void login() { if(Boolean.FALSE.equals(validateCaptcha("captcha"))){ renderJson(CommonService.ajaxError("驗證碼錯誤")); return; } String username = getPara("username"); String password = HashKit.md5(getPara("password")); Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(username, password); try { subject.login(token); renderJson(CommonService.ajaxSuccess()); } catch (AuthenticationException e) { //雖然在realm中有具體的錯誤信息,可是安全起見,統一返回登陸失敗 renderJson(CommonService.ajaxError("登錄失敗")); } }
public void logout() { Subject subject = SecurityUtils.getSubject(); subject.logout(); redirect("/passport/login"); }
是否是感受很easy:)
com.yourdomain.module.shiro.AuthorizeFilter
public class AuthorizeFilter extends AuthorizationFilter
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception { //-----------------用戶驗證------------------ Subject currentUser = getSubject(request, response); if (!currentUser.isAuthenticated()) return false; //-----------------獲取資源權限表達式------------- SysAdmin user = (SysAdmin) currentUser.getPrincipal(); //request中加入attribute便於controller調用admin的信息 request.setAttribute("admin",user); // 根據actionKey分析出權限表達式 HttpServletRequest hsr = ((HttpServletRequest) request); String root = hsr.getContextPath(); String URI = hsr.getRequestURI(); String actionKey = URI.replace(root,""); if("".equals(actionKey)) actionKey="/"; RoleService roleService = new RoleService(); String expression = roleService.getActionKeyExpression(actionKey); //-----------------進行鑑權------------- if (user==null) return false; else if(user.getStr("username").equals("superadmin")){ //超級管理員具備全部權限 return true; }else if(expression==null){ return false; }else if(currentUser.isPermitted(expression)){ //鑑權 return true; }else{ return false; } }
你能夠按照你本身的方式來構建一套,我相信對於大多數人應該不成問題,由於這個已經不屬於shiro的範疇了。本身搞幾個表,搞幾個配置界面,作下緩存策略等等。
有時候你的應用也許須要在界面上進行鑑權,好比按鈕啥的,這時候就可能須要擴展模板引擎的函數或者標籤。
能夠參考下 《beetl 和 shrio 結合》 http://my.oschina.net/xiandaf...
只要解決如何擴展模板引擎的函數或者標籤,其餘,我想應該都是雷同的吧。