package org.calonlan.security.component; import java.util.Iterator; import java.util.Set; import org.springframework.beans.factory.annotation.Value; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; /** * @author Administrator * redismanager主要用來給用戶提供一個設計完備的,經過jedis的jar包來管理redis內存數據庫的各類方法 */ public class RedisManager { // ip和port屬性都定義在了properties文件中,這裏經過spring的註解方式來直接使用 @Value("${redis.ip}") private String host; @Value("${redis.port}") private int port; // 設置爲0的話就是永遠都不會過時 private int expire = 0; // 定義一個管理池,全部的redisManager共同使用。 private static JedisPool jedisPool = null; public RedisManager() { } /** * * 初始化方法,在這個方法中經過host和port來初始化jedispool。 * * */ public void init() { if (null == host || 0 == port) { System.out.println("請初始化redis配置文件"); throw new NullPointerException("找不到redis配置"); } if (jedisPool == null) { jedisPool = new JedisPool(new JedisPoolConfig(), host, port); } } /** * get value from redis * * @param key * @return */ public byte[] get(byte[] key) { byte[] value = null; Jedis jedis = jedisPool.getResource(); try { value = jedis.get(key); } finally { jedisPool.returnResource(jedis); } return value; } /** * get value from redis * * @param key * @return */ public String get(String key) { String value = null; Jedis jedis = jedisPool.getResource(); try { value = jedis.get(key); } finally { jedisPool.returnResource(jedis); } return value; } /** * set * * @param key * @param value * @return */ public byte[] set(byte[] key, byte[] value) { Jedis jedis = jedisPool.getResource(); try { jedis.set(key, value); if (this.expire != 0) { jedis.expire(key, this.expire); } } finally { jedisPool.returnResource(jedis); } return value; } /** * set * * @param key * @param value * @return */ public String set(String key, String value) { Jedis jedis = jedisPool.getResource(); try { jedis.set(key, value); if (this.expire != 0) { jedis.expire(key, this.expire); } } finally { jedisPool.returnResource(jedis); } return value; } /** * set * * @param key * @param value * @param expire * @return */ public byte[] set(byte[] key, byte[] value, int expire) { Jedis jedis = jedisPool.getResource(); try { jedis.set(key, value); if (expire != 0) { jedis.expire(key, expire); } } finally { jedisPool.returnResource(jedis); } return value; } /** * set * * @param key * @param value * @param expire * @return */ public String set(String key, String value, int expire) { Jedis jedis = jedisPool.getResource(); try { jedis.set(key, value); if (expire != 0) { jedis.expire(key, expire); } } finally { jedisPool.returnResource(jedis); } return value; } /** * del * * @param key */ public void del(byte[] key) { Jedis jedis = jedisPool.getResource(); try { jedis.del(key); } finally { jedisPool.returnResource(jedis); } } /** * del * * @param key */ public void del(String key) { Jedis jedis = jedisPool.getResource(); try { jedis.del(key); } finally { jedisPool.returnResource(jedis); } } /** * flush */ public void flushDB() { Jedis jedis = jedisPool.getResource(); try { jedis.flushDB(); } finally { jedisPool.returnResource(jedis); } } /** * size */ public Long dbSize() { Long dbSize = 0L; Jedis jedis = jedisPool.getResource(); try { dbSize = jedis.dbSize(); } finally { jedisPool.returnResource(jedis); } return dbSize; } /** * keys * * @param regex * @return */ public Set<byte[]> keys(String pattern) { Set<byte[]> keys = null; Jedis jedis = jedisPool.getResource(); try { keys = jedis.keys(pattern.getBytes()); } finally { jedisPool.returnResource(jedis); } return keys; } public void dels(String pattern) { Set<byte[]> keys = null; Jedis jedis = jedisPool.getResource(); try { keys = jedis.keys(pattern.getBytes()); Iterator<byte[]> ito = keys.iterator(); while (ito.hasNext()) { jedis.del(ito.next()); } } finally { jedisPool.returnResource(jedis); } } public String getHost() { return host; } public void setHost(String host) { this.host = host; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } public int getExpire() { return expire; } public void setExpire(int expire) { this.expire = expire; } }
這裏的redisManager是經過spring來進行管理的,因此直接使用了@value來讀取properties文件中的屬性。properties文件的內容以下:css
<span style="white-space:pre"> </span>redis.ip=127.0.0.1 <span style="white-space:pre"> </span> redis.port=6379
ip定義爲本機的ip,端口是redis默認的6379端口。java
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations"> <list> <value>classpath:/config/jdbc.properties</value> <value>classpath:/config/redis.properties</value> </list> </property> </bean>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:util="http://www.springframework.org/schema/util" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation=" http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd" default-lazy-init="false"> <!-- 緩存管理器 --> <bean id="cacheManager" class="org.calonlan.security.spring.SpringCacheManagerWrapper"> <property name="cacheManager" ref="springCacheManager" /> </bean> <!-- 憑證匹配器 --> <bean id="credentialsMatcher" class="org.calonlan.security.credentials.RetryLimitHashedCredentialsMatcher"> <constructor-arg ref="cacheManager" /> <property name="hashAlgorithmName" value="md5" /> <property name="hashIterations" value="2" /> <property name="storedCredentialsHexEncoded" value="true" /> </bean> <!-- Realm實現 --> <bean id="userRealm" class="org.calonlan.security.realm.UserRealm"> <property name="credentialsMatcher" ref="credentialsMatcher" /> <property name="cachingEnabled" value="true" /> <!--<property name="authenticationCachingEnabled" value="true"/> --> <!--<property name="authenticationCacheName" value="authenticationCache"/> --> <!--<property name="authorizationCachingEnabled" value="true"/> --> <!--<property name="authorizationCacheName" value="authorizationCache"/> --> </bean> <!-- 會話ID生成器 --> <bean id="sessionIdGenerator" class="org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator" /> <!-- 會話Cookie模板 --> <bean id="sessionIdCookie" class="org.apache.shiro.web.servlet.SimpleCookie"> <constructor-arg value="sid" /> <property name="httpOnly" value="true" /> <property name="maxAge" value="-1" /> </bean> <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie"> <constructor-arg value="rememberMe" /> <property name="httpOnly" value="true" /> <property name="maxAge" value="2592000" /><!-- 30天 --> </bean> <!-- rememberMe管理器 --> <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager"> <!-- rememberMe cookie加密的密鑰 建議每一個項目都不同 默認AES算法 密鑰長度(128 256 512 位) --> <property name="cipherKey" value="#{T(org.apache.shiro.codec.Base64).decode('4AvVhmFLUs0KTA3Kprsdag==')}" /> <property name="cookie" ref="rememberMeCookie" /> </bean> <!-- 會話DAO --> <bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO"> <property name="activeSessionsCacheName" value="shiro-activeSessionCache" /> <property name="sessionIdGenerator" ref="sessionIdGenerator" /> </bean> <!-- 會話驗證調度器 --> <bean id="sessionValidationScheduler" class="org.apache.shiro.session.mgt.quartz.QuartzSessionValidationScheduler"> <property name="sessionValidationInterval" value="1800000" /> <property name="sessionManager" ref="sessionManager" /> </bean> <!-- 會話管理器 --> <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"> <property name="globalSessionTimeout" value="1800000" /> <property name="deleteInvalidSessions" value="true" /> <property name="sessionValidationSchedulerEnabled" value="true" /> <property name="sessionValidationScheduler" ref="sessionValidationScheduler" /> <property name="sessionDAO" ref="<span style="color:#ff0000;">customShiroSessionDAO</span>" /> //這裏指定shiro的sessionManager使用咱們指定的存儲方式來存放session信息 <property name="sessionIdCookieEnabled" value="true" /> <property name="sessionIdCookie" ref="sessionIdCookie" /> </bean> <span style="color:#ff0000;"><bean id="customShiroSessionDAO" class="org.calonlan.security.component.CustomShiroSessionDao"> <property name="shiroSessionRepository" ref="jedisShiroSessionRepository" />//本身定義的sessiondao </bean></span> <span style="color:#ff0000;"> <bean id="jedisShiroSessionRepository" class="org.calonlan.security.component.JedisShiroSessionRepository"> <property name="redisManager" ref="redisManager"></property> </bean></span> <span style="color:#ff0000;"><bean id="redisManager" class="org.calonlan.security.component.RedisManager"></bean>//註冊上面實現的redisManager到spring中</span> <span style="background-color: rgb(255, 0, 0);"><bean id="jedisShiroCacheManager" class="org.calonlan.security.component.JedisShiroCacheManager"> <property name="redisManager" ref="redisManager"></property> </bean></span><span style="background-color: rgb(255, 255, 255);"> </span> <span style="color:#ff0000;"> <bean id="customShiroCacheManager" class="org.calonlan.security.component.CustomShiroCacheManager"> <property name="shrioCacheManager" ref="jedisShiroCacheManager"></property> </bean></span> <!-- 安全管理器 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="userRealm" /> <property name="sessionManager" ref="sessionManager" /> <property name="cacheManager" ref="<span style="color:#ff0000;">customShiroCacheManager</span>" /> <property name="rememberMeManager" ref="rememberMeManager" /> </bean> <!-- 至關於調用SecurityUtils.setSecurityManager(securityManager) --> <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean"> <property name="staticMethod" value="org.apache.shiro.SecurityUtils.setSecurityManager" /> <property name="arguments" ref="securityManager" /> </bean> <!-- 基於Form表單的身份驗證過濾器 --> <bean id="formAuthenticationFilter" class="org.apache.shiro.web.filter.authc.FormAuthenticationFilter"> <property name="usernameParam" value="username" /> <property name="passwordParam" value="password" /> <property name="rememberMeParam" value="rememberMe" /> <property name="loginUrl" value="/login" /> </bean> <bean id="sysUserFilter" class="org.calonlan.security.web.shiro.filter.SysUserFilter" /> <!-- Shiro的Web過濾器 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager" /> <!-- 邏輯上正確,不起做用 --> <property name="loginUrl" value="/login" /> <property name="successUrl" value="/admin/index" /> <property name="filters"> <util:map> <entry key="authc" value-ref="formAuthenticationFilter" /> <entry key="sysUser" value-ref="sysUserFilter" /> </util:map> </property> <property name="filterChainDefinitions"> <value> /img/** =anon /ueditor/jsp/upload/** =anon /login = authc /authenticated = authc /css/** = anon /common/** = anon /js/** = anon /admin/** = user,sysUser //*=anon </value> </property> </bean> <!-- Shiro生命週期處理器 --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" /> </beans>
package org.calonlan.security.component; import java.io.Serializable; import java.util.Collection; import org.apache.shiro.session.Session; import org.apache.shiro.session.UnknownSessionException; import org.apache.shiro.session.mgt.eis.AbstractSessionDAO; public class CustomShiroSessionDao extends AbstractSessionDAO { private ShiroSessionRepository shiroSessionRepository; public ShiroSessionRepository getShiroSessionRepository() { return shiroSessionRepository; } public void setShiroSessionRepository( ShiroSessionRepository shiroSessionRepository) { this.shiroSessionRepository = shiroSessionRepository; } @Override public void delete(Session session) { if (session == null) { System.out.println("錯誤"); return; } Serializable id = session.getId(); if (id != null) getShiroSessionRepository().deleteSession(id); } @Override public Collection<Session> getActiveSessions() { return getShiroSessionRepository().getAllSessions(); } @Override public void update(Session session) throws UnknownSessionException { getShiroSessionRepository().saveSession(session); } @Override protected Serializable doCreate(Session session) { Serializable sessionId = this.generateSessionId(session); this.assignSessionId(session, sessionId); getShiroSessionRepository().saveSession(session); return sessionId; } @Override protected Session doReadSession(Serializable sessionId) { return getShiroSessionRepository().getSession(sessionId); } }
這裏咱們是繼承了shiro的AbstractSessionDAO,而後仿照shiro的模式,給他一個shiroSessionRepository,來進行詳細的session存儲操做。ios
package org.calonlan.security.component; import java.io.Serializable; import java.util.Collection; import org.apache.shiro.session.Session; public interface ShiroSessionRepository { void saveSession(Session session); void deleteSession(Serializable sessionId); Session getSession(Serializable sessionId); Collection<Session> getAllSessions(); }
package org.calonlan.security.component; import java.io.Serializable; import java.util.Collection; import java.util.HashSet; import java.util.Set; import org.apache.shiro.session.Session; public class JedisShiroSessionRepository implements ShiroSessionRepository { /** * * redis session key 前綴 * * */ private final String REDIS_SHIRO_SESSION = "shiro-session"; private RedisManager redisManager; @Override public void saveSession(Session session) { redisManager.init(); if (session == null || session.getId() == null) { System.out.println("session 或者 session ID 爲空"); } byte[] key = SerializeUtils.serialize(getRedisSessionKey(session .getId())); byte[] value = SerializeUtils.serialize(session); Long timeOut = session.getTimeout() / 1000; redisManager.set(key, value, Integer.parseInt(timeOut.toString())); } @Override public void deleteSession(Serializable sessionId) { redisManager.init(); if (sessionId == null) { System.out.println("id爲空"); } redisManager.del(SerializeUtils .serialize(getRedisSessionKey(sessionId))); } @Override public Session getSession(Serializable sessionId) { redisManager.init(); if (null == sessionId) { System.out.println("id爲空"); return null; } Session session = null; byte[] value = redisManager.get(SerializeUtils .serialize(getRedisSessionKey(sessionId))); if (null == value) return null; session = (Session) SerializeUtils.deserialize(value); return session; } @Override public Collection<Session> getAllSessions() { redisManager.init(); Set<Session> sessions = new HashSet<Session>(); Set<byte[]> byteKeys = redisManager .keys(this.REDIS_SHIRO_SESSION + "*"); if (byteKeys != null && byteKeys.size() > 0) { for (byte[] bs : byteKeys) { Session s = (Session) SerializeUtils.deserialize(redisManager .get(bs)); sessions.add(s); } } return sessions; } /** * 獲取redis中的session key * * @param sessionId * @return */ private String getRedisSessionKey(Serializable sessionId) { return this.REDIS_SHIRO_SESSION + sessionId; } public RedisManager getRedisManager() { return redisManager; } public void setRedisManager(RedisManager redisManager) { this.redisManager = redisManager; } public JedisShiroSessionRepository() { } // public static void main(String[] args) { // Jedis jj = new Jedis("localhost"); // //jj.set("key2", "232323231========="); // String ss = jj.get("key1"); // System.out.println(jj.get("key2")); // System.out.println(ss); // } }
package org.calonlan.security.component; import org.apache.shiro.cache.Cache; import org.apache.shiro.cache.CacheException; import org.apache.shiro.cache.CacheManager; import org.apache.shiro.util.Destroyable; public class CustomShiroCacheManager implements CacheManager, Destroyable { private ShiroCacheManager shrioCacheManager; public ShiroCacheManager getShrioCacheManager() { return shrioCacheManager; } public void setShrioCacheManager(ShiroCacheManager shrioCacheManager) { this.shrioCacheManager = shrioCacheManager; } @Override public void destroy() throws Exception { getShrioCacheManager().destroy(); } @Override public <K, V> Cache<K, V> getCache(String name) throws CacheException { return getShrioCacheManager().getCache(name); } }
package org.calonlan.security.component; import org.apache.shiro.cache.Cache; public interface ShiroCacheManager { <K, V> Cache<K, V> getCache(String name); void destroy(); }
package org.calonlan.security.component; import org.apache.shiro.cache.Cache; public class JedisShiroCacheManager implements ShiroCacheManager { private RedisManager redisManager; public RedisManager getRedisManager() { return redisManager; } public void setRedisManager(RedisManager redisManager) { this.redisManager = redisManager; } @Override public <K, V> Cache<K, V> getCache(String name) { return new JedisShiroCache<K, V>(redisManager, name); } @Override public void destroy() { redisManager.init(); redisManager.flushDB(); } }
package org.calonlan.security.component; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class SerializeUtils { public static byte[] serialize(Object o) { ByteArrayOutputStream out = new ByteArrayOutputStream(); try { ObjectOutputStream outo = new ObjectOutputStream(out); outo.writeObject(o); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return out.toByteArray(); } public static Object deserialize(byte[] b) { ObjectInputStream oin; try { oin = new ObjectInputStream(new ByteArrayInputStream(b)); try { return oin.readObject(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); return null; } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); return null; } } }
package org.calonlan.security.component; import java.util.Iterator; import java.util.Set; import org.springframework.beans.factory.annotation.Value; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; /** * @author Administrator * redismanager主要用來給用戶提供一個設計完備的,經過jedis的jar包來管理redis內存數據庫的各類方法 */ public class RedisManager { // ip和port屬性都定義在了properties文件中,這裏經過spring的註解方式來直接使用 @Value("${redis.ip}") private String host; @Value("${redis.port}") private int port; // 設置爲0的話就是永遠都不會過時 private int expire = 0; // 定義一個管理池,全部的redisManager共同使用。 private static JedisPool jedisPool = null; public RedisManager() { } /** * * 初始化方法,在這個方法中經過host和port來初始化jedispool。 * * */ public void init() { if (null == host || 0 == port) { System.out.println("請初始化redis配置文件"); throw new NullPointerException("找不到redis配置"); } if (jedisPool == null) { jedisPool = new JedisPool(new JedisPoolConfig(), host, port); } } /** * get value from redis * * @param key * @return */ public byte[] get(byte[] key) { byte[] value = null; Jedis jedis = jedisPool.getResource(); jedis.auth("你的密碼"); try { value = jedis.get(key); } finally { jedisPool.returnResource(jedis); } return value; } /** * get value from redis * * @param key * @return */ public String get(String key) { String value = null; Jedis jedis = jedisPool.getResource(); jedis.auth("你的密碼"); try { value = jedis.get(key); } finally { jedisPool.returnResource(jedis); } return value; } /** * set * * @param key * @param value * @return */ public byte[] set(byte[] key, byte[] value) { Jedis jedis = jedisPool.getResource(); jedis.auth("你的密碼"); try { jedis.set(key, value); if (this.expire != 0) { jedis.expire(key, this.expire); } } finally { jedisPool.returnResource(jedis); } return value; } /** * set * * @param key * @param value * @return */ public String set(String key, String value) { Jedis jedis = jedisPool.getResource(); jedis.auth("你的密碼"); try { jedis.set(key, value); if (this.expire != 0) { jedis.expire(key, this.expire); } } finally { jedisPool.returnResource(jedis); } return value; } /** * set * * @param key * @param value * @param expire * @return */ public byte[] set(byte[] key, byte[] value, int expire) { Jedis jedis = jedisPool.getResource(); jedis.auth("你的密碼"); try { jedis.set(key, value); if (expire != 0) { jedis.expire(key, expire); } } finally { jedisPool.returnResource(jedis); } return value; } /** * set * * @param key * @param value * @param expire * @return */ public String set(String key, String value, int expire) { Jedis jedis = jedisPool.getResource(); jedis.auth("你的密碼"); try { jedis.set(key, value); if (expire != 0) { jedis.expire(key, expire); } } finally { jedisPool.returnResource(jedis); } return value; } /** * del * * @param key */ public void del(byte[] key) { Jedis jedis = jedisPool.getResource(); jedis.auth("你的密碼"); try { jedis.del(key); } finally { jedisPool.returnResource(jedis); } } /** * del * * @param key */ public void del(String key) { Jedis jedis = jedisPool.getResource(); jedis.auth("你的密碼"); try { jedis.del(key); } finally { jedisPool.returnResource(jedis); } } /** * flush */ public void flushDB() { Jedis jedis = jedisPool.getResource(); jedis.auth("你的密碼"); try { jedis.flushDB(); } finally { jedisPool.returnResource(jedis); } } /** * size */ public Long dbSize() { Long dbSize = 0L; Jedis jedis = jedisPool.getResource(); jedis.auth("你的密碼"); try { dbSize = jedis.dbSize(); } finally { jedisPool.returnResource(jedis); } return dbSize; } /** * keys * * @param regex * @return */ public Set<byte[]> keys(String pattern) { Set<byte[]> keys = null; Jedis jedis = jedisPool.getResource(); jedis.auth("你的密碼"); try { System.out.println("我調用了keys方法=---shiro"); keys = jedis.keys(("*" + pattern).getBytes()); if (null != keys) System.out.println(keys.size()); } finally { jedisPool.returnResource(jedis); } return keys; } public void dels(String pattern) { Set<byte[]> keys = null; Jedis jedis = jedisPool.getResource(); jedis.auth("你的密碼"); try { System.out.println("我調用了dels方法=---shiro"); keys = jedis.keys(("*" + pattern).getBytes());//這裏我作了修改,在redis數據庫中咱們的id前面還加了一堆東西,這樣修改後就能夠所有查看到了 Iterator<byte[]> ito = keys.iterator(); while (ito.hasNext()) { jedis.del(ito.next()); } } finally { jedisPool.returnResource(jedis); } } public String getHost() { return host; } public void setHost(String host) { this.host = host; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } public int getExpire() { return expire; } public void setExpire(int expire) { this.expire = expire; } }
package org.calonlan.security.component; import java.io.Serializable; import java.util.Collection; import java.util.HashSet; import java.util.Set; import org.apache.shiro.session.Session; public class JedisShiroSessionRepository implements ShiroSessionRepository { /** * * redis session key 前綴 * * */ private final String REDIS_SHIRO_SESSION = "shiro-session"; private RedisManager redisManager; @Override public void saveSession(Session session) { redisManager.init(); if (session == null || session.getId() == null) { System.out.println("session 或者 session ID 爲空"); } byte[] key = getRedisSessionKey(session.getId()).getBytes(); byte[] value = SerializeUtils.serialize(session); Long timeOut = session.getTimeout() / 1000; redisManager.set(key, value, Integer.parseInt(timeOut.toString())); } @Override public void deleteSession(Serializable sessionId) { redisManager.init(); if (sessionId == null) { System.out.println("id爲空"); } redisManager.del(getRedisSessionKey(sessionId).getBytes()); } @Override public Session getSession(Serializable sessionId) { redisManager.init(); if (null == sessionId) { System.out.println("id爲空"); return null; } Session session = null; byte[] value = redisManager.get(getRedisSessionKey(sessionId) .getBytes()); if (null == value) return null; session = (Session) SerializeUtils.deserialize(value); return session; } @Override public Collection<Session> getAllSessions() { redisManager.init(); Set<Session> sessions = new HashSet<Session>(); Set<byte[]> byteKeys = redisManager .keys(this.REDIS_SHIRO_SESSION + "*"); if (byteKeys != null && byteKeys.size() > 0) { for (byte[] bs : byteKeys) { Session s = (Session) SerializeUtils.deserialize(redisManager .get(bs)); sessions.add(s); } } return sessions; } /** * 獲取redis中的session key * * @param sessionId * @return */ private String getRedisSessionKey(Serializable sessionId) { return this.REDIS_SHIRO_SESSION + sessionId; } public RedisManager getRedisManager() { return redisManager; } public void setRedisManager(RedisManager redisManager) { this.redisManager = redisManager; } public JedisShiroSessionRepository() { } // public static void main(String[] args) { // Jedis jj = new Jedis("localhost"); // //jj.set("key2", "232323231========="); // String ss = jj.get("key1"); // System.out.println(jj.get("key2")); // System.out.println(ss); // } }
package org.calonlan.security.component; import java.util.Collection; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; import org.apache.shiro.cache.Cache; import org.apache.shiro.cache.CacheException; public class JedisShiroCache<K, V> implements Cache<K, V> { private final String REDIS_SHIRO_CACHE = "shiro-cache"; private RedisManager redisManager; private String name; public JedisShiroCache(RedisManager redisManager, String name) { this.redisManager = redisManager; this.name = name; } public String getName() { if (null == null) { return ""; } return name; } public void setName(String name) { this.name = name; } @Override public void clear() throws CacheException { redisManager.init(); String keysPattern = this.REDIS_SHIRO_CACHE + "*"; redisManager.flushDB(); } @Override public V get(K key) throws CacheException { redisManager.init(); byte[] byteKey = getCacheKey(key).getBytes(); byte[] byteValue = redisManager.get(byteKey); if (null == byteValue) return null; return (V) SerializeUtils.deserialize(byteValue); } @Override public Set<K> keys() { redisManager.init(); Set<byte[]> byteSet = redisManager.keys(this.REDIS_SHIRO_CACHE + "*"); Set<K> keys = new HashSet<K>(); for (byte[] bs : byteSet) { keys.add((K) SerializeUtils.deserialize(bs)); } return keys; } @Override public V put(K key, V value) throws CacheException { redisManager.init(); V previos = get(key); redisManager.set(getCacheKey(key).getBytes(), SerializeUtils.serialize(value)); return previos; } @Override public V remove(K key) throws CacheException { redisManager.init(); V previos = get(key); redisManager.del(getCacheKey(key).getBytes()); return previos; } @Override public int size() { redisManager.init(); if (keys() == null) return 0; return keys().size(); } @Override public Collection<V> values() { Set<byte[]> byteSet = redisManager.keys(this.REDIS_SHIRO_CACHE + "*"); List<V> result = new LinkedList<V>(); for (byte[] bs : byteSet) { result.add((V) SerializeUtils.deserialize(redisManager.get(bs))); } return result; } private String getCacheKey(Object key) { return this.REDIS_SHIRO_CACHE + getName() + ":" + key; } }
package org.calonlan.security.component; import java.util.Iterator; import java.util.Set; import org.springframework.beans.factory.annotation.Value; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; /** * @author Administrator * redismanager主要用來給用戶提供一個設計完備的,經過jedis的jar包來管理redis內存數據庫的各類方法 */ public class RedisManager { // ip和port屬性都定義在了properties文件中,這裏經過spring的註解方式來直接使用 @Value("${redis.ip}") private String host; @Value("${redis.port}") private int port; // 設置爲0的話就是永遠都不會過時 private int expire = 0; // 定義一個管理池,全部的redisManager共同使用。 private static JedisPool jedisPool = null; public RedisManager() { } /** * * 初始化方法,在這個方法中經過host和port來初始化jedispool。 * * */ public void init() { if (null == host || 0 == port) { System.out.println("請初始化redis配置文件"); throw new NullPointerException("找不到redis配置"); } if (jedisPool == null) { jedisPool = new JedisPool(new JedisPoolConfig(), host, port); } } /** * get value from redis * * @param key * @return */ public byte[] get(byte[] key) { byte[] value = null; Jedis jedis = jedisPool.getResource(); jedis.auth("你的密碼"); try { value = jedis.get(key); } finally { jedisPool.returnResource(jedis); } return value; } /** * get value from redis * * @param key * @return */ public String get(String key) { String value = null; Jedis jedis = jedisPool.getResource(); jedis.auth("你的密碼"); try { value = jedis.get(key); } finally { jedisPool.returnResource(jedis); } return value; } /** * set * * @param key * @param value * @return */ public byte[] set(byte[] key, byte[] value) { Jedis jedis = jedisPool.getResource(); jedis.auth("你的密碼"); try { jedis.set(key, value); if (this.expire != 0) { jedis.expire(key, this.expire); } } finally { jedisPool.returnResource(jedis); } return value; } /** * set * * @param key * @param value * @return */ public String set(String key, String value) { Jedis jedis = jedisPool.getResource(); jedis.auth("你的密碼"); try { jedis.set(key, value); if (this.expire != 0) { jedis.expire(key, this.expire); } } finally { jedisPool.returnResource(jedis); } return value; } /** * set * * @param key * @param value * @param expire * @return */ public byte[] set(byte[] key, byte[] value, int expire) { Jedis jedis = jedisPool.getResource(); jedis.auth("你的密碼"); try { jedis.set(key, value); if (expire != 0) { jedis.expire(key, expire); } } finally { jedisPool.returnResource(jedis); } return value; } /** * set * * @param key * @param value * @param expire * @return */ public String set(String key, String value, int expire) { Jedis jedis = jedisPool.getResource(); jedis.auth("你的密碼"); try { jedis.set(key, value); if (expire != 0) { jedis.expire(key, expire); } } finally { jedisPool.returnResource(jedis); } return value; } /** * del * * @param key */ public void del(byte[] key) { Jedis jedis = jedisPool.getResource(); jedis.auth("你的密碼"); try { jedis.del(key); } finally { jedisPool.returnResource(jedis); } } /** * del * * @param key */ public void del(String key) { Jedis jedis = jedisPool.getResource(); jedis.auth("你的密碼"); try { jedis.del(key); } finally { jedisPool.returnResource(jedis); } } /** * flush */ public void flushDB() { Jedis jedis = jedisPool.getResource(); jedis.auth("你的密碼"); try { jedis.flushDB(); } finally { jedisPool.returnResource(jedis); } } /** * size */ public Long dbSize() { Long dbSize = 0L; Jedis jedis = jedisPool.getResource(); jedis.auth("你的密碼"); try { dbSize = jedis.dbSize(); } finally { jedisPool.returnResource(jedis); } return dbSize; } /** * keys * * @param regex * @return */ public Set<byte[]> keys(String pattern) { Set<byte[]> keys = null; Jedis jedis = jedisPool.getResource(); jedis.auth("你的密碼"); try { System.out.println("我調用了keys方法=---shiro"); keys = jedis.keys(pattern.getBytes()); if (null != keys) System.out.println(keys.size()); } finally { jedisPool.returnResource(jedis); } return keys; } public void dels(String pattern) { Set<byte[]> keys = null; Jedis jedis = jedisPool.getResource(); jedis.auth("你的密碼"); try { System.out.println("我調用了dels方法=---shiro"); keys = jedis.keys(pattern.getBytes()); Iterator<byte[]> ito = keys.iterator(); while (ito.hasNext()) { jedis.del(ito.next()); } } finally { jedisPool.returnResource(jedis); } } public String getHost() { return host; } public void setHost(String host) { this.host = host; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } public int getExpire() { return expire; } public void setExpire(int expire) { this.expire = expire; } }
/** * Copyright (c) 2005-2012 https://github.com/zhangkaitao * * Licensed under the Apache License, Version 2.0 (the "License"); */ package org.calonlan.security.spring; import net.sf.ehcache.Ehcache; import org.apache.shiro.cache.Cache; import org.apache.shiro.cache.CacheException; import org.apache.shiro.cache.CacheManager; import org.apache.shiro.util.CollectionUtils; import org.springframework.cache.support.SimpleValueWrapper; import java.util.*; /** * 包裝Spring cache抽象 * <p>User: Zhang Kaitao * <p>Date: 13-3-23 上午8:26 * <p>Version: 1.0 */ public class SpringCacheManagerWrapper implements CacheManager { private org.springframework.cache.CacheManager cacheManager; /** * 設置spring cache manager * * @param cacheManager */ public void setCacheManager(org.springframework.cache.CacheManager cacheManager) { this.cacheManager = cacheManager; } @Override public <K, V> Cache<K, V> getCache(String name) throws CacheException { org.springframework.cache.Cache springCache = cacheManager.getCache(name); return new SpringCacheWrapper(springCache); } static class SpringCacheWrapper implements Cache { private org.springframework.cache.Cache springCache; SpringCacheWrapper(org.springframework.cache.Cache springCache) { this.springCache = springCache; } @Override public Object get(Object key) throws CacheException { Object value = springCache.get(key); if (value instanceof SimpleValueWrapper) { return ((SimpleValueWrapper) value).get(); } return value; } @Override public Object put(Object key, Object value) throws CacheException { springCache.put(key, value); return value; } @Override public Object remove(Object key) throws CacheException { springCache.evict(key); return null; } @Override public void clear() throws CacheException { springCache.clear(); } @Override public int size() { if(springCache.getNativeCache() instanceof Ehcache) { Ehcache ehcache = (Ehcache) springCache.getNativeCache(); return ehcache.getSize(); } throw new UnsupportedOperationException("invoke spring cache abstract size method not supported"); } @Override public Set keys() { if(springCache.getNativeCache() instanceof Ehcache) { Ehcache ehcache = (Ehcache) springCache.getNativeCache(); return new HashSet(ehcache.getKeys()); } throw new UnsupportedOperationException("invoke spring cache abstract keys method not supported"); } @Override public Collection values() { if(springCache.getNativeCache() instanceof Ehcache) { Ehcache ehcache = (Ehcache) springCache.getNativeCache(); List keys = ehcache.getKeys(); if (!CollectionUtils.isEmpty(keys)) { List values = new ArrayList(keys.size()); for (Object key : keys) { Object value = get(key); if (value != null) { values.add(value); } } return Collections.unmodifiableList(values); } else { return Collections.emptyList(); } } throw new UnsupportedOperationException("invoke spring cache abstract values method not supported"); } } }
RetryLimitHashedCredentialsMatcher:git
package org.calonlan.security.credentials; 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 java.util.concurrent.atomic.AtomicInteger; /** * <p>User: Zhang Kaitao * <p>Date: 14-1-28 * <p>Version: 1.0 */ public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher { private Cache<String, AtomicInteger> passwordRetryCache; public RetryLimitHashedCredentialsMatcher(CacheManager cacheManager) { passwordRetryCache = cacheManager.getCache("passwordRetryCache"); } @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 throw new ExcessiveAttemptsException(); } boolean matches = super.doCredentialsMatch(token, info); if(matches) { //clear retry count passwordRetryCache.remove(username); } return matches; } }
UserRealm:github
package org.calonlan.security.realm; import org.apache.log4j.Logger; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.LockedAccountException; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.cache.Cache; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.util.ByteSource; import org.calonlan.security.entity.User; import org.calonlan.security.service.ResourceService; import org.calonlan.security.service.UserRoleService; import org.calonlan.security.service.UserService; /** * @ClassName: UserRealm * @Description: TODO(這裏用一句話描述這個類的做用) * @author mbc * @date 2014-6-7 上午11:49:06 * */ public class UserRealm extends AuthorizingRealm { private static final Logger logger = Logger.getLogger(UserRealm.class); @javax.annotation.Resource private UserRoleService userRoleService; @javax.annotation.Resource private ResourceService resourceService; @javax.annotation.Resource private UserService userService; /* * (非 Javadoc) <p>Title: doGetAuthorizationInfo</p> <p>Description:權限受權 </p> * * @param principals * * @return * * @see * org.apache.shiro.realm.AuthorizingRealm#doGetAuthorizationInfo(org.apache * .shiro.subject.PrincipalCollection) */ @Override protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection principals) { // 爲空的狀況直接返回null if (null == principals) { return null; } SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); String username = (String) principals.getPrimaryPrincipal(); Cache<Object, AuthenticationInfo> cache = getAuthenticationCache(); System.out.println(cache == null); logger.info("[用戶:" + username + "|權限受權]"); authorizationInfo.setRoles(userRoleService .loadRoleIdsByUsername(username)); authorizationInfo.setStringPermissions(resourceService .loadPermissionsByUsername(username)); logger.info("[用戶:" + username + "|權限受權完成]"); return authorizationInfo; } /* * (非 Javadoc) <p>Title: doGetAuthenticationInfo</p> <p>Description:權限認證 * </p> * * @param token * * @return * * @throws AuthenticationException * * @see * org.apache.shiro.realm.AuthenticatingRealm#doGetAuthenticationInfo(org * .apache.shiro.authc.AuthenticationToken) */ @Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException { SimpleAuthenticationInfo authenticationInfo; String username = (String) token.getPrincipal(); logger.info("[用戶:" + username + "|系統權限認證]"); User user = userService.loadByUsername(username); if (user != null) { if ("賬號鎖定".equals(user.getState())) { throw new LockedAccountException();// 賬號鎖定 } // 交給AuthenticatingRealm使用CredentialsMatcher進行密碼匹配,若是以爲人家的很差能夠自定義實現 authenticationInfo = new SimpleAuthenticationInfo( user.getUsername(), user.getPassword(), ByteSource.Util.bytes(user.getCredentialsSalt()), getName());// realm logger.info("[用戶:" + username + "|系統權限認證完成]"); return authenticationInfo; // name } else return null; } }