shiro分布式控制登录状态_shiro权限控制(二):分布式架构中shiro的实现

前言:

前段时间在搭建公司游戏框架安全验证的时候,就想到之前web最火的shiro框架,虽然后面实践发现在netty中不太适用,最后自己模仿shiro写了一个缩减版的,但是中间花费两天时间弄出来的shiro可不能白费,这里给大家出个简单的教程说明吧。

shiro的基本介绍这里就不再说了,可以自行翻阅博主之前写的shiro教程,这篇文章主要说明分布式架构下shiro的session共享问题。

一、原理描述

无论分布式、还是集群下,项目都需要获取登录用户的信息,而不可能做的就是让客户在每个系统或者每个模块中反复登录,也不存在让客户端存载用户信息给服务端,这是很常识的问题

而单机模式下,我们用shiro做了登录验证,他的主要方式就是在第一次登陆的时候,把我们设置的用户信息保存在cache(内存)中和自带的ehcahe(缓存管理器)中,然后给客户端一个cookie,在每次客户端访问时获取cookie值,从而得到用户信息。

好了,那么逻辑就清楚了,分布式架构下,要与多系统共享用户信息,其实就是共享shiro保存的cache。

要在多项目中共享,内存是不可能的了,ehcache对分布式支持不太好,或者说根本不支持。那么剩下只能是我么熟悉的mysql,redis,mongdb啥的数据库了。这么一对比,不用我说大家也明白了,最适合的无疑是redis了,速度快,主从啥的。

二、流程描述

查看源码我们可以知道,cacheManager最终会被set到sessionDAO中,所以我们要自己写sessionDAO。有两个类去操作保存的,那么我们只需要重写,实现这两个类,然后在注册的时候声明即可。

1.shiroCache:cache类,可以自己写一个定时消除的MAP存放更好,文章结尾我会给出map的代码。而这里的代码我是放在redis的。

package com.result.shiro.distributed;

import java.util.ArrayList;

import java.util.Collection;

import java.util.List;

import java.util.Set;

import org.apache.shiro.cache.Cache;

import org.apache.shiro.cache.CacheException;

import com.result.redis.RedisKey;

import com.result.redis.RedisUtil;

import com.result.tools.KyroUtil;

/**

* @author 作者 huangxinyu

* @version 创建时间:2018年1月8日 下午9:33:23

* cache共享

*/

@SuppressWarnings("unchecked")

public class ShiroCache implements Cache {

private static final String REDIS_SHIRO_CACHE = RedisKey.CACHEKEY;

private String cacheKey;

private long globExpire = 30;

@SuppressWarnings("rawtypes")

public ShiroCache(String name) {

this.cacheKey = REDIS_SHIRO_CACHE + name + ":";

}

@Override

public V get(K key) throws CacheException {

Object obj = RedisUtil.get(KyroUtil.serialization(getCacheKey(key)));

if(obj==null){

return null;

}

return (V) KyroUtil.deserialization((String)obj);

}

@Override

public V put(K key, V value) throws CacheException {

V old = get(key);

RedisUtil.setex(KyroUtil.serialization(getCacheKey(key)), 18000, KyroUtil.serialization(value));

return old;

}

@Override

public V remove(K key) throws CacheException {

V old = get(key);

RedisUtil.del(KyroUtil.serialization(getCacheKey(key)));

return old;

}

@Override

public void clear() throws CacheException {

for(String key : (Set)keys()){

RedisUtil.del(key);

}

}

@Override

public int size() {

return keys().size();

}

@Override

public Set keys() {

return (Set) RedisUtil.keys(KyroUtil.serialization(getCacheKey("*")));

}

@Override

public Collection values() {

Set set = keys();

List list = new ArrayList<>();

for (K s : set) {

list.add(get(s));

}

return list;

}

private K getCacheKey(Object k) {

return (K) (this.cacheKey + k);

}

}

2.session操作类:这里用来把用户信息存放在redis中共享的。

package com.result.shiro.distributed;

/**

* @author 作者 huangxinyu

* @version 创建时间:2018年1月6日 上午10:12:42

* redis实现共享session

*/

import java.io.Serializable;

import java.util.Collection;

import java.util.HashSet;

import java.util.Set;

import org.apache.shiro.session.Session;

import org.apache.shiro.session.UnknownSessionException;

import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import com.result.redis.RedisKey;

import com.result.redis.RedisUtil;

import com.result.tools.KyroUtil;

import com.result.tools.SerializationUtil;

public class RedisSessionDao extends EnterpriseCacheSessionDAO {

private static Logger logger = LoggerFactory.getLogger(RedisSessionDao.class);

@Override

public void update(Session session) throws UnknownSessionException {

this.saveSession(session);

}

/**

* 删除session

*/

@Override

public void delete(Session session) {

if (session == null || session.getId() == null) {

logger.error("==========session或sessionI 不存在");

return;

}

RedisUtil.del(KyroUtil.serialization(RedisKey.SESSIONKEY + session.getId()));

}

/**

* 获取存活的sessions

*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值