session共享

登录缓存清理
缓存更换为redis缓存代码提交
This commit is contained in:
段冬梅
2018-12-16 11:04:25 +08:00
parent 22920b84cc
commit ed45211de9
11 changed files with 310 additions and 82 deletions

View File

@@ -5,6 +5,7 @@ import java.util.Map;
import java.util.Map.Entry;
import org.apache.log4j.Logger;
import org.apache.shiro.cache.Cache;
import com.beust.jcommander.internal.Lists;
import com.nis.domain.specific.ConfigGroupInfo;
@@ -12,8 +13,6 @@ import com.nis.web.dao.specific.ConfigGroupInfoDao;
import com.nis.web.service.SpringContextHolder;
import jersey.repackaged.com.google.common.collect.Maps;
import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
/**
* asn no缓存工具类
@@ -35,9 +34,12 @@ public class AsnCacheUtils{
* @return
*/
public static ConfigGroupInfo get(Long key) {
Element element = getCache(ASN_NO_CACHE).get(key/cache_rage);
Cache cache = getCache(ASN_NO_CACHE);
Object element = cache.get(key/cache_rage);
// Element element = getCache(ASN_NO_CACHE).get(key/cache_rage);
if(element!=null) {
Map<Long,ConfigGroupInfo> map=(Map<Long,ConfigGroupInfo>)element.getObjectValue();
Map<Long,ConfigGroupInfo> map=(Map<Long,ConfigGroupInfo>)element;
if(map.containsKey(key)) {
return map.get(key);
}
@@ -45,20 +47,19 @@ public class AsnCacheUtils{
return null;
}
public static Map<Long,ConfigGroupInfo> getMap(Object key) {
Element element = getCache(ASN_NO_CACHE).get(key);
return (Map<Long,ConfigGroupInfo>)element.getObjectValue();
Object element = getCache(ASN_NO_CACHE).get(key);
return (Map<Long,ConfigGroupInfo>)element;
}
public static void clearCache() {
logger.warn("clear cache!");
CacheUtils.getCacheManager().removeCache(ASN_NO_CACHE);
getCache(ASN_NO_CACHE).clear();
}
public static List<ConfigGroupInfo> getAllAsnGroup(){
List<ConfigGroupInfo> configGroupInfos=Lists.newArrayList();
Cache cache=getCache(ASN_NO_CACHE);
for(Object key:cache.getKeys()) {
Element element = getCache(ASN_NO_CACHE).get(key);
if(element!=null) {
Map<Long,ConfigGroupInfo> map=(Map<Long,ConfigGroupInfo>)element.getObjectValue();
for(Object val : cache.values()) {
if(val!=null) {
Map<Long,ConfigGroupInfo> map=(Map<Long,ConfigGroupInfo>)val;
configGroupInfos.addAll(map.values());
}
}
@@ -89,19 +90,21 @@ public class AsnCacheUtils{
}
}
for(Entry<Long, Map<Long, ConfigGroupInfo>> e:groupMap.entrySet()) {
Element element = new Element(e.getKey(), e.getValue());
cache.put(element);
cache.put(e.getKey(),e.getValue());
}
}else {
//查询总量
Long count=configGroupInfoDao.getCountByType(4);
boolean loadDatabase=false;
if(cache.getKeys().size()==0) {
if(cache.keys().size()==0) {
loadDatabase=true;
}else {
long c=0l;
for(Object key:cache.getKeys()) {
c+=getMap(key).size();
for(Object key:cache.keys()) {
Map<Long, ConfigGroupInfo> map = getMap(key);
if(map != null) {
c+=getMap(key).size();
}
}
if(c!=count) {
loadDatabase=true;
@@ -121,8 +124,7 @@ public class AsnCacheUtils{
}
}
for(Entry<Long, Map<Long, ConfigGroupInfo>> e:groupMap.entrySet()) {
Element element = new Element(e.getKey(), e.getValue());
cache.put(element);
cache.put(e.getKey(), e.getValue());
}
}
}
@@ -137,17 +139,16 @@ public class AsnCacheUtils{
*/
public static void put(Long key, ConfigGroupInfo value) {
Long _key=key/cache_rage;
Element element = getCache(ASN_NO_CACHE).get(_key);
Object element = getCache(ASN_NO_CACHE).get(_key);
if(element==null) {
Map<Long,ConfigGroupInfo> map=Maps.newHashMap();
map.put(key, value);
element = new Element(_key, map);
getCache(ASN_NO_CACHE).put(_key,map);
}else {
Map<Long,ConfigGroupInfo> map=(Map<Long,ConfigGroupInfo>)element.getObjectValue();
Map<Long,ConfigGroupInfo> map=(Map<Long,ConfigGroupInfo>)element;
map.put(key, value);
element = new Element(_key, map);
getCache(ASN_NO_CACHE).put(_key,map);
}
getCache(ASN_NO_CACHE).put(element);
}
/**
* 从缓存中移除
@@ -159,30 +160,25 @@ public class AsnCacheUtils{
}
public static void remove(Long key) {
Long _key=key/cache_rage;
Element element = getCache(ASN_NO_CACHE).get(_key);
Object element = getCache(ASN_NO_CACHE).get(_key);
if(element!=null) {
Map<Long,ConfigGroupInfo> map=(Map<Long,ConfigGroupInfo>)element.getObjectValue();
Map<Long,ConfigGroupInfo> map=(Map<Long,ConfigGroupInfo>)element;
if(map.containsKey(key)) {
map.remove(key);
}
if(map.isEmpty()) {
getCache(ASN_NO_CACHE).remove(_key);
}else {
element=new Element(_key,map);
getCache(ASN_NO_CACHE).put(element);
getCache(ASN_NO_CACHE).put(_key, map);
}
}
}
private static Cache getCache(String cacheName){
Cache cache = CacheUtils.getCacheManager().getCache(cacheName);
if (cache == null){
CacheUtils.getCacheManager().addCache(cacheName);
cache = CacheUtils.getCacheManager().getCache(cacheName);
cache.getCacheConfiguration().setEternal(true);
}
return cache;
}
public static String getCacheName() {
return ASN_NO_CACHE;
}

View File

@@ -1,10 +1,11 @@
package com.nis.util;
import org.apache.shiro.cache.Cache;
import org.crazycake.shiro.RedisCacheManager;
import com.nis.web.service.SpringContextHolder;
import net.sf.ehcache.Cache;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Element;
/**
* Cache工具类
@@ -13,7 +14,7 @@ import net.sf.ehcache.Element;
*/
public class CacheUtils {
private static CacheManager cacheManager = ((CacheManager)SpringContextHolder.getBean("cacheManager"));
private static RedisCacheManager cacheManager = (RedisCacheManager)SpringContextHolder.getBean("shiroCacheManager");
private static final String SYS_CACHE = "sysCache";
@@ -51,8 +52,7 @@ public class CacheUtils {
* @return
*/
public static Object get(String cacheName, String key) {
Element element = getCache(cacheName).get(key);
return element==null?null:element.getObjectValue();
return getCache(cacheName).get(key);
}
/**
@@ -62,8 +62,8 @@ public class CacheUtils {
* @param value
*/
public static void put(String cacheName, String key, Object value) {
Element element = new Element(key, value);
getCache(cacheName).put(element);
Cache cache=cacheManager.getCache(cacheName);
cache.put(key, value);
}
/**
@@ -80,7 +80,7 @@ public class CacheUtils {
* @param cacheName
* @return
*/
private static Cache getCache(String cacheName){
/*private static Cache getCache(String cacheName){
Cache cache = cacheManager.getCache(cacheName);
if (cache == null){
cacheManager.addCache(cacheName);
@@ -88,9 +88,13 @@ public class CacheUtils {
cache.getCacheConfiguration().setEternal(true);
}
return cache;
}*/
private static Cache getCache(String cacheName){
Cache cache = cacheManager.getCache(cacheName);
return cache;
}
public static CacheManager getCacheManager() {
public static RedisCacheManager getCacheManager() {
return cacheManager;
}

View File

@@ -1,12 +1,26 @@
package com.nis.web.controller.sys;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.derby.tools.sysinfo;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.mgt.RealmSecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.crazycake.shiro.RedisCache;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
@@ -22,11 +36,15 @@ import com.nis.domain.Page;
import com.nis.domain.SysRole;
import com.nis.domain.SysUser;
import com.nis.util.DateUtils;
import com.nis.util.IpUtil;
import com.nis.util.StringUtil;
import com.nis.util.StringUtils;
import com.nis.util.excel.ExportExcel;
import com.nis.web.controller.BaseController;
import com.nis.web.security.SystemAuthorizingRealm;
import com.nis.web.security.SystemAuthorizingRealm.Principal;
import com.nis.web.security.UserUtils;
import com.nis.web.security.UsernamePasswordToken;
@Controller
@RequestMapping("${adminPath}/sys/user")
@@ -97,7 +115,7 @@ public class UserController extends BaseController{
return form(user, model);
}*/
if (!"true".equals(checkLoginName(user.getOldLoginId(), user.getLoginId()))){
addMessage(redirectAttributes,"error", "save_failed");
addMessage(model,"error", "save_failed");
return form(user, model);
}
// 角色数据有效性验证,过滤不在授权内的角色
@@ -264,6 +282,7 @@ public class UserController extends BaseController{
/**
* 修改个人用户密码
*
* @param oldPassword
* @param newPassword
* @param model
@@ -273,20 +292,44 @@ public class UserController extends BaseController{
@RequestMapping(value = "modifyPwd")
public String modifyPwd(String oldPassword, String newPassword, Model model) {
SysUser user = UserUtils.getUser();
if (StringUtils.isNotBlank(oldPassword) && StringUtils.isNotBlank(newPassword)){
if (StringUtils.validatePassword(oldPassword, user.getPassword())){
if (StringUtils.isNotBlank(oldPassword) && StringUtils.isNotBlank(newPassword)) {
if (StringUtils.validatePassword(oldPassword, user.getPassword())) {
userService.updatePasswordById(user.getId(), user.getLoginId(), newPassword);
Session curSession = UserUtils.getSession();// 当前登录用户的session
Principal principal = UserUtils.getPrincipal();// 当前登录用户的鉴权信息
// 过滤 当前用户的 非此客户的其它登录信息
Collection<Session> allOtherSession = systemService.getActiveSessions(true, principal, curSession);
if (allOtherSession.size() > 0) {
// 如果是登录进来的,则踢出已在线用户
if (UserUtils.getSubject().isAuthenticated()) {
for (Session session : allOtherSession) {
systemService.deleteSession(session);
}
}
}
RealmSecurityManager securityManager = (RealmSecurityManager) SecurityUtils.getSecurityManager();
Collection<Realm> realm = securityManager.getRealms();
for (Realm realm2 : realm) {
SystemAuthorizingRealm userRealm = (SystemAuthorizingRealm) realm2;
RedisCache<Object, AuthenticationInfo> cache = (RedisCache<Object, AuthenticationInfo>) userRealm.getAuthenticationCache();
String keyPrefix = cache.getKeyPrefix();
for (AuthenticationInfo auth : cache.values()) {
userRealm.getAuthenticationCache().remove(auth.getPrincipals().getPrimaryPrincipal());
}
systemService.deleteAuthenticationCache(keyPrefix + user.getName());
systemService.deleteAuthenticationCache(keyPrefix + user.getId());
}
model.addAttribute("message", "update_success");
}else{
} else {
model.addAttribute("message", "update_failed");
}
}
model.addAttribute("user", user);
return "/sys/userModifyPwd";
}
}

View File

@@ -11,6 +11,7 @@ import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.crazycake.shiro.RedisSessionDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -26,7 +27,8 @@ import com.nis.util.StringUtils;
* @author
* @version
*/
public class CacheSessionDAO extends EnterpriseCacheSessionDAO implements SessionDAO {
/*public class CacheSessionDAO extends EnterpriseCacheSessionDAO implements SessionDAO {*/
public class CacheSessionDAO extends RedisSessionDAO {
private Logger logger = LoggerFactory.getLogger(getClass());
@@ -34,7 +36,7 @@ public class CacheSessionDAO extends EnterpriseCacheSessionDAO implements Sessio
super();
}
@Override
/*@Override
protected void doUpdate(Session session) {
if (session == null || session.getId() == null) {
return;
@@ -60,9 +62,9 @@ public class CacheSessionDAO extends EnterpriseCacheSessionDAO implements Sessio
}
super.doUpdate(session);
logger.debug("update {} {}", session.getId(), request != null ? request.getRequestURI() : "");
}
}*/
@Override
/*@Override
protected void doDelete(Session session) {
if (session == null || session.getId() == null) {
return;
@@ -70,7 +72,7 @@ public class CacheSessionDAO extends EnterpriseCacheSessionDAO implements Sessio
super.doDelete(session);
logger.debug("delete {} ", session.getId());
}
}*/
@Override
protected Serializable doCreate(Session session) {
@@ -127,7 +129,6 @@ public class CacheSessionDAO extends EnterpriseCacheSessionDAO implements Sessio
* @param includeLeave 是否包括离线最后访问时间大于3分钟为离线会话
* @return
*/
@Override
public Collection<Session> getActiveSessions(boolean includeLeave) {
return getActiveSessions(includeLeave, null, null);
}
@@ -139,7 +140,6 @@ public class CacheSessionDAO extends EnterpriseCacheSessionDAO implements Sessio
* @param filterSession 不为空,则过滤掉(不包含)这个会话。
* @return
*/
@Override
public Collection<Session> getActiveSessions(boolean includeLeave, Object principal, Session filterSession) {
// 如果包括离线,并无登录者条件。
if (includeLeave && principal == null){

View File

@@ -1,31 +1,38 @@
package com.nis.web.security;
import java.io.File;
import java.io.InputStream;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import javax.annotation.PostConstruct;
import org.apache.shiro.SecurityUtils;
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.credential.DefaultPasswordService;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authc.credential.PasswordService;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.Permission;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.codec.CodecSupport;
import org.apache.shiro.codec.Hex;
import org.apache.shiro.mgt.RealmSecurityManager;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.google.code.kaptcha.Constants;
import com.nis.domain.SysMenu;
import com.nis.domain.SysRole;
import com.nis.domain.SysUser;
@@ -34,8 +41,8 @@ import com.nis.util.Encodes;
import com.nis.util.LogUtils;
import com.nis.util.StringUtil;
import com.nis.util.StringUtils;
import com.nis.util.TreeUtil;
import com.nis.web.service.SystemService;
import com.sun.jna.platform.win32.Netapi32Util.User;
/**
@@ -82,7 +89,8 @@ public class SystemAuthorizingRealm extends AuthorizingRealm {
throw new AuthenticationException("msg:该已帐号禁止登录.");
}
byte[] salt = Encodes.decodeHex(user.getPassword().substring(0,16));
return new SimpleAuthenticationInfo(new Principal(user, token.isMobileLogin()), user.getPassword().substring(16), ByteSource.Util.bytes(salt), getName());
return new SimpleAuthenticationInfo(new Principal(user, token.isMobileLogin()), user.getPassword().substring(16), new MySimpleByteSource(salt), getName());
//return new SimpleAuthenticationInfo(new Principal(user, token.isMobileLogin()), user.getPassword().substring(16), ByteSource.Util.bytes(salt), getName());
}
return null;
}
@@ -194,14 +202,37 @@ public class SystemAuthorizingRealm extends AuthorizingRealm {
setCredentialsMatcher(matcher);
}
// /**
// * 清空用户关联权限认证,待下次使用时重新加载
// */
// public void clearCachedAuthorizationInfo(Principal principal) {
// SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, getName());
// clearCachedAuthorizationInfo(principals);
// }
/**
* 清空用户关联权限认证,待下次使用时重新加载
*/
public void clearCachedAuthorizationInfo(Principal principal) {
SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, getName());
clearCachedAuthorizationInfo(principals);
}
/**
* 清空用户关联权限认证,待下次使用时重新加载
*/
public void clearCachedAuthenticationInfo(Object principal) {
SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, getName());
clearCachedAuthenticationInfo(principals);
}
/**
* 清空用户关联权限认证,待下次使用时重新加载
*/
public void clearCachedAuthorizationInfoC(PrincipalCollection principals) {
SimplePrincipalCollection principalsa = new SimplePrincipalCollection(principals, getName());
clearCachedAuthorizationInfo(principalsa);
}
/*@Override
protected void clearCachedAuthenticationInfo(PrincipalCollection principals) {
// TODO Auto-generated method stub
super.clearCachedAuthenticationInfo(principals);
}
@Override
protected void clearCachedAuthorizationInfo(PrincipalCollection principals) {
// TODO Auto-generated method stub
super.clearCachedAuthorizationInfo(principals);
}*/
/**
* 授权用户信息
@@ -293,3 +324,107 @@ public class SystemAuthorizingRealm extends AuthorizingRealm {
}
}
class MySimpleByteSource implements ByteSource, Serializable {
private static final long serialVersionUID = 5175082362119580768L;
private byte[] bytes;
private String cachedHex;
private String cachedBase64;
public MySimpleByteSource(){
}
public MySimpleByteSource(byte[] bytes) {
this.bytes = bytes;
}
public MySimpleByteSource(char[] chars) {
this.bytes = CodecSupport.toBytes(chars);
}
public MySimpleByteSource(String string) {
this.bytes = CodecSupport.toBytes(string);
}
public MySimpleByteSource(ByteSource source) {
this.bytes = source.getBytes();
}
public MySimpleByteSource(File file) {
this.bytes = (new MySimpleByteSource.BytesHelper()).getBytes(file);
}
public MySimpleByteSource(InputStream stream) {
this.bytes = (new MySimpleByteSource.BytesHelper()).getBytes(stream);
}
public static boolean isCompatible(Object o) {
return o instanceof byte[] || o instanceof char[] || o instanceof String || o instanceof ByteSource || o instanceof File || o instanceof InputStream;
}
public void setBytes(byte[] bytes) {
this.bytes = bytes;
}
@Override
public byte[] getBytes() {
return this.bytes;
}
@Override
public String toHex() {
if(this.cachedHex == null) {
this.cachedHex = Hex.encodeToString(this.getBytes());
}
return this.cachedHex;
}
@Override
public String toBase64() {
if(this.cachedBase64 == null) {
this.cachedBase64 = Base64.encodeToString(this.getBytes());
}
return this.cachedBase64;
}
@Override
public boolean isEmpty() {
return this.bytes == null || this.bytes.length == 0;
}
@Override
public String toString() {
return this.toBase64();
}
@Override
public int hashCode() {
return this.bytes != null && this.bytes.length != 0? Arrays.hashCode(this.bytes):0;
}
@Override
public boolean equals(Object o) {
if(o == this) {
return true;
} else if(o instanceof ByteSource) {
ByteSource bs = (ByteSource)o;
return Arrays.equals(this.getBytes(), bs.getBytes());
} else {
return false;
}
}
private static final class BytesHelper extends CodecSupport {
private BytesHelper() {
}
public byte[] getBytes(File file) {
return this.toBytes(file);
}
public byte[] getBytes(InputStream stream) {
return this.toBytes(stream);
}
}
}

View File

@@ -24,7 +24,12 @@ import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.rpc.client.RPCServiceClient;
import org.apache.commons.io.FileUtils;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.session.Session;
import org.crazycake.shiro.exception.SerializationException;
import org.crazycake.shiro.serializer.ObjectSerializer;
import org.crazycake.shiro.serializer.RedisSerializer;
import org.crazycake.shiro.serializer.StringSerializer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -39,15 +44,19 @@ import com.nis.util.TimeConstants;
import com.nis.web.dao.SrcIpDao;
import com.nis.web.dao.SysOfficeDao;
import com.nis.web.dao.UserDao;
import com.nis.web.security.CacheSessionDAO;
import com.nis.web.security.Servlets;
import com.nis.web.security.SessionDAO;
import com.nis.web.security.UserUtils;
import antlr.StringUtils;
@Service
public class SystemService extends BaseService{
@Autowired
private SessionDAO sessionDao;
private CacheSessionDAO sessionDao;
/*private SessionDAO sessionDao;*/
@Autowired
private UserDao userDao;
@@ -57,7 +66,8 @@ public class SystemService extends BaseService{
@Autowired
private SrcIpDao srcIpDao;
private RedisSerializer keySerializer = new StringSerializer();
private RedisSerializer valueSerializer = new ObjectSerializer();
public Collection<Session> getActiveSessions(boolean includeLeave) {
return sessionDao.getActiveSessions(includeLeave);
@@ -72,6 +82,17 @@ public class SystemService extends BaseService{
sessionDao.delete(session);
}
public void deleteAuthenticationCache(String authenticationInfo) {
if (org.apache.commons.lang3.StringUtils.isBlank(authenticationInfo)) {
logger.error("AuthenticationInfo is null");
return;
}
try {
sessionDao.getRedisManager().del(keySerializer.serialize(authenticationInfo));
} catch (SerializationException e) {
logger.error("delete AuthenticationInfo error. AuthenticationInfo key=" + authenticationInfo);
}
}
public SysUser getUserByLoginName(String loginName) {
return UserUtils.getByLoginName(loginName);