shiroセキュリティフレームワーク拡張チュートリアル--realmブリッジを拡張し、自動クリアロールリソースキャッシュを終了する方法


前の章では、自分のキャッシュメカニズムを拡張する方法を知っています.次に、自分のカスタムキャッシュをどのように適用するかを学びます.ログインするにはrealmを書かなければなりません.いわゆるブリッジです.
私たちがログインすると、所有するロールがキャッシュに格納されるため、リクエストのたびにデータベースにアクセスする必要がなくなり、アレクサンダーが終了したときに自動的にログインしたときに追加したキャッシュデータが
以下に展示コードを貼ります
package com.silvery.security.shiro.realm;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.silvery.core.model.ViewResult;
import com.silvery.project.cms.model.Authority;
import com.silvery.project.cms.model.UserDetails;
import com.silvery.project.cms.service.AuthorityService;
import com.silvery.project.cms.service.UserDetailsService;
import com.silvery.project.cms.vo.AuthorityVo;
import com.silvery.project.cms.vo.UserDetailsVo;
import com.silvery.security.shiro.cache.SimpleMapCache;
import com.silvery.security.shiro.cache.extend.SimpleCacheManager;

/**
 * 
 *        
 * 
 * @author shadow
 * 
 */
public class SimpleUserRealm extends AuthorizingRealm {

	private final static Logger log = LoggerFactory.getLogger(SimpleUserRealm.class);

	@Autowired
	private UserDetailsService userDetailsService;

	@Autowired
	private AuthorityService authorityService;

	@Autowired
	private SimpleCacheManager simpleCacheManager;

	//         
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		return getAuthorizationInfo(principals.getPrimaryPrincipal());
	}

	@SuppressWarnings("unchecked")
	private SimpleAuthorizationInfo getAuthorizationInfo(Object principal) {

		List<Authority> authorities = null;

		//     ,             
		try {
			authorities = (List<Authority>) simpleCacheManager.getCache(principal.toString()).get(principal);
		} catch (Exception e) {
			authorities = new ArrayList<Authority>();
			log.error(e.getMessage());
		}

		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();

		//            
		for (Authority authority : authorities) {
			authorizationInfo.addRole((authority.getName()));
		}

		return authorizationInfo;

	}

	//       
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {

		UsernamePasswordToken token = (UsernamePasswordToken) authcToken;

		UserDetailsVo vo = new UserDetailsVo();
		vo.setUsername(token.getUsername());
		vo.setPassword(String.valueOf(token.getPassword()));
		vo.setJcaptionCode(token.getHost());

		//                  
		ViewResult viewResult = userDetailsService.login(vo);

		if (viewResult.getSuccess()) {
			UserDetails details = (UserDetails) viewResult.getValue();
			//            
			loadUserAuthorityTocache(details);
			//           
			return new SimpleAuthenticationInfo(details.getUsername(), details.getPassword(), getName());
		} else {
			log.debug(new StringBuffer().append(token.getUsername()).append(" login failure at ").append(
					new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())).append(", error message: ").append(
					viewResult.getMessage()).toString());
			//                     
			throw new AuthenticationException(viewResult.getMessage());
		}

	}

	/**
	 *       
	 * 
	 * @param details
	 */
	private void loadUserAuthorityTocache(UserDetails details) {

		//          cache key
		String cacheKey = details.getUsername();

		AuthorityVo vo = new AuthorityVo();
		vo.setUser_id(details.getId());

		//           map
		Map<Object, Object> map = new HashMap<Object, Object>();
		map.put(cacheKey, authorityService.find4user(vo).getValue());

		//   cache          
		SimpleMapCache cache = new SimpleMapCache(cacheKey, map);
		simpleCacheManager.createCache(details.getUsername(), cache);

	}

	/**             */
	protected void doClearCache(PrincipalCollection principalcollection) {
		Object principal = principalcollection.getPrimaryPrincipal();
		simpleCacheManager.removeCache(principal.toString());
		log.debug(new StringBuffer().append(principal).append(" on logout to remove the cache [").append(principal)
				.append("]").toString());
	}

}

1.ログインプロセスでは、独自に定義したキャッシュマネージャを使用してログイン認証に成功した後、ユーザーの関連ロールをロードしてキャッシュに格納することが明らかになりました.
2.ユーザーが認証する時、私達のカスタムキャッシュマネージャを通じて資源を読み取って、私達が第2回データベースの需要を問合せないことを実現します
3.終了した自動クリア関連キャッシュをどのようにしてクリアしますか?私がdoClearCacheを書き換える方法であることがわかりますが、なぜ書き直すのですか?まず下に書いてあるソースを見てみましょう.
public abstract class CachingRealm
    implements Realm, Nameable, CacheManagerAware, LogoutAware
{

    public CachingRealm()
    {
        cachingEnabled = true;
        name = (new StringBuilder()).append(getClass().getName()).append("_").append(INSTANCE_COUNT.getAndIncrement()).toString();
    }

    public CacheManager getCacheManager()
    {
        return cacheManager;
    }

    public void setCacheManager(CacheManager cacheManager)
    {
        this.cacheManager = cacheManager;
        afterCacheManagerSet();
    }

    public boolean isCachingEnabled()
    {
        return cachingEnabled;
    }

    public void setCachingEnabled(boolean cachingEnabled)
    {
        this.cachingEnabled = cachingEnabled;
    }

    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    protected void afterCacheManagerSet()
    {
    }

    public void onLogout(PrincipalCollection principals)
    {
        clearCache(principals);
    }

    protected void clearCache(PrincipalCollection principals)
    {
        if(!CollectionUtils.isEmpty(principals))
        {
            doClearCache(principals);
            log.trace("Cleared cache entries for account with principals [{}]", principals);
        }
    }

    protected void doClearCache(PrincipalCollection principalcollection)
    {
    }

    protected Object getAvailablePrincipal(PrincipalCollection principals)
    {
        Object primary = null;
        if(!CollectionUtils.isEmpty(principals))
        {
            Collection thisPrincipals = principals.fromRealm(getName());
            if(!CollectionUtils.isEmpty(thisPrincipals))
                primary = thisPrincipals.iterator().next();
            else
                primary = principals.getPrimaryPrincipal();
        }
        return primary;
    }

    private static final Logger log = LoggerFactory.getLogger(org/apache/shiro/realm/CachingRealm);
    private static final AtomicInteger INSTANCE_COUNT = new AtomicInteger();
    private String name;
    private boolean cachingEnabled;
    private CacheManager cacheManager;

}

安全終了時の動作をonLogoutで処理する方法が明らかになったので、この方法を書き直してremove cacheの動作に参加してみると、終了時に自分のロールリソースキャッシュを自動的に空にすることができます.
しかし、もし私が安全に退出しなければ、資源はずっと残っていますか?
これは間違いありませんが、次回ログインすると、リソースが上書きされる前のロールリソースキャッシュが再ロードされます.
今回の実験は简単ですが、実用的で、皆さんに役に立つと信じています.