1. 程式人生 > >SpringSecurity 禁用使用者後 實現清除指定使用者快取

SpringSecurity 禁用使用者後 實現清除指定使用者快取

問題出現的場景
一般在類似於資訊管理平臺,通常會有對使用者的狀態進行操作,我遇到的問題是,當管理員使用者,禁用普通使用者後,普通使用者仍然可以登入。

出現的原因
SpringSecurity在使用者登陸訪問系統過程中,會將使用者的登陸資訊儲存到cache當中,它允許將頻繁訪問的伺服器資源儲存在記憶體中,當用戶發出相同的請求後,伺服器不是再次處理而是將Cache中儲存的資料直接返回給使用者。因此,當管理員進行使用者禁用時,如果不及時重新整理快取,使用者再次登陸,依舊可以登入成功。

解決
實現思路:當管理員操作普通使用者時,清除指定使用者快取。
程式碼如下:

@Autowired
    private
ICacheRefreshService cacheRefreshService; ...... //將使用者鎖定 if (type == 1) { userLock.setStatus("1"); userService.update(userLock); //實現重新整理使用者快取 this.cacheRefreshService.refreshUser(userName); //記錄操作日誌 logService.sysLog(Log.SYSTEM, "使用者-鎖定", userLock.getId(), userLock.getUserName()+
"|"+userLock.getRealName(), "鎖定使用者"); //頁面處理,和文章無關 result = new Result(true, "使用者鎖定成功!"); }

建立工具類

//interface
public interface ICacheRefreshService {
    public  void refreshUrl();
    public void refreshUser(String username);
}
//實現類
public class CacheRefreshService implements ICacheRefreshService
{
private UserCache userCache;//使用者快取 private IResourceCacheManager urlCache;//資源授權快取(和本篇內容無關) /** * 重新整理其中一個使用者 * @param username */ public void refreshUser(String username){ userCache.removeUserFromCache(username); } /** * 重新整理全部URL */ public void refreshUrl(){ urlCache.removeAll(); urlCache.init(); } public void setUserCache(UserCache userCache) { this.userCache = userCache; } public void setUrlCache(IResourceCacheManager urlCache) { this.urlCache = urlCache; } } //interface UserCache public interface UserCache { /** * Obtains a {@link UserDetails} from the cache. * * @param username the {@link User#getUsername()} used to place the user in the cache * * @return the populated <code>UserDetails</code> or <code>null</code> if the user could not be found or if the * cache entry has expired */ UserDetails getUserFromCache(String username); /** * Places a {@link UserDetails} in the cache. The <code>username</code> is the key used to subsequently * retrieve the <code>UserDetails</code>. * * @param user the fully populated <code>UserDetails</code> to place in the cache */ void putUserInCache(UserDetails user); /** * Removes the specified user from the cache. The <code>username</code> is the key used to remove the user. * If the user is not found, the method should simply return (not thrown an exception).<P>Some cache * implementations may not support eviction from the cache, in which case they should provide appropriate * behaviour to alter the user in either its documentation, via an exception, or through a log message.</p> * * @param username to be evicted from the cache */ void removeUserFromCache(String username); } //EhCacheBasedUserCache /** * Caches <code>User</code> objects using a Spring IoC defined <A * HREF="http://ehcache.sourceforge.net">EHCACHE</a>. * * @author Ben Alex * @version $Id: EhCacheBasedUserCache.java 2217 2007-10-27 00:45:30Z luke_t $ */ public class EhCacheBasedUserCache implements UserCache, InitializingBean { //~ Static fields/initializers ===================================================================================== private static final Log logger = LogFactory.getLog(EhCacheBasedUserCache.class); //~ Instance fields ================================================================================================ private Ehcache cache; //~ Methods ======================================================================================================== public void afterPropertiesSet() throws Exception { Assert.notNull(cache, "cache mandatory"); } public Ehcache getCache() { return cache; } public UserDetails getUserFromCache(String username) { Element element = null; try { element = cache.get(username); } catch (CacheException cacheException) { throw new DataRetrievalFailureException("Cache failure: " + cacheException.getMessage()); } if (logger.isDebugEnabled()) { logger.debug("Cache hit: " + (element != null) + "; username: " + username); } if (element == null) { return null; } else { return (UserDetails) element.getValue(); } } public void putUserInCache(UserDetails user) { Element element = new Element(user.getUsername(), user); if (logger.isDebugEnabled()) { logger.debug("Cache put: " + element.getKey()); } cache.put(element); } public void removeUserFromCache(UserDetails user) { if (logger.isDebugEnabled()) { logger.debug("Cache remove: " + user.getUsername()); } this.removeUserFromCache(user.getUsername()); } public void removeUserFromCache(String username) { cache.remove(username); } public void setCache(Ehcache cache) { this.cache = cache; } }

springSecurity配置的部分程式碼:

<!--cache manager-->
<beans:bean id="cacheManager"
            class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
            p:configLocation="classpath:ehcache.xml">
</beans:bean>
<beans:bean id="userCache"
                class="org.springframework.security.providers.dao.cache.EhCacheBasedUserCache">
        <beans:property name="cache">
            <beans:bean class="org.springframework.cache.ehcache.EhCacheFactoryBean"
                        p:cacheManager-ref="cacheManager"
                        p:cacheName="security.user"/>
        </beans:property>
    </beans:bean>
    <beans:bean id="urlCache"
                class="org.zcframework.security.cache.impl.UrlResourceCacheManager" init-method="init"
                destroy-method="destroy">
        <beans:property name="cache">
            <beans:bean class="org.springframework.cache.ehcache.EhCacheFactoryBean"
                        p:cacheManager-ref="cacheManager"
                        p:cacheName="security.url"/>
        </beans:property>
        <beans:property name="resourceDetailService" ref="resourceDetailService"/>
    </beans:bean>

    <beans:bean id="cacheRefreshService" class="org.zcframework.security.cache.impl.CacheRefreshService">
        <beans:property name="userCache" ref="userCache"/>
        <beans:property name="urlCache" ref="urlCache"/>
    </beans:bean>