一、引入依赖
<dependency> <groupId>org.springframeworkgroupId> <artifactId>spring-testartifactId> <version>4.3.18.RELEASEversion> <scope>testscope> dependency> <dependency> <groupId>org.springframeworkgroupId> <artifactId>spring-webmvcartifactId> <version>4.3.18.RELEASEversion> dependency> <dependency> <groupId>org.springframeworkgroupId> <artifactId>spring-jdbcartifactId> <version>4.3.18.RELEASEversion> dependency> <dependency> <groupId>org.springframeworkgroupId> <artifactId>spring-context-supportartifactId> <version>4.3.18.RELEASEversion> dependency> <dependency> <groupId>org.apache.shirogroupId> <artifactId>shiro-springartifactId> <version>1.4.0version> dependency> <dependency> <groupId>net.sf.ehcachegroupId> <artifactId>ehcache-coreartifactId> <version>2.6.11version> dependency>
二、创建 ehcache 缓存配置文件
文件:ehchache.xml
xml version="1.0" encoding="UTF-8"?> <ehcache updateCheck="false" dynamicConfig="false"> <diskStore path="java.io.tmpdir"/> <cache name="authenticationCache" maxEntriesLocalHeap="2000" eternal="false" timeToIdleSeconds="1800" timeToLiveSeconds="1800" overflowToDisk="false" statistics="true"/> <cache name="authorizationCache" maxEntriesLocalHeap="2000" eternal="false" timeToIdleSeconds="1800" timeToLiveSeconds="1800" overflowToDisk="false" statistics="true"/> <cache name="activeSessionCache" maxEntriesLocalHeap="2000" eternal="false" timeToIdleSeconds="1800" timeToLiveSeconds="1800" overflowToDisk="false" statistics="true"> cache> <cache name="halfHour" maxElementsInMemory="10000" maxElementsOnDisk="100000" eternal="false" timeToIdleSeconds="1800" timeToLiveSeconds="1800" overflowToDisk="false" diskPersistent="false" /> <cache name="hour" maxElementsInMemory="10000" maxElementsOnDisk="100000" eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="3600" overflowToDisk="false" diskPersistent="false" /> <cache name="oneDay" maxElementsInMemory="10000" maxElementsOnDisk="100000" eternal="false" timeToIdleSeconds="86400" timeToLiveSeconds="86400" overflowToDisk="false" diskPersistent="false" /> <defaultCache name="defaultCache" maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="false" maxElementsOnDisk="100000" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU"/> ehcache>
四、Spring 整合 Shiro
1. 创建文件 spring-shiro.xml
xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> beans>
2. 将 shiro 的缓存管理器交给 spring-cache 管理
package com.beovo.dsd.common.shiro.cache; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.apache.shiro.cache.Cache; import org.apache.shiro.cache.CacheException; import org.apache.shiro.cache.CacheManager; import org.apache.shiro.util.Destroyable; import org.springframework.util.ClassUtils; /** * 使用spring-cache作为shiro缓存- 缓存管理器 * @author Jimc. * @since 2018/11/22. */ public class ShiroSpringCacheManager implements CacheManager, Destroyable { private static final Logger logger = LogManager.getLogger(ShiroSpringCacheManager.class); private org.springframework.cache.CacheManager cacheManager; private final boolean hasEhcache; public ShiroSpringCacheManager() { hasEhcache = ClassUtils.isPresent("net.sf.ehcache.Ehcache", this.getClass().getClassLoader()); } public org.springframework.cache.CacheManager getCacheManager() { return cacheManager; } public void setCacheManager(org.springframework.cache.CacheManager cacheManager) { this.cacheManager = cacheManager; } @Override publicCache getCache(String name) throws CacheException { if (logger.isTraceEnabled()) { logger.trace("Acquiring ShiroSpringCache instance named [" + name + "]"); } org.springframework.cache.Cache cache = cacheManager.getCache(name); return new ShiroSpringCache (cache, hasEhcache); } @Override public void destroy() throws Exception { cacheManager = null; } }
package com.beovo.dsd.common.shiro.cache; import cn.hutool.log.Log; import cn.hutool.log.LogFactory; import org.apache.shiro.cache.CacheException; import org.springframework.cache.Cache; import org.springframework.cache.Cache.ValueWrapper; import java.util.*; /** * 使用spring-cache作为shiro缓存 * @author Jimc. * @since 2018/11/22. */ public class ShiroSpringCacheimplements org.apache.shiro.cache.Cache { private static final Log log = LogFactory.get(); private final Cache cache; private final boolean hasEhcache; public ShiroSpringCache(Cache cache, boolean hasEhcache) { if (cache == null) { throw new IllegalArgumentException("Cache argument cannot be null."); } this.cache = cache; this.hasEhcache = hasEhcache; } @Override public V get(K key) throws CacheException { if (log.isTraceEnabled()) { log.trace("Getting object from cache [" + this.cache.getName() + "] for key [" + key + "]key type:" + key.getClass()); } ValueWrapper valueWrapper = cache.get(key); if (valueWrapper == null) { if (log.isTraceEnabled()) { log.trace("Element for [" + key + "] is null."); } return null; } return (V) valueWrapper.get(); } @Override public V put(K key, V value) throws CacheException { if (log.isTraceEnabled()) { log.trace("Putting object in cache [" + this.cache.getName() + "] for key [" + key + "]key type:" + key.getClass()); } V previous = get(key); cache.put(key, value); return previous; } @Override public V remove(K key) throws CacheException { if (log.isTraceEnabled()) { log.trace("Removing object from cache [" + this.cache.getName() + "] for key [" + key + "]key type:" + key.getClass()); } V previous = get(key); cache.evict(key); return previous; } @Override public void clear() throws CacheException { if (log.isTraceEnabled()) { log.trace("Clearing all objects from cache [" + this.cache.getName() + "]"); } cache.clear(); } @Override public int size() { if (hasEhcache) { Object nativeCache = cache.getNativeCache(); if (nativeCache instanceof net.sf.ehcache.Ehcache) { net.sf.ehcache.Ehcache ehcache = (net.sf.ehcache.Ehcache) nativeCache; return ehcache.getSize(); } } return 0; } @Override public Set keys() { if (hasEhcache) { Object nativeCache = cache.getNativeCache(); if (nativeCache instanceof net.sf.ehcache.Ehcache) { net.sf.ehcache.Ehcache ehcache = (net.sf.ehcache.Ehcache) nativeCache; return new HashSet<>(ehcache.getKeys()); } } return Collections.emptySet(); } @Override public Collection values() { if (hasEhcache) { Object nativeCache = cache.getNativeCache(); if (nativeCache instanceof net.sf.ehcache.Ehcache) { net.sf.ehcache.Ehcache ehcache = (net.sf.ehcache.Ehcache) nativeCache; List keys = ehcache.getKeys(); Map
将 缓存管理器交给 Spring 来管理,在 spring-shiro.xml 添加配置如下:
<bean id="shiroSpringCacheManager" class="com.beovo.dsd.common.shiro.cache.ShiroSpringCacheManager"> <property name="cacheManager" ref="cacheManager"/> bean>
3. 自定义 Realm
(1)创建一个存放用户信息的bean
package com.beovo.dsd.common.shiro; import java.io.Serializable; import java.util.List; /** * 自定义Authentication对象,使得Subject除了携带用户的登录名外还可以携带更多信息 * @author Jimc. * @since 2018/11/23. */ public class ShiroUser implements Serializable { private static final long serialVersionUID = -1373760725780840091L; /** * 主键ID */ private Long id; /** * 账号 */ private String account; /** * 姓名 */ private String name; /** * 部门id集 */ private ListdeptIds; /** * 部门名称集 */ private List deptNames; /** * 角色id集 */ private List roleIds; /** * 角色名称集 */ private List roleNames; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getAccount() { return account; } public void setAccount(String account) { this.account = account; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List getDeptIds() { return deptIds; } public void setDeptIds(List deptIds) { this.deptIds = deptIds; } public List getDeptNames() { return deptNames; } public void setDeptNames(List deptNames) { this.deptNames = deptNames; } public List getRoleIds() { return roleIds; } public void setRoleIds(List roleIds) { this.roleIds = roleIds; } public List getRoleNames() { return roleNames; } public void setRoleNames(List roleNames) { this.roleNames = roleNames; } }
(2)首先创建一个继承 AuthorizingRealm 的类
package com.beovo.dsd.common.shiro; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.util.StrUtil; import cn.hutool.log.Log; import cn.hutool.log.LogFactory; import com.beovo.dsd.po.User; import com.beovo.dsd.service.UserAuthService; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.authc.credential.CredentialsMatcher; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.cache.CacheManager; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.springframework.beans.factory.annotation.Autowired; import java.util.HashSet; import java.util.List; import java.util.Set; /** * shiro权限认证 * @author Jimc. * @since 2018/11/22. */ public class ShiroDbRealm extends AuthorizingRealm { private static final Log log = LogFactory.get(); @Autowired private UserAuthService userAuthService; public ShiroDbRealm(CacheManager cacheManager, CredentialsMatcher matcher) { super(cacheManager, matcher); } /** * Shiro登录认证(原理:用户提交 用户名和密码 --- shiro 封装令牌 ---- realm 通过用户名将密码查询返回 ---- shiro 自动去比较查询出密码和用户输入密码是否一致---- 进行登陆控制) */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException { log.info("Shiro开始登录认证"); UsernamePasswordToken token = Convert.convert(UsernamePasswordToken.class, authcToken); User user = userAuthService.getUser(token.getUsername()); ShiroUser shiroUser = userAuthService.getShiroUser(user); // 认证缓存信息 return userAuthService.info(shiroUser, user, getName()); } /** * Shiro权限认证 */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { ShiroUser shiroUser = Convert.convert(ShiroUser.class, principals.getPrimaryPrincipal()); List<Long> roleIds = shiroUser.getRoleIds(); Set<String> permissionSet = new HashSet<>(); Set<String> roleAliasSet = new HashSet<>(); for (Long roleId : roleIds) { List<String> permissions = userAuthService.getPermissionsByRoleId(roleId); if (CollUtil.isNotEmpty(permissions)) { for (String permission : permissions) { if (StrUtil.isNotEmpty(permission)) { permissionSet.add(permission); } } } String roleAlias = userAuthService.getRoleAliasByRoleId(roleId); roleAliasSet.add(roleAlias); } SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); info.addStringPermissions(permissionSet); info.addRoles(roleAliasSet); return info; } }
(3)加入到 spring-shiro.xml 配置中
<bean id="shiroDbRealm" class="com.beovo.dsd.common.shiro.ShiroDbRealm"> <constructor-arg index="0" name="cacheManager" ref="shiroSpringCacheManager"/> <constructor-arg index="1" name="matcher" ref="credentialsMatcher"/> <property name="authenticationCachingEnabled" value="true"/> <property name="authenticationCacheName" value="authenticationCache"/> <property name="authorizationCacheName" value="authorizationCache"/> bean>
3. 添加会话管理器
<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"> <property name="globalSessionTimeout" value="#{30 * 60 * 1000}"/> <property name="sessionIdUrlRewritingEnabled" value="false"/> <property name="sessionDAO" ref="sessionDAO"/> bean> <bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO"> <property name="activeSessionsCacheName" value="activeSessionCache"/> <property name="cacheManager" ref="shiroSpringCacheManager"/> bean>
4. 添加Remember管理器
<bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie"> <constructor-arg value="rememberMe"/> <property name="httpOnly" value="true"/> <property name="maxAge" value="#{7 * 24 * 60 * 60}"/> bean> <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager"> <property name="cipherKey" value="#{T(org.apache.shiro.codec.Base64).decode('amltYwAAAAAAAAAAAAAAAA==')}"/> <property name="cookie" ref="rememberMeCookie"/> bean>
5. 添加密码加密配置
package com.beovo.dsd.common.shiro; /** * shiro密码加密配置 * * @author Jimc. * @since 2018/11/22. */ public class PasswordHash { /** * 加密算法名称 */ private String algorithmName; /** * 密码hash次数 */ private Integer hashIterations; public String getAlgorithmName() { return algorithmName; } public void setAlgorithmName(String algorithmName) { this.algorithmName = algorithmName; } public Integer getHashIterations() { return hashIterations; } public void setHashIterations(Integer hashIterations) { this.hashIterations = hashIterations; } /** * 密码加密 * * @param source 加密源对象 * @param salt 加密盐 * @return 加密后的字符 */ public String encrypt(Object source, Object salt) { return ShiroKit.encrypt(algorithmName, source, salt, hashIterations); } }
<bean id="passwordHash" class="com.beovo.dsd.common.shiro.PasswordHash"> <property name="algorithmName" value="md5"/> <property name="hashIterations" value="2"/> bean>
6. 添加密码错误次数锁定功能
package com.beovo.dsd.common.shiro; import cn.hutool.log.Log; import cn.hutool.log.LogFactory; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.ExcessiveAttemptsException; import org.apache.shiro.authc.credential.HashedCredentialsMatcher; import org.apache.shiro.cache.Cache; import org.apache.shiro.cache.CacheManager; import org.springframework.beans.factory.InitializingBean; import org.springframework.util.Assert; import java.util.concurrent.atomic.AtomicInteger; /** * 输错5次密码锁定半小时,ehcache.xml配置 * @author Jimc. * @since 2018/11/22. */ public class RetryLimitCredentialsMatcher extends HashedCredentialsMatcher implements InitializingBean { private static final Log log = LogFactory.get(); private final static String DEFAULT_CACHE_NAME = "retryLimitCache"; private final CacheManager cacheManager; private String retryLimitCacheName; private CachepasswordRetryCache; private PasswordHash passwordHash; public RetryLimitCredentialsMatcher(CacheManager cacheManager) { this.cacheManager = cacheManager; this.retryLimitCacheName = DEFAULT_CACHE_NAME; } public String getRetryLimitCacheName() { return retryLimitCacheName; } public void setRetryLimitCacheName(String retryLimitCacheName) { this.retryLimitCacheName = retryLimitCacheName; } public void setPasswordHash(PasswordHash passwordHash) { this.passwordHash = passwordHash; } @Override public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) { String username = (String) token.getPrincipal(); //retry count + 1 AtomicInteger retryCount = passwordRetryCache.get(username); if(retryCount == null) { retryCount = new AtomicInteger(0); passwordRetryCache.put(username, retryCount); } if(retryCount.incrementAndGet() > 5) { //if retry count > 5 throw String message = "用户名: " + username + " 密码连续输入错误超过5次,锁定半小时!"; log.warn(message); throw new ExcessiveAttemptsException(message); } else { passwordRetryCache.put(username, retryCount); } boolean matches = super.doCredentialsMatch(token, info); if(matches) { //clear retry data passwordRetryCache.remove(username); } return matches; } @Override public void afterPropertiesSet() throws Exception { Assert.notNull(passwordHash, "you must set passwordHash!"); super.setHashAlgorithmName(passwordHash.getAlgorithmName()); super.setHashIterations(passwordHash.getHashIterations()); this.passwordRetryCache = cacheManager.getCache(retryLimitCacheName); } }
<bean id="credentialsMatcher" class="com.beovo.dsd.common.shiro.RetryLimitCredentialsMatcher"> <constructor-arg ref="shiroSpringCacheManager"/> <property name="retryLimitCacheName" value="halfHour"/> <property name="passwordHash" ref="passwordHash"/> bean>
7. 添加拦截器
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager"/> <property name="loginUrl" value="/login"/> <property name="successUrl" value="/index"/> <property name="unauthorizedUrl" value="/unauth"/> <property name="filterChainDefinitions"> <value> /login = anon /captcha = anon /resources/** = anon /** = user value> property> <property name="filters"> <map> <entry key="user" value-ref="ajaxSessionFilter"/> map> property> bean> <bean id="ajaxSessionFilter" class="com.beovo.dsd.common.shiro.filter.ShiroAjaxSessionFilter"/>
package com.beovo.dsd.common.shiro.filter; import cn.hutool.core.util.StrUtil; import org.apache.shiro.web.filter.authc.UserFilter; import org.apache.shiro.web.util.WebUtils; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * ajax shiro session超时统一处理 * @author Jimc. * @since 2018/11/23. */ public class ShiroAjaxSessionFilter extends UserFilter { @Override protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { HttpServletRequest req = WebUtils.toHttp(request); String xmlHttpRequest = req.getHeader("X-Requested-With"); if (StrUtil.isNotBlank(xmlHttpRequest)) { if (xmlHttpRequest.equalsIgnoreCase("XMLHttpRequest")) { HttpServletResponse res = WebUtils.toHttp(response); // 采用res.sendError(401);在Easyui中会处理掉error,$.ajaxSetup中监听不到 res.setHeader("oauthstatus", "401"); return false; } } return super.onAccessDenied(request, response); } }
8. 将自定义Realm、缓存管理器、会话管理器以及Remember管理器交给shiro的安全管理器
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="shiroDbRealm"/> <property name="cacheManager" ref="shiroSpringCacheManager"/> <property name="rememberMeManager" ref="rememberMeManager"/> <property name="sessionManager" ref="sessionManager"/> bean>
9. 提供一个shiro的工具类
package com.beovo.dsd.common.shiro; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.convert.Convert; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; import org.apache.shiro.SecurityUtils; import org.apache.shiro.crypto.hash.Md5Hash; import org.apache.shiro.crypto.hash.SimpleHash; import org.apache.shiro.session.Session; import org.apache.shiro.subject.Subject; import org.apache.shiro.util.ByteSource; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.apache.shiro.web.session.mgt.DefaultWebSessionManager; import java.util.Collection; /** * shiro工具类 * * @author Jimc. * @since 2018/11/23. */ public class ShiroKit { private static final String NAMES_DELIMITER = ","; /** * 密码盐长度 */ private static final int SALT_LENGTH = 16; /** * shiro密码加密 * * @param algorithmName 算法 * @param source 源对象(密码) * @param salt 密码盐 * @param hashIterations hash次数 * @return 加密后的字符 */ public static String encrypt(String algorithmName, Object source, Object salt, int hashIterations) { ByteSource saltSource = new Md5Hash(salt); return new SimpleHash(algorithmName, source, saltSource, hashIterations).toString(); } /** * 获取随机16位盐值 */ public static String getRandomSalt() { return RandomUtil.randomString(SALT_LENGTH); } /** * 获取当前 Subject * * @return Subject */ public static Subject getSubject() { return SecurityUtils.getSubject(); } /** * 获取封装的 ShiroUser * * @return ShiroUser */ public static ShiroUser getUser() { if (isGuest()) { return null; } else { return Convert.convert(ShiroUser.class, getSubject().getPrincipals().getPrimaryPrincipal()); } } /** * 从shiro获取session */ public static Session getSession() { return getSubject().getSession(); } /** * 获取shiro指定的sessionKey */ @SuppressWarnings("unchecked") public staticT getSessionAttr(String key) { Session session = getSession(); return ObjectUtil.isNotNull(session) ? (T) session.getAttribute(key) : null; } /** * 设置shiro指定的sessionKey */ public static void setSessionAttr(String key, Object value) { Session session = getSession(); session.setAttribute(key, value); } /** * 移除shiro指定的sessionKey */ public static void removeSessionAttr(String key) { Session session = getSession(); if (ObjectUtil.isNotNull(session)) { session.removeAttribute(key); } } /** * 验证当前用户是否属于该角色?,使用时与lacksRole 搭配使用 * * @param roleName 角色名 * @return 属于该角色:true,否则false */ public static boolean hasRole(String roleName) { return ObjectUtil.isNotNull(getSubject()) && StrUtil.isNotEmpty(roleName) && getSubject().hasRole(roleName); } /** * 与hasRole标签逻辑相反,当用户不属于该角色时验证通过。 * * @param roleName 角色名 * @return 不属于该角色:true,否则false */ public static boolean lacksRole(String roleName) { return !hasRole(roleName); } /** * 验证当前用户是否属于以下任意一个角色。 * * @param roleNames 角色列表 * @return 属于:true,否则false */ public static boolean hasAnyRoles(String roleNames) { boolean hasAnyRole = false; Subject subject = getSubject(); if (ObjectUtil.isNotNull(getSubject()) && StrUtil.isNotEmpty(roleNames)) { for (String role : roleNames.split(NAMES_DELIMITER)) { if (subject.hasRole(role.trim())) { hasAnyRole = true; break; } } } return hasAnyRole; } /** * 验证当前用户是否属于以下所有角色。 * * @param roleNames 角色列表 * @return 属于:true,否则false */ public static boolean hasAllRoles(String roleNames) { boolean hasAllRole = true; Subject subject = getSubject(); if (ObjectUtil.isNotNull(getSubject()) && StrUtil.isNotEmpty(roleNames)) { for (String role : roleNames.split(NAMES_DELIMITER)) { if (!subject.hasRole(role.trim())) { hasAllRole = false; break; } } } return hasAllRole; } /** * 验证当前用户是否拥有指定权限,使用时与lacksPermission 搭配使用 * * @param permission 权限名 * @return 拥有权限:true,否则false */ public static boolean hasPermission(String permission) { return ObjectUtil.isNotNull(getSubject()) && StrUtil.isNotEmpty(permission) && getSubject().isPermitted(permission); } /** * 与hasPermission标签逻辑相反,当前用户没有制定权限时,验证通过。 * * @param permission 权限名 * @return 拥有权限:true,否则false */ public static boolean lacksPermission(String permission) { return !hasPermission(permission); } /** * 已认证通过的用户。不包含已记住的用户,这是与user标签的区别所在。与notAuthenticated搭配使用 * * @return 通过身份验证:true,否则false */ public static boolean isAuthenticated() { return ObjectUtil.isNotNull(getSubject()) && getSubject().isAuthenticated(); } /** * 未认证通过用户,与authenticated标签相对应。与guest标签的区别是,该标签包含已记住用户。。 * * @return 没有通过身份验证:true,否则false */ public static boolean notAuthenticated() { return !isAuthenticated(); } /** * 认证通过或已记住的用户。与guset搭配使用。 * * @return 用户:true,否则 false */ public static boolean isUser() { return ObjectUtil.isNotNull(getSubject()) && ObjectUtil.isNotNull(getSubject().getPrincipal()); } /** * 验证当前用户是否为“访客”,即未认证(包含未记住)的用户。用user搭配使用 * * @return 访客:true,否则false */ public static boolean isGuest() { return !isUser(); } /** * 输出当前用户信息,通常为登录帐号信息。 * * @return 当前用户信息 */ public static String principal() { Subject subject = getSubject(); if (ObjectUtil.isNotNull(subject)) { Object principal = subject.getPrincipal(); return principal.toString(); } return ""; } /** * 单用户登录时,判断用户是否已经登录 */ public static boolean isLogin(String username) { Collection sessions = ((DefaultWebSessionManager) (((DefaultWebSecurityManager) SecurityUtils .getSecurityManager()).getSessionManager())).getSessionDAO().getActiveSessions(); if (CollUtil.isNotEmpty(sessions)) { for (Session session : sessions) { String _username = Convert.toStr(session.getAttribute("username")); if (StrUtil.isNotEmpty(_username) && StrUtil.equals(username, _username)) { return true; } } } return false; } /** * 获取当前用户的部门数据范围的集合 */ /*public static List getDeptDataScope() { Long deptId = getUser().getDeptId(); // List */ /** * 判断当前用户是否是超级管理员 */ /*public static boolean isAdmin() { SetsubDeptIds = ConstantFactory.me().getSubDeptId(deptId); // subDeptIds.add(deptId); return subDeptIds; } roles = ShiroKit.getUser().getRoles(); for (Long role : roles) { String singleRoleTip = ConstantFactory.me().getSingleRoleTip(role); if (singleRoleTip.equals(Const.ADMIN_NAME)) { return true; } } return false; } */ }
五、在web.xml添加shiro的过滤器
<filter> <filter-name>shiroFilterfilter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxyfilter-class> <init-param> <param-name>targetFilterLifecycleparam-name> <param-value>trueparam-value> init-param> filter> <filter-mapping> <filter-name>shiroFilterfilter-name> <url-pattern>/*url-pattern> <dispatcher>REQUESTdispatcher> <dispatcher>FORWARDdispatcher> filter-mapping>
源码下载