原文: 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...
只要解决如何扩展模板引擎的函数或者标签,其余,我想应该都是雷同的吧。