Java使用reids,以及redis與shiro集成

什麼是redis:redis是一個key-value存儲系統。和Memcached相似,它支持存儲的value類型相對更多,包括string(字符串)、list(鏈表)、set(集合)、zset(sorted set --有序集合)和hash(哈希類型)。這些數據類型都支持push/pop、add/remove及取交集並集和差集及更豐富的操做,並且這些操做都是原子性的。在此基礎上,redis支持各類不一樣方式的排序。與memcached同樣,爲了保證效率,數據都是緩存在內存中。區別的是redis會週期性的把更新的數據寫入磁盤或者把修改操做寫入追加的記錄文件,而且在此基礎上實現了master-slave(主從)同步。(我也是百度的,我的理解reids就是個比較輕量級的key——value模式的數據庫,這個數據庫的存儲性能很好,能夠用來代替緩存實現的不少功能。並且這個redis數據庫是第三方獨立的服務,能夠用在負載均衡狀況下多個服務器,多個web容器之間公用數據的緩存。)
要使用reids,首先能夠到官網reids的jar包和redis。
而後把redis的jar包導入到項目中。
我用的版本是2.1.0. 系統是32位的,因此我解壓了32位的redis服務。
打開之後使用裏面的redis-servier。exe來啓動redis服務。啓動後的結果以下圖所示
 
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>
在spring中就是在這個地方把reids服務的配置文件redis.properties文件加載到spring中管理的。
 
 
這樣redis服務就集成到了項目中,具體的使用,經過對shiro默認緩存和session數據的緩存的保存過程來展現。
 
項目中遇到的問題是這樣的,在同時使用一個機器使用多個web容器或者多個機器同時來爲一個項目進行負載均衡時,shiro的默認緩存和session數據沒法在多個web容器或者多個機器之間進行同步。爲了達到多web容器或多機器負載均衡的目的,咱們修改了shiro的默認session管理器和緩存管理器來使shiro經過redis來管理session和緩存。這樣多個web容器或機器之間的數據就能夠互通共用了。
首先是shiro的配置文件,我用的是spring集成的方式。
 
<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>
主要看上圖的紅色部分:其中customShiroSessionDAO、jedisShiroSessionRepository用來處理session;customShiroCacheManager、jedisShiroCacheManager用來處理緩存。
 
他們的源代碼以下:
 
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();
    }

}
具體的使用就如如上代碼所示,爲何要弄一個什麼ShiroCacheManager和ShiroSessionRepository接口呢,我想各位大俠也能知道的。有了這個兩個接口,咱們就能夠經過這個兩個接口來實現更多形式的shiro的session和緩存的管理了。
 
 
在不少地方使用到了SerializeUtils,它的做用就是把對象轉化爲byte數組,或把byte數組轉化爲對象。源代碼以下:
 
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;
        }

    }
}
而後項目的運行結果以下:
 
從圖中能夠看到,我登陸後,session信息已經保存到了redis數據庫中。多個tomcat作負載均衡的測試結果也很良好,可是我這個筆記本沒有安裝那種環境,因此沒法測試。這都是我的一點小東西,各位大神勿噴。
 
 
12.10日補充更新,爲了讓redis數據庫能安全的使用,(在實際生產環境中咱們也是這樣要求的)咱們須要給redis數據庫設置密碼;在windows環境下是這樣的。
 
首先進入32bit目錄中,找到redis.conf文件,在文件中作以下修改:
找到# requirepass foobared
修改成 requirepass 你的密碼。
 
而後在DOS環境下進入你的redis-server.exe所在的目錄
執行以下命令:redis-server.exe reids.conf 從dos中來啓動redis服務,這樣你的conf中配置纔會生效。
對應的我修改了redisManager的代碼。
 
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;
    }
}
我在代碼中還作了一下修改,代碼中也作了註釋。修改的地方是keys = jedis.keys(("*" + pattern).getBytes()); 在全部的pattern前面都加上*號了,由於我看到在redis實際使用的時候不加*號是查詢不到結果的。由於redis在咱們的id前面加了一堆東西;可是在使用get的時候倒是沒問題的,直接經過id就能取到值··這個我還沒弄懂· ··但願有高手看到之後能指點一下;我也會繼續研究。
 
12.10下午6點··今天休息··多想一想了··問題解決了。更新的代碼主要包括一下內容:
 
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;
    }
}
主要更改了這三個類,作的主要修改就是這句,byte[] key = getRedisSessionKey(session.getId()).getBytes();這句很重要,之前咱們的key和value同樣是用serilizableUtil在轉換爲byte數組的。可是咱們這樣轉換會有一個問題。就是會有OBJECT標識,由於咱們使用了對象流··。你們能夠看serilizableutil的代碼。而後我給你們看看修改前和修改後在數據庫中看到的不一樣景象;
修改前:
能夠看到咱們定義的key前面多了一堆/xac/xed#$^%^$%^$%^$這樣的東西,我的理解這就是類標識吧···
修改後:
能夠看到咱們的id就是按咱們定義的樣子在顯示着··雖然是用byte數組傳遞過去的··
 
而後的redismanager中,咱們使用keys(「shiro-session*」)也能夠列出須要的全部的key了···
 
就這樣··也許還會有問題····也但願高手能給批評意見。
 
有人反應我出如今配置文件中的類有幾個沒有貼出來,首先很感謝您的指正;在這裏我主要說shiro和redis的結合。至於shiro的配置使用不在這篇博文中討論。可是鑑於有人要看我就貼出來。
 
SpringCacheManagerWrapper
 
/**
 * 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;

    }

}
相關文章
相關標籤/搜索