session共享
登录缓存清理 缓存更换为redis缓存代码提交
This commit is contained in:
@@ -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";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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){
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user