아파 치 shiro 클 러 스 터 구현 (7) 분포 식 클 러 스 터 시스템 에서 - cache 공유
Apache shiro 클 러 스 터 구현 (2) shiro 의 INI 설정
아파 치 shiro 클 러 스 터 구현 (3) shiro 인증 (Shiro Authentication)
아파 치 shiro 클 러 스 터 구현 (4) shiro 권한 부여 (Authentication) -- 접근 제어
Apache shiro 클 러 스 터 구현 (5) 분포 식 클 러 스 터 시스템 에서 사용 가능 한 높 은 session 솔 루 션
Apache shiro 클 러 스 터 구현 (6) 분포 식 클 러 스 터 시스템 에서 사용 가능 한 높 은 session 솔 루 션 - Session 공유
아파 치 shiro 클 러 스 터 구현 (7) 분포 식 클 러 스 터 시스템 에서 - cache 공유
Apache shiro 클 러 스 터 구현 (8) 웹 클 러 스 터 시 session 동기 화 3 가지 방법
지난 편 에 서 는 첫 번 째 문제, session 의 공 유 를 해 결 했 습 니 다. 지금 우 리 는 두 번 째 문제 cache 의 공 유 를 해결 합 니 다.
다음 spring 프로필 을 먼저 보 세 요.
<span style="font-size:18px;"><bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager" depends-on="userRepository,roleRepository">
<property name="sessionManager" ref="defaultWebSessionManager" />
<property name="realm" ref="shiroDbRealm" />
<property name="cacheManager" ref="memoryConstrainedCacheManager" />
</bean>
<bean id="memoryConstrainedCacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager" /></span>
여기 cacheManager 는 shiro 가 자체 적 으로 정 한 이 컴퓨터 메모리 에 실 현 된 cacheManager 류 를 주입 합 니 다. 물론 이것 은 우리 집단의 수 요 를 만족 시 키 지 못 할 것 입 니 다. 그래서 우 리 는 스스로 cacheManager 류 를 실현 해 야 합 니 다. 여기 서 저 는 redis 를 cache 의 저장 소로 사용 하고 RedisCacheManager 실현 류 를 먼저 만 듭 니 다.
<span style="font-size:18px;">package com.tgb.itoo.authority.cache;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.cache.CacheManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RedisCacheManager implements CacheManager{
private static final Logger logger = LoggerFactory
.getLogger(RedisCacheManager.class);
// fast lookup by name map
private final ConcurrentMap<String, Cache> caches = new ConcurrentHashMap<String, Cache>();
private RedisManager redisManager;
/**
* The Redis key prefix for caches
*/
private String keyPrefix = "shiro_redis_cache:";
/**
* Returns the Redis session keys
* prefix.
* @return The prefix
*/
public String getKeyPrefix() {
return keyPrefix;
}
/**
* Sets the Redis sessions key
* prefix.
* @param keyPrefix The prefix
*/
public void setKeyPrefix(String keyPrefix) {
this.keyPrefix = keyPrefix;
}
@Override
public <K, V> Cache<K, V> getCache(String name) throws CacheException {
logger.debug(" : " + name + " RedisCache ");
Cache c = caches.get(name);
if (c == null) {
// initialize the Redis manager instance
redisManager.init();
// create a new cache instance
c = new RedisCache<K, V>(redisManager, keyPrefix);
// add it to the cache collection
caches.put(name, c);
}
return c;
}
public RedisManager getRedisManager() {
return redisManager;
}
public void setRedisManager(RedisManager redisManager) {
this.redisManager = redisManager;
}
}
</span>
물론 여 기 는 getCache 일 뿐 입 니 다. 제 가 소스 코드 를 처음 봤 을 때 도 이런 의문 이 있 었 습 니 다. cache 의 add, remove 등 방법 은 어디에서 이 루어 졌 습 니까?저희 가 계속해서 shiro 의 소스 코드 를 보면 답 을 알 수 있 을 거 예요.
이 건 자기 relm 의 Authorizing Realm 의 방법 이에 요.
<span style="font-size:18px;"> protected AuthorizationInfo getAuthorizationInfo(PrincipalCollection principals) {
if (principals == null) {
return null;
}
AuthorizationInfo info = null;
if (log.isTraceEnabled()) {
log.trace("Retrieving AuthorizationInfo for principals [" + principals + "]");
}
Cache<Object, AuthorizationInfo> cache = getAvailableAuthorizationCache();
if (cache != null) {
if (log.isTraceEnabled()) {
log.trace("Attempting to retrieve the AuthorizationInfo from cache.");
}
Object key = getAuthorizationCacheKey(principals);
info = cache.get(key);
if (log.isTraceEnabled()) {
if (info == null) {
log.trace("No AuthorizationInfo found in cache for principals [" + principals + "]");
} else {
log.trace("AuthorizationInfo found in cache for principals [" + principals + "]");
}
}
}
if (info == null) {
// Call template method if the info was not found in a cache
info = <STRONG>doGetAuthorizationInfo</STRONG>(principals);
// If the info is not null and the cache has been created, then cache the authorization info.
if (info != null && cache != null) {
if (log.isTraceEnabled()) {
log.trace("Caching authorization info for principals: [" + principals + "].");
}
Object key = getAuthorizationCacheKey(principals);
<STRONG>cache.put</STRONG>(key, info);
}
}
return info;
} </span>
만약 에 여러분 이 찾 아서 도입 하면 우리 가 사용자 정의 relm 이 doGetAuthorizationInfo () 라 는 방법 을 실현 해 야 한 다 는 것 을 알 수 있 습 니 다. 그 역할 은 권한 수여 정 보 를 조회 하 는 것 입 니 다. 우 리 는 굵 은 2 줄 에 주 의 를 기울 여야 합 니 다. 사실은 cache 의 put 방법 이 cache 저장 의 핵심 유형 이라는 것 을 알 게 되 었 습 니 다. 사실은 모두 cache 에 있 기 때문에 우 리 는 자신의 cache 를 실현 하고 RedisCache 류 를 만들어 야 합 니 다.
<span style="font-size:18px;">package com.tgb.itoo.authority.cache;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.util.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RedisCache<K,V> implements Cache<K,V> {
private Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* The wrapped Jedis instance.
*/
private RedisManager cache;
/**
* The Redis key prefix for the sessions
*/
private String keyPrefix = "shiro_redis_session:";
/**
* Returns the Redis session keys
* prefix.
* @return The prefix
*/
public String getKeyPrefix() {
return keyPrefix;
}
/**
* Sets the Redis sessions key
* prefix.
* @param keyPrefix The prefix
*/
public void setKeyPrefix(String keyPrefix) {
this.keyPrefix = keyPrefix;
}
/**
* JedisManager RedisCache
*/
public RedisCache(RedisManager cache){
if (cache == null) {
throw new IllegalArgumentException("Cache argument cannot be null.");
}
this.cache = cache;
}
/**
* Constructs a cache instance with the specified
* Redis manager and using a custom key prefix.
* @param cache The cache manager instance
* @param prefix The Redis key prefix
*/
public RedisCache(RedisManager cache,
String prefix){
this( cache );
// set the prefix
this.keyPrefix = prefix;
}
/**
* byte[] key
* @param key
* @return
*/
private byte[] getByteKey(K key){
if(key instanceof String){
String preKey = this.keyPrefix + key;
return preKey.getBytes();
}else{
return SerializeUtils.serialize(key);
}
}
@Override
public V get(K key) throws CacheException {
logger.debug(" key Redis key [" + key + "]");
try {
if (key == null) {
return null;
}else{
byte[] rawValue = cache.get(getByteKey(key));
@SuppressWarnings("unchecked")
V value = (V)SerializeUtils.deserialize(rawValue);
return value;
}
} catch (Throwable t) {
throw new CacheException(t);
}
}
@Override
public V put(K key, V value) throws CacheException {
logger.debug(" key key [" + key + "]");
try {
cache.set(getByteKey(key), SerializeUtils.serialize(value));
return value;
} catch (Throwable t) {
throw new CacheException(t);
}
}
@Override
public V remove(K key) throws CacheException {
logger.debug(" redis key [" + key + "]");
try {
V previous = get(key);
cache.del(getByteKey(key));
return previous;
} catch (Throwable t) {
throw new CacheException(t);
}
}
@Override
public void clear() throws CacheException {
logger.debug(" redis ");
try {
cache.flushDB();
} catch (Throwable t) {
throw new CacheException(t);
}
}
@Override
public int size() {
try {
Long longSize = new Long(cache.dbSize());
return longSize.intValue();
} catch (Throwable t) {
throw new CacheException(t);
}
}
@SuppressWarnings("unchecked")
@Override
public Set<K> keys() {
try {
Set<byte[]> keys = cache.keys(this.keyPrefix + "*");
if (CollectionUtils.isEmpty(keys)) {
return Collections.emptySet();
}else{
Set<K> newKeys = new HashSet<K>();
for(byte[] key:keys){
newKeys.add((K)key);
}
return newKeys;
}
} catch (Throwable t) {
throw new CacheException(t);
}
}
@Override
public Collection<V> values() {
try {
Set<byte[]> keys = cache.keys(this.keyPrefix + "*");
if (!CollectionUtils.isEmpty(keys)) {
List<V> values = new ArrayList<V>(keys.size());
for (byte[] key : keys) {
@SuppressWarnings("unchecked")
V value = get((K)key);
if (value != null) {
values.add(value);
}
}
return Collections.unmodifiableList(values);
} else {
return Collections.emptyList();
}
} catch (Throwable t) {
throw new CacheException(t);
}
}
}
</span>
마지막 으로 spring 프로필 수정
<span style="font-size:18px;"><!-- :shiro start- -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="shiroRealm"></property>
<property name="sessionMode" value="http"></property>
<property name="subjectFactory" ref="casSubjectFactory"></property>
<!-- ehcahe shiro -->
<!-- <property name="cacheManager" ref="shiroEhcacheManager"></property> -->
<!-- redis -->
<property name="cacheManager" ref="redisCacheManager" />
<!-- sessionManager -->
<property name="sessionManager" ref="sessionManager"></property>
</bean></span>
이렇게 해서 전체 shiro 군집 의 설정 을 완성 하 였 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.