diff options
| author | fangshunjian <[email protected]> | 2023-06-29 10:00:10 +0800 |
|---|---|---|
| committer | fangshunjian <[email protected]> | 2023-06-29 10:00:10 +0800 |
| commit | ca2f8e5f3d7d3a1cb563f89aa7de5eac69d83c95 (patch) | |
| tree | 25419b65ec455bc3d152eafe635254bb256bfe98 | |
| parent | 0b2c961471085bf0c177246e6cc455eb81908fab (diff) | |
fix: NEZ-2918 shiro 统一通过单例redisTemplate操作
12 files changed, 342 insertions, 718 deletions
diff --git a/nz-admin/src/main/java/com/nis/common/config/RedisConfig.java b/nz-admin/src/main/java/com/nis/common/config/RedisConfig.java index bb8f6ee9..49840bbf 100644 --- a/nz-admin/src/main/java/com/nis/common/config/RedisConfig.java +++ b/nz-admin/src/main/java/com/nis/common/config/RedisConfig.java @@ -9,7 +9,6 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.dao.DataAccessException; -import org.springframework.data.redis.connection.RedisConfiguration; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisNode; @@ -53,9 +52,9 @@ public class RedisConfig { @Value("${nezha.inited:0}") private int inited; // redis sentinel配置项 - @Value("${redis.sentinel.master}") + @Value("${redis.sentinel.master:}") private String sentinelMaster; - @Value("${redis.sentinel.nodes}") + @Value("${redis.sentinel.nodes:}") private String sentinelNodes; /** * redis配置项 diff --git a/nz-admin/src/main/java/com/nis/common/config/ShiroConfig.java b/nz-admin/src/main/java/com/nis/common/config/ShiroConfig.java index 0853bb5b..9b2927ef 100644 --- a/nz-admin/src/main/java/com/nis/common/config/ShiroConfig.java +++ b/nz-admin/src/main/java/com/nis/common/config/ShiroConfig.java @@ -1,25 +1,25 @@ package com.nis.common.config; -import Aladdin.HaspStatus; -import cn.hutool.core.util.StrUtil; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.nis.common.interceptor.TokenCheckFilter; -import com.nis.common.utils.*; -import com.nis.modules.metric.dto.NezhaMetrics; -import com.nis.modules.sys.dao.SysApiKeyDao; -import com.nis.modules.sys.dao.SysUserDao; -import com.nis.modules.sys.entity.SysConfigEntity; -import com.nis.modules.sys.service.LicenseService; -import com.nis.modules.sys.service.SysConfigService; -import com.nis.modules.sys.shiro.*; -import io.micrometer.core.instrument.MeterRegistry; +import java.nio.charset.Charset; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import javax.servlet.Filter; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletResponse; + import org.apache.catalina.connector.Connector; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.session.mgt.SessionManager; import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.filter.AccessControlFilter; +import org.apache.shiro.web.filter.authc.AuthenticatingFilter; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; +import org.crazycake.shiro.IRedisManager; import org.crazycake.shiro.RedisCacheManager; import org.crazycake.shiro.RedisSessionDAO; import org.springframework.beans.factory.annotation.Autowired; @@ -31,55 +31,59 @@ import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerF import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; -import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.ValueOperations; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; -import javax.servlet.Filter; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletResponse; -import java.util.LinkedHashMap; -import java.util.Map; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.nis.common.interceptor.TokenCheckFilter; +import com.nis.common.utils.Constant; +import com.nis.common.utils.R; +import com.nis.common.utils.RCode; +import com.nis.common.utils.Tool; +import com.nis.common.utils.ToolUtil; +import com.nis.modules.metric.dto.NezhaMetrics; +import com.nis.modules.sys.dao.SysApiKeyDao; +import com.nis.modules.sys.dao.SysUserDao; +import com.nis.modules.sys.entity.SysConfigEntity; +import com.nis.modules.sys.service.LicenseService; +import com.nis.modules.sys.service.SysConfigService; +import com.nis.modules.sys.shiro.MySessionManager; +import com.nis.modules.sys.shiro.ShiroUtils; +import com.nis.modules.sys.shiro.UserRealm; + +import Aladdin.HaspStatus; +import cn.hutool.core.util.StrUtil; +import io.micrometer.core.instrument.MeterRegistry; /** * Shiro的配置文件 + * */ @Configuration @DependsOn(value = { "mybatisPlusConfig", "redisConfig" }) public class ShiroConfig { - @Value("${compileType:release}") - private String compileType; - - @Value("${vendorCode}") - private String vendorCode; - @Autowired - private LicenseService licenseService; + private RedisTemplate<String,String> redisTemplate; @Autowired private SysConfigService sysconfigService; - @Autowired - private SysUserDao sysUserDao; - - @Autowired - private SysApiKeyDao sysApiKeyDao; - + @Value("${compileType:release}") + private String compileType; + @Value("${vendorCode}") + private String vendorCode; @Autowired private NezhaMetrics nezhaMetrics; @Autowired private MeterRegistry meterRegistry; - @Autowired - private RedisTemplate<String, String> redisTemplate; - + private LicenseService licenseService; @Autowired - private RedisConnectionFactory redisConnectionFactory; - + private TokenCheckFilter tokenCheckFilter; @Bean("shiroFilter") public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) { ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean(); @@ -88,10 +92,9 @@ public class ShiroConfig { shiroFilter.setUnauthorizedUrl("/"); Map<String, String> filterMap = new LinkedHashMap<>(); - - + /* - * 静态资源 + * 静态资源 */ filterMap.put("/", "anon"); filterMap.put("/static/**", "anon"); @@ -101,37 +104,35 @@ public class ShiroConfig { filterMap.put("/**/*.jpg", "anon"); filterMap.put("/**/*.css", "anon"); filterMap.put("/**/*.ico", "anon"); - + /* * 开放权限接口 */ filterMap.put("/sys/login", "anon"); // 登录接口 filterMap.put("/api/**", "anon"); // 告警消息接收 接口 - filterMap.put("/sys/i18n/lang", "anon"); //国际化文件获取接口 + filterMap.put("/sys/i18n/lang", "anon"); // 国际化文件获取接口 filterMap.put("/mfa/**", "anon"); // mfa 认证接口 - filterMap.put("/healthy", "anon"); //健康检查接口 - filterMap.put("/buildInfo", "anon"); //编译信息查询接口 - filterMap.put("/terminal.ws", "anon"); //terminal websocket 接口 - filterMap.put("/terminal/monitor.ws", "anon"); //terminal/monitor websocket 接口 + filterMap.put("/healthy", "anon"); // 健康检查接口 + filterMap.put("/buildInfo", "anon"); // 编译信息查询接口 + filterMap.put("/terminal.ws", "anon"); // terminal websocket 接口 + filterMap.put("/terminal/monitor.ws", "anon"); // terminal/monitor websocket 接口 filterMap.put("/sys/license/**", "anon");// license 相关接口 filterMap.put("/monitor/project/topo/icon/**", "anon"); // topo icon 相关接口 filterMap.put("/setup/**", "anon");// 程序配置 相关接口 - filterMap.put("/sys/appearance","anon"); //系统外观配置查询接口 - filterMap.put("/ctl/**","anon"); //管理员账号密码重置接口 + filterMap.put("/sys/appearance", "anon"); // 系统外观配置查询接口 + filterMap.put("/ctl/**", "anon"); // 管理员账号密码重置接口 filterMap.put("/ui/**", "anon"); // UI 接口 filterMap.put("/topology/**", "anon"); // topology 接口 filterMap.put("/file/download/**", "anon"); // 文件下载接口 - + /* * 自定义 过滤器 */ - filterMap.put("/actuator/prometheus", "metricsFilter"); //prometheus metrics + filterMap.put("/actuator/prometheus", "metricsFilter"); // prometheus metrics filterMap.put("/actuator/**", "anon"); // 诊断接口 filterMap.put("/**", "tokenCheckFilter,licenseFilter"); - Integer loginExpiration = getTimeOutData(); Map<String, Filter> cumstomFilterMap = new LinkedHashMap<String, Filter>(); - TokenCheckFilter tokenCheckFilter = new TokenCheckFilter(redisTemplate, loginExpiration, sysUserDao,sysApiKeyDao); LicenseShiroFilter licenseShiroFilter = new LicenseShiroFilter(); MetricsShiroFilter metricsShiroFilter = new MetricsShiroFilter(); cumstomFilterMap.put("tokenCheckFilter", tokenCheckFilter); @@ -139,26 +140,27 @@ public class ShiroConfig { cumstomFilterMap.put("metricsFilter", metricsShiroFilter); shiroFilter.setFilters(cumstomFilterMap); shiroFilter.setFilterChainDefinitionMap(filterMap); - + return shiroFilter; } @Component public class LicenseShiroFilter extends AccessControlFilter { - + @Override protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception { // debug 模式不校验 license - if(Tool.StrUtil.equalsIgnoreCase(compileType, "debug")) { + if (Tool.StrUtil.equalsIgnoreCase(compileType, "debug")) { return true; } - + Integer status = licenseService.verify(); - if( ! Tool.NumberUtil.equals(status, HaspStatus.HASP_STATUS_OK)) { - HttpServletResponse httpResponse=(HttpServletResponse) response; + if (!Tool.NumberUtil.equals(status, HaspStatus.HASP_STATUS_OK)) { + HttpServletResponse httpResponse = (HttpServletResponse) response; httpResponse.setStatus(HttpStatus.FORBIDDEN.value()); - httpResponse.getWriter().write(Tool.JSONUtil.toJsonStr(R.error(RCode.LICENSE_FILE_INVALID.setParam(status)))); + httpResponse.getWriter() + .write(Tool.JSONUtil.toJsonStr(R.error(RCode.LICENSE_FILE_INVALID.setParam(status)))); return false; } return true; @@ -170,21 +172,21 @@ public class ShiroConfig { } } - + public class MetricsShiroFilter extends AccessControlFilter { - @Override - protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o) throws Exception { - nezhaMetrics.bindTo(meterRegistry); - return true; - } - - @Override - protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { - return false; - } + @Override + protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o) + throws Exception { + nezhaMetrics.bindTo(meterRegistry); + return true; + } + + @Override + protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception { + return false; + } } - - + @Bean @ConditionalOnExpression("${nezha.shiroPermisSupport:true}") public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) { @@ -213,8 +215,9 @@ public class ShiroConfig { * * @return */ - public MyRedisManager redisManager() { - MyRedisManager redisManager = new MyRedisManager(redisConnectionFactory); + @Bean + public IRedisManager redisManager() { + RedisManager redisManager = new RedisManager(redisTemplate); return redisManager; } @@ -242,7 +245,7 @@ public class ShiroConfig { @Bean public RedisSessionDAO redisSessionDAO() { Integer loginExpiration = getTimeOutData(); - MyRedisSessionDAO redisSessionDAO = new MyRedisSessionDAO(); + RedisSessionDAO redisSessionDAO = new RedisSessionDAO(); redisSessionDAO.setRedisManager(redisManager()); redisSessionDAO.setExpire(loginExpiration * 60); redisSessionDAO.setKeyPrefix(ShiroUtils.REDIS_KEYPREFIX); @@ -301,4 +304,53 @@ public class ShiroConfig { } return loginExpiration; } -} + + /** + * 自定义 redis manager + * @author ThinkPad + * + */ + public static class RedisManager implements IRedisManager { + private RedisTemplate<String, String> redisTemplate; + + public RedisManager(RedisTemplate<String, String> redisTemplate) { + this.redisTemplate = redisTemplate; + } + + @Override + public byte[] get(byte[] key) { + ValueOperations<String, String> opsForValue = redisTemplate.opsForValue(); + String v = opsForValue.get(Tool.StrUtil.str(key, "UTF-8")); + return Tool.HexUtil.decodeHex(v); + } + + @Override + public byte[] set(byte[] key, byte[] value, int expire) { + ValueOperations<String, String> opsForValue = redisTemplate.opsForValue(); + opsForValue.set(Tool.StrUtil.str(key, "UTF-8"), Tool.HexUtil.encodeHexStr(value), expire, TimeUnit.SECONDS); + return value; + } + + @Override + public void del(byte[] key) { + redisTemplate.delete(Tool.StrUtil.str(key, "UTF-8")); + } + + @Override + public Long dbSize(byte[] pattern) { + return (long)redisTemplate.keys(Tool.StrUtil.str(pattern, "UTF-8")).size(); + } + + @Override + public Set<byte[]> keys(byte[] pattern) { + Set<String> set = redisTemplate.keys(Tool.StrUtil.str(pattern, "UTF-8")); + if(Tool.CollUtil.isEmpty(set)) { + return null; + } + Set<byte[]> keys = Tool.CollUtil.newHashSet(); + set.forEach( k -> keys.add(Tool.StrUtil.bytes(k,"UTF-8"))); + return keys; + } + + } +}
\ No newline at end of file diff --git a/nz-admin/src/main/java/com/nis/common/interceptor/TokenCheckFilter.java b/nz-admin/src/main/java/com/nis/common/interceptor/TokenCheckFilter.java index fbc35adf..2cd89086 100644 --- a/nz-admin/src/main/java/com/nis/common/interceptor/TokenCheckFilter.java +++ b/nz-admin/src/main/java/com/nis/common/interceptor/TokenCheckFilter.java @@ -1,187 +1,127 @@ package com.nis.common.interceptor; -import com.alibaba.fastjson.JSON; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; -import com.nis.common.utils.Constant; -import com.nis.common.utils.DateUtils; -import com.nis.common.utils.R; -import com.nis.common.utils.RCode; -import com.nis.common.utils.SpringContextUtils; -import com.nis.common.utils.Tool; -import com.nis.common.utils.ToolUtil; -import com.nis.modules.sys.dao.SysApiKeyDao; -import com.nis.modules.sys.dao.SysUserDao; -import com.nis.modules.sys.entity.SysApiKey; -import com.nis.modules.sys.entity.SysUserEntity; -import com.nis.modules.sys.shiro.ShiroUtils; +import java.util.Date; -import cn.hutool.core.date.DateUnit; -import cn.hutool.core.date.DateUtil; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; -import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.apache.shiro.SecurityUtils; -import org.apache.shiro.authc.SimpleAuthenticationInfo; -import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.session.Session; import org.apache.shiro.session.mgt.SimpleSession; -import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.subject.SimplePrincipalCollection; import org.apache.shiro.subject.Subject; import org.apache.shiro.subject.support.DefaultSubjectContext; -import org.apache.shiro.util.ByteSource; import org.apache.shiro.util.ThreadContext; import org.apache.shiro.web.filter.AccessControlFilter; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.core.ValueOperations; -import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; -import org.springframework.data.redis.serializer.StringRedisSerializer; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.nis.common.utils.Constant; +import com.nis.common.utils.R; +import com.nis.common.utils.RCode; +import com.nis.common.utils.Tool; +import com.nis.common.utils.ToolUtil; +import com.nis.modules.sys.dao.SysApiKeyDao; +import com.nis.modules.sys.entity.SysApiKey; +import com.nis.modules.sys.entity.SysUserEntity; +import com.nis.modules.sys.shiro.ShiroUtils; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.TimeUnit; +import cn.hutool.core.date.DateUnit; +import cn.hutool.core.date.DateUtil; +@Component public class TokenCheckFilter extends AccessControlFilter { - private Integer loginExpiration; - private SysUserDao sysUserDao; - private RedisTemplate<String, String> redisTemplate; - private SysApiKeyDao sysApiKeyDao; - - public TokenCheckFilter(RedisTemplate redisTemplate) { - this.redisTemplate = redisTemplate; - } - - public TokenCheckFilter(RedisTemplate redisTemplate, Integer loginExpiration) { - this.redisTemplate = redisTemplate; - this.loginExpiration = loginExpiration; - } - - public TokenCheckFilter(RedisTemplate redisTemplate, Integer loginExpiration, SysUserDao sysUserDao, SysApiKeyDao sysApiKeyDao) { - this.redisTemplate = redisTemplate; - this.loginExpiration = loginExpiration; - this.sysUserDao = sysUserDao; - this.sysApiKeyDao = sysApiKeyDao; - } - + @Autowired + private SysApiKeyDao sysApiKeyDao; -// @Override -// protected boolean preHandle(ServletRequest req, ServletResponse resp) throws Exception { -// HttpServletRequest request=(HttpServletRequest) req; -// HttpServletResponse response=(HttpServletResponse)resp; -// //跨域请求标志 -// String origin = request.getHeader("Origin"); -// if(StringUtils.isNotBlank(origin)){ -// response.setHeader("Access-Control-Allow-Origin",origin); -// response.setHeader("Access-Control-Allow-Credentials","true"); -// } -// -// return super.preHandle(request, response); -// } + public TokenCheckFilter() { - @Override - protected boolean isAccessAllowed(ServletRequest req, ServletResponse resp, Object o) throws Exception { - HttpServletRequest request = (HttpServletRequest) req; - HttpServletResponse response = (HttpServletResponse) resp; - String requestToken = request.getHeader(Constant.AUTH_TOKEN_CODE); - if (StringUtils.isBlank(requestToken)) { - requestToken = request.getParameter(Constant.AUTH_TOKEN_CODE); - } - if (StringUtils.isBlank(requestToken)) { - response.getWriter().write(JSON.toJSON(R.error(RCode.SYS_LOGIN_REQUIRED)).toString()); - return false; - } - - Boolean exist = redisTemplate.hasKey(ShiroUtils.REDIS_KEYPREFIX + requestToken); - if (exist) { - SysUserEntity userEntity = ShiroUtils.getUserEntity(); - if(Tool.ObjectUtil.isNull(userEntity) ) { - return false; - } - if(ToolUtil.equals(userEntity.getId(), 0L)) { - // 第三方api key登录 - return true; - } - // 重新查询数据库 - SysUserEntity entity = this.sysUserDao.selectById(ShiroUtils.getUserEntity().getId()); - if (entity.getStatus() == 0) { - response.getWriter().write(JSON.toJSON(R.error(RCode.SYS_LOGIN_LOCK)).toString()); - return false; - } - // key 存在 证明验证成功,刷新过期时间 - redisTemplate.expire(requestToken, this.loginExpiration, TimeUnit.MINUTES); - return true; - } else { - Date now = new Date(); - String time = DateUtil.format(now , "yyyy-MM-dd hh:mm:ss"); - // 查询sys_api_key是否有该token记录 - SysApiKey apiKey = sysApiKeyDao.selectOne(new QueryWrapper<SysApiKey>().lambda().eq(SysApiKey::getToken, requestToken) - .and(wrapper -> wrapper.ge(SysApiKey::getExpireAt,time).or().isNull(SysApiKey::getExpireAt))); - // 如果有的话则认证通过 同时将该值存放到redis里 - if(ToolUtil.isEmpty(apiKey)) { - // 如果没有则 返回响应值 - response.getWriter().write(JSON.toJSON(R.error(RCode.SYS_LOGIN_REQUIRED)).toString()); - return false; - }else { - RedisConnectionFactory factory = SpringContextUtils.getBean("redisConnectionFactory", RedisConnectionFactory.class); - RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); - redisTemplate.setKeySerializer(new StringRedisSerializer()); - redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer()); - redisTemplate.setConnectionFactory(factory); - redisTemplate.afterPropertiesSet(); - - - //获取存在缓存中的过期时间 - Date expireAt = apiKey.getExpireAt(); - - SimpleSession session = new SimpleSession(); - SysUserEntity user = new SysUserEntity(); - user.setApiKeyId(apiKey.getId()); - user.setId(0L); - user.setName(apiKey.getName()); - SimplePrincipalCollection primaryPrincipal =new SimplePrincipalCollection(user,""); - session.setAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY, primaryPrincipal); - session.setId(apiKey.getToken()); - - if(!ToolUtil.isEmpty(expireAt)){ - long seconds = DateUtil.between(now, expireAt, DateUnit.SECOND); - redisTemplate.opsForValue().set(ShiroUtils.REDIS_KEYPREFIX + requestToken, session,seconds,TimeUnit.SECONDS); - }else{ - redisTemplate.opsForValue().set(ShiroUtils.REDIS_KEYPREFIX + requestToken, session); - } - - DefaultSubjectContext context =new DefaultSubjectContext(); - context.setSession(session); - SecurityManager securityManager = SecurityUtils.getSecurityManager(); - Subject subject = securityManager.createSubject(context); - ThreadContext.bind(subject); - return true; - } - } - } + } - public Integer getLoginExpiration() { - return loginExpiration; + @Override + protected boolean isAccessAllowed(ServletRequest req, ServletResponse resp, Object o) throws Exception { + HttpServletRequest request = (HttpServletRequest) req; + HttpServletResponse response = (HttpServletResponse) resp; + String requestToken = request.getHeader(Constant.AUTH_TOKEN_CODE); + if (StringUtils.isBlank(requestToken)) { + requestToken = request.getParameter(Constant.AUTH_TOKEN_CODE); + } + if (StringUtils.isBlank(requestToken)) { + response.getWriter().write(JSON.toJSON(R.error(RCode.SYS_LOGIN_REQUIRED)).toString()); + return false; + } + + Session session = ShiroUtils.getSessionById(requestToken); + if (Tool.ObjectUtil.isNotNull(session)) { + SysUserEntity userEntity = ShiroUtils.getUserEntity(); + if (Tool.ObjectUtil.isNull(userEntity)) { + return false; + } + return true; + } else { + boolean login = this.apiKeyLogin(requestToken); + if(!login) { + response.getWriter().write(JSON.toJSON(R.error(RCode.SYS_LOGIN_REQUIRED)).toString()); + } + return login; + } } - public void setLoginExpiration(Integer loginExpiration) { - this.loginExpiration = loginExpiration; + /** + * 验证 apikey 登录 + * @param token + * @return + */ + private boolean apiKeyLogin(String token) { + Date now = new Date(); + String time = DateUtil.format(now, "yyyy-MM-dd hh:mm:ss"); + // 查询sys_api_key是否有该token记录 + SysApiKey apiKey = sysApiKeyDao.selectOne(new QueryWrapper<SysApiKey>().lambda().eq(SysApiKey::getToken, token).and( + wrapper -> wrapper.ge(SysApiKey::getExpireAt, time).or().isNull(SysApiKey::getExpireAt))); + // 如果有的话则认证通过 同时将该值存放到redis里 + if (ToolUtil.isEmpty(apiKey)) { + // 如果没有则 返回响应值 + return false; + } else { + // 获取存在缓存中的过期时间 + Date expireAt = apiKey.getExpireAt(); + SimpleSession session = new SimpleSession(); + SysUserEntity user = new SysUserEntity(); + user.setApiKeyId(apiKey.getId()); + user.setId(0L); + user.setName(apiKey.getName()); + SimplePrincipalCollection primaryPrincipal = new SimplePrincipalCollection(user, ""); + session.setAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY, primaryPrincipal); + session.setId(apiKey.getToken()); + // 设置超时时间 + if (!ToolUtil.isEmpty(expireAt)) { + long ms = DateUtil.between(now, expireAt, DateUnit.MS); + session.setTimeout(ms); + } else { + session.setTimeout(Integer.MAX_VALUE); + } + // 手动保存 session 信息 + ShiroUtils.updateSession(session); + DefaultSubjectContext context = new DefaultSubjectContext(); + context.setSession(session); + SecurityManager securityManager = SecurityUtils.getSecurityManager(); + Subject subject = securityManager.createSubject(context); + ThreadContext.bind(subject); + return true; + } + } @Override - protected boolean onAccessDenied(ServletRequest req, ServletResponse resp) throws Exception { + protected boolean onAccessDenied(ServletRequest req, ServletResponse resp) throws Exception { - return false; - } + return false; + } } diff --git a/nz-admin/src/main/java/com/nis/common/thread/RedisCacheSubscribe.java b/nz-admin/src/main/java/com/nis/common/thread/RedisCacheSubscribe.java index ec03aa2c..f18ce055 100644 --- a/nz-admin/src/main/java/com/nis/common/thread/RedisCacheSubscribe.java +++ b/nz-admin/src/main/java/com/nis/common/thread/RedisCacheSubscribe.java @@ -84,7 +84,7 @@ public class RedisCacheSubscribe implements MessageListener{ TokenCheckFilter filter = (TokenCheckFilter) filters.get("tokenCheckFilter"); // Integer loginExpiration = filter.getLoginExpiration(); // System.out.println(loginExpiration); - filter.setLoginExpiration(Integer.valueOf(sessionTimeOut)); +// filter.setLoginExpiration(Integer.valueOf(sessionTimeOut)); redisCacheManager.setExpire(Integer.valueOf(sessionTimeOut) * 60); redisSessionDao.setExpire(Integer.valueOf(sessionTimeOut) * 60); mySessionManager.setGlobalSessionTimeout(Integer.valueOf(sessionTimeOut) * 60 * 1000); diff --git a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysApiKeyServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysApiKeyServiceImpl.java index 18aac459..4ed2d6c2 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysApiKeyServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysApiKeyServiceImpl.java @@ -65,9 +65,9 @@ public class SysApiKeyServiceImpl extends ServiceImpl<SysApiKeyDao,SysApiKey> im List<SysApiKey> sysApiKeys = this.list(new QueryWrapper<SysApiKey>().lambda().in(SysApiKey::getId, Arrays.asList(ids.split(",")))); List<String> tokens = new ArrayList<String>(); for(SysApiKey sysApiKey : sysApiKeys) { - tokens.add(StrUtil.str(ShiroUtils.REDIS_KEYPREFIX+sysApiKey.getToken())); + tokens.add(sysApiKey.getToken()); } - ShiroUtils.removeRedisCacheByToken(tokens); + ShiroUtils.deleteSession(tokens); this.removeByIds(Arrays.asList(ids.split(","))); } @@ -122,8 +122,8 @@ public class SysApiKeyServiceImpl extends ServiceImpl<SysApiKeyDao,SysApiKey> im .eq(SysApiKey::getCreateBy, ShiroUtils.getUserId().intValue()) ); // 删除 redis 中 api key - List<String> tokens = sysApiKeys.stream().map(k -> ShiroUtils.REDIS_KEYPREFIX + k.getToken()).collect(Collectors.toList()); - ShiroUtils.removeRedisCacheByToken(tokens); + List<String> tokens = sysApiKeys.stream().map(k -> k.getToken()).collect(Collectors.toList()); + ShiroUtils.deleteSession(tokens); List<Integer> removeIds = sysApiKeys.stream().map(SysApiKey::getId).collect(Collectors.toList()); this.removeByIds(removeIds); diff --git a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysRoleServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysRoleServiceImpl.java index cc549b4f..a6ce4b59 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysRoleServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysRoleServiceImpl.java @@ -177,7 +177,7 @@ public class SysRoleServiceImpl extends ServiceImpl<SysRoleDao, SysRoleEntity> i } finally { // 删除 关联key if (CollectionUtils.isNotEmpty(removeKeys)) { - redisTemplate.delete(removeKeys); + ShiroUtils.deleteSession(removeKeys); } } } diff --git a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysUserServiceImpl.java b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysUserServiceImpl.java index 1144f83f..7c4f9f7e 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysUserServiceImpl.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/service/impl/SysUserServiceImpl.java @@ -1,8 +1,35 @@ package com.nis.modules.sys.service.impl; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.log.Log; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang.ArrayUtils; +import org.apache.commons.lang.RandomStringUtils; +import org.apache.commons.lang.StringUtils; +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.session.Session; +import org.apache.shiro.subject.PrincipalCollection; +import org.apache.shiro.subject.support.DefaultSubjectContext; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.ValueOperations; +import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -12,7 +39,13 @@ import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.nis.common.exception.NZException; import com.nis.common.smartvalidate.ValidateUtils; -import com.nis.common.utils.*; +import com.nis.common.utils.CommonUtils; +import com.nis.common.utils.Constant; +import com.nis.common.utils.PageUtils; +import com.nis.common.utils.Query; +import com.nis.common.utils.RCode; +import com.nis.common.utils.Tool; +import com.nis.common.utils.ToolUtil; import com.nis.modules.alert.dao.AlertRuleDao; import com.nis.modules.alert.entity.AlertRuleEntity; import com.nis.modules.alert.service.AlertRuleService; @@ -27,29 +60,17 @@ import com.nis.modules.sys.entity.SysApiKey; import com.nis.modules.sys.entity.SysRoleEntity; import com.nis.modules.sys.entity.SysUserEntity; import com.nis.modules.sys.entity.SysUserRoleEntity; -import com.nis.modules.sys.service.*; +import com.nis.modules.sys.service.SysApiKeyService; +import com.nis.modules.sys.service.SysConfigService; +import com.nis.modules.sys.service.SysMenuService; +import com.nis.modules.sys.service.SysRoleService; +import com.nis.modules.sys.service.SysUserRoleService; +import com.nis.modules.sys.service.SysUserService; import com.nis.modules.sys.shiro.ShiroUtils; -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.lang.ArrayUtils; -import org.apache.commons.lang.RandomStringUtils; -import org.apache.commons.lang.StringUtils; -import org.apache.shiro.SecurityUtils; -import org.apache.shiro.session.mgt.SimpleSession; -import org.apache.shiro.subject.SimplePrincipalCollection; -import org.apache.shiro.subject.support.DefaultSubjectContext; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.core.ValueOperations; -import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; -import org.springframework.data.redis.serializer.StringRedisSerializer; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import javax.servlet.http.HttpServletRequest; -import java.util.*; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.log.Log; @Service("sysUserService") public class SysUserServiceImpl extends ServiceImpl<SysUserDao, SysUserEntity> implements SysUserService { @@ -116,17 +137,17 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserDao, SysUserEntity> i } // 获取缓存中登录的用户 Map<String, SysUserEntity> shiroSessionInfoMap = ShiroUtils.getShiroSessionInfoMap(); - List<SysUserEntity> users = new ArrayList<SysUserEntity>(shiroSessionInfoMap.values()); + List<Long> loginUserIds = Tool.CollUtil.newArrayList(); + shiroSessionInfoMap.values().forEach( u -> { + loginUserIds.add(u.getId()); + }); for (SysUserEntity userEntity : userList) { - for (SysUserEntity user : users) { - if (user.getId().equals(userEntity.getId())){ - //在线 - userEntity.setOnline(1); - break; - }else { - //离线 - userEntity.setOnline(0); - } + if (loginUserIds.contains(userEntity.getId())){ + //在线 + userEntity.setOnline(1); + }else { + //离线 + userEntity.setOnline(0); } List<SysUserRoleEntity> userRoleEntities = userRoleMap.get(userEntity.getId().intValue()); if (CollectionUtils.isEmpty(userRoleEntities)) { @@ -290,7 +311,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserDao, SysUserEntity> i } finally { // 删除 关联key if (CollectionUtils.isNotEmpty(removeKeys)) { - redisTemplate.delete(removeKeys); + ShiroUtils.deleteSession(removeKeys); } } } @@ -384,7 +405,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserDao, SysUserEntity> i } finally { // 删除 关联key if (CollectionUtils.isNotEmpty(removeKeys)) { - redisTemplate.delete(removeKeys); + ShiroUtils.deleteSession(removeKeys); } } } @@ -393,24 +414,14 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserDao, SysUserEntity> i public Map<String, Object> getUserPermissions(HttpServletRequest request) { String requestToken = request.getHeader(Constant.AUTH_TOKEN_CODE); requestToken = StringUtils.isEmpty(requestToken) ? request.getParameter(Constant.AUTH_TOKEN_CODE) : requestToken; - if (StringUtils.isEmpty(requestToken)) + if (StringUtils.isEmpty(requestToken)) { throw new NZException(RCode.SYS_TOKEN_ISNULL); - - RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); - redisTemplate.setKeySerializer(new StringRedisSerializer()); - redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer()); - redisTemplate.setConnectionFactory(factory); - - redisTemplate.afterPropertiesSet(); - - Boolean exist = redisTemplate.hasKey(ShiroUtils.REDIS_KEYPREFIX + requestToken); - if (!exist) + } + Session session = ShiroUtils.getSessionById(requestToken); + if(Tool.ObjectUtil.isNull(session)) { throw new NZException(RCode.SYS_LOGIN_REQUIRED); - - ValueOperations ops = redisTemplate.opsForValue(); - Object obj = ops.get(ShiroUtils.REDIS_KEYPREFIX + requestToken); - SimpleSession session = (SimpleSession) obj; - SimplePrincipalCollection primaryPrincipal = (SimplePrincipalCollection) session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY); + } + PrincipalCollection primaryPrincipal = (PrincipalCollection) session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY); SysUserEntity userEntity = (SysUserEntity) primaryPrincipal.getPrimaryPrincipal(); SysUserEntity user = this.getById(userEntity.getId()); diff --git a/nz-admin/src/main/java/com/nis/modules/sys/shiro/MyRedisManager.java b/nz-admin/src/main/java/com/nis/modules/sys/shiro/MyRedisManager.java deleted file mode 100644 index 98271bf5..00000000 --- a/nz-admin/src/main/java/com/nis/modules/sys/shiro/MyRedisManager.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.nis.modules.sys.shiro; - -import com.nis.common.utils.Tool; -import org.apache.shiro.session.Session; -import org.crazycake.shiro.IRedisManager; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.data.redis.core.ValueOperations; -import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; -import org.springframework.data.redis.serializer.StringRedisSerializer; - -import java.util.Set; -import java.util.concurrent.TimeUnit; - -/** - * 自定义 redis manager - * - * @author ThinkPad - */ -public class MyRedisManager implements IRedisManager { - - private RedisTemplate<String, Object> redisTemplate; - - public MyRedisManager(RedisConnectionFactory factory) { - redisTemplate = new RedisTemplate<>(); - - redisTemplate.setKeySerializer(new StringRedisSerializer()); - redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer()); - - redisTemplate.setConnectionFactory(factory); - redisTemplate.afterPropertiesSet(); - } - - @Override - public byte[] get(byte[] key) { - return null; - } - - @Override - public byte[] set(byte[] key, byte[] value, int expire) { - return null; - } - - @Override - public void del(byte[] key) { - } - - @Override - public Long dbSize(byte[] pattern) { - return 16L; - } - - @Override - public Set<byte[]> keys(byte[] pattern) { - return Tool.CollUtil.newHashSet(); - } - - public Object get(String key) { - ValueOperations<String, Object> valueOperations = this.redisTemplate.opsForValue(); - return valueOperations.get(key); - } - - public Session set(String key, Session value, int expire) { - ValueOperations<String, Object> opsForValue = this.redisTemplate.opsForValue(); - opsForValue.set(key, value, expire, TimeUnit.SECONDS); - return value; - } - - public void del(String key) { - this.redisTemplate.delete(key); - } - - public Set<String> keys(String pattern) { - return this.redisTemplate.keys(pattern); - } -} diff --git a/nz-admin/src/main/java/com/nis/modules/sys/shiro/MyRedisSessionDAO.java b/nz-admin/src/main/java/com/nis/modules/sys/shiro/MyRedisSessionDAO.java deleted file mode 100644 index 8fedc6aa..00000000 --- a/nz-admin/src/main/java/com/nis/modules/sys/shiro/MyRedisSessionDAO.java +++ /dev/null @@ -1,305 +0,0 @@ -package com.nis.modules.sys.shiro; - -import cn.hutool.log.Log; -import org.apache.shiro.session.Session; -import org.apache.shiro.session.UnknownSessionException; -import org.apache.shiro.session.mgt.eis.SessionDAO; -import org.crazycake.shiro.IRedisManager; -import org.crazycake.shiro.RedisSessionDAO; -import org.crazycake.shiro.common.SessionInMemory; -import org.springframework.data.redis.serializer.SerializationException; - -import java.io.Serializable; -import java.util.*; - -public class MyRedisSessionDAO extends RedisSessionDAO implements SessionDAO { - - private static final Log logger = Log.get(); - - private static final String DEFAULT_SESSION_KEY_PREFIX = "shiro:session:"; - private String keyPrefix = "shiro:session:"; - private static final long DEFAULT_SESSION_IN_MEMORY_TIMEOUT = 1000L; - private long sessionInMemoryTimeout = 1000L; - private static final boolean DEFAULT_SESSION_IN_MEMORY_ENABLED = true; - private boolean sessionInMemoryEnabled = true; - private static ThreadLocal sessionsInThread = new ThreadLocal(); - private static final int DEFAULT_EXPIRE = -2; - private static final int NO_EXPIRE = -1; - private int expire = -2; - private static final int MILLISECONDS_IN_A_SECOND = 1000; - private MyRedisManager redisManager; - - public MyRedisSessionDAO() { - } - - @Override - public void update(Session session) throws UnknownSessionException { - if (this.sessionInMemoryEnabled) { - this.removeExpiredSessionInMemory(); - } - - this.saveSession(session); - if (this.sessionInMemoryEnabled) { - this.setSessionToThreadLocal(session.getId(), session); - } - - } - - private void saveSession(Session session) throws UnknownSessionException { - if (session != null && session.getId() != null) { - String key; - Session value; - try { - key = this.getRedisSessionKey(session.getId()); - value = session; - } catch (SerializationException var5) { - logger.error("serialize session error. session id=" + session.getId()); - throw new UnknownSessionException(var5); - } - - if (this.expire == -2) { - this.redisManager.set(key, value, (int) (session.getTimeout() / 1000L)); - } else { - if (this.expire != -1 && (long) (this.expire * 1000) < session.getTimeout()) { - logger.warn("Redis session expire time: " + this.expire * 1000 + " is less than Session timeout: " + session.getTimeout() + " . It may cause some problems."); - } - - this.redisManager.set(key, value, this.expire); - } - } else { - logger.error("session or session id is null"); - throw new UnknownSessionException("session or session id is null"); - } - } - - @Override - public void delete(Session session) { - if (this.sessionInMemoryEnabled) { - this.removeExpiredSessionInMemory(); - } - - if (session != null && session.getId() != null) { - if (this.sessionInMemoryEnabled) { - this.delSessionFromThreadLocal(session.getId()); - } - - try { - this.redisManager.del(this.getRedisSessionKey(session.getId())); - } catch (SerializationException var3) { - logger.error("delete session error. session id=" + session.getId()); - } - - } else { - logger.error("session or session id is null"); - } - } - - @Override - public Collection<Session> getActiveSessions() { - if (this.sessionInMemoryEnabled) { - this.removeExpiredSessionInMemory(); - } - - HashSet sessions = new HashSet(); - - try { - Set<String> keys = this.redisManager.keys(this.keyPrefix + "*"); - if (keys != null && keys.size() > 0) { - Iterator<String> var3 = keys.iterator(); - while (var3.hasNext()) { - String key = var3.next(); - Session s = (Session) this.redisManager.get(key); - sessions.add(s); - } - } - } catch (SerializationException var6) { - logger.error("get active sessions error."); - } - - return sessions; - } - - @Override - protected Serializable doCreate(Session session) { - if (this.sessionInMemoryEnabled) { - this.removeExpiredSessionInMemory(); - } - - if (session == null) { - logger.error("session is null"); - throw new UnknownSessionException("session is null"); - } else { - Serializable sessionId = this.generateSessionId(session); - this.assignSessionId(session, sessionId); - this.saveSession(session); - return sessionId; - } - } - - @Override - protected Session doReadSession(Serializable sessionId) { - if (this.sessionInMemoryEnabled) { - this.removeExpiredSessionInMemory(); - } - - if (sessionId == null) { - logger.warn("session id is null"); - return null; - } else { - Session session; - if (this.sessionInMemoryEnabled) { - session = this.getSessionFromThreadLocal(sessionId); - if (session != null) { - return session; - } - } - - session = null; - - try { - String sessionRedisKey = this.getRedisSessionKey(sessionId); - logger.debug("read session: " + sessionRedisKey + " from Redis"); - session = (Session) this.redisManager.get(sessionRedisKey); - if (this.sessionInMemoryEnabled) { - this.setSessionToThreadLocal(sessionId, session); - } - } catch (SerializationException var4) { - logger.error("read session error. sessionId: " + sessionId); - } - - return session; - } - } - - private void setSessionToThreadLocal(Serializable sessionId, Session session) { - this.initSessionsInThread(); - Map<Serializable, SessionInMemory> sessionMap = (Map) sessionsInThread.get(); - sessionMap.put(sessionId, this.createSessionInMemory(session)); - } - - private void delSessionFromThreadLocal(Serializable sessionId) { - Map<Serializable, SessionInMemory> sessionMap = (Map) sessionsInThread.get(); - if (sessionMap != null) { - sessionMap.remove(sessionId); - } - } - - private SessionInMemory createSessionInMemory(Session session) { - SessionInMemory sessionInMemory = new SessionInMemory(); - sessionInMemory.setCreateTime(new Date()); - sessionInMemory.setSession(session); - return sessionInMemory; - } - - private void initSessionsInThread() { - Map<Serializable, SessionInMemory> sessionMap = (Map) sessionsInThread.get(); - if (sessionMap == null) { - sessionMap = new HashMap(); - sessionsInThread.set(sessionMap); - } - - } - - private void removeExpiredSessionInMemory() { - Map<Serializable, SessionInMemory> sessionMap = (Map) sessionsInThread.get(); - if (sessionMap != null) { - Iterator it = sessionMap.keySet().iterator(); - - while (it.hasNext()) { - Serializable sessionId = (Serializable) it.next(); - SessionInMemory sessionInMemory = (SessionInMemory) sessionMap.get(sessionId); - if (sessionInMemory == null) { - it.remove(); - } else { - long liveTime = this.getSessionInMemoryLiveTime(sessionInMemory); - if (liveTime > this.sessionInMemoryTimeout) { - it.remove(); - } - } - } - - if (sessionMap.size() == 0) { - sessionsInThread.remove(); - } - - } - } - - private Session getSessionFromThreadLocal(Serializable sessionId) { - if (sessionsInThread.get() == null) { - return null; - } else { - Map<Serializable, SessionInMemory> sessionMap = (Map) sessionsInThread.get(); - SessionInMemory sessionInMemory = (SessionInMemory) sessionMap.get(sessionId); - if (sessionInMemory == null) { - return null; - } else { - logger.debug("read session from memory"); - return sessionInMemory.getSession(); - } - } - } - - private long getSessionInMemoryLiveTime(SessionInMemory sessionInMemory) { - Date now = new Date(); - return now.getTime() - sessionInMemory.getCreateTime().getTime(); - } - - private String getRedisSessionKey(Serializable sessionId) { - return this.keyPrefix + sessionId; - } - - @Override - public IRedisManager getRedisManager() { - return this.redisManager; - } - - public void setRedisManager(MyRedisManager redisManager) { - this.redisManager = redisManager; - } - - @Override - public String getKeyPrefix() { - return this.keyPrefix; - } - - @Override - public void setKeyPrefix(String keyPrefix) { - this.keyPrefix = keyPrefix; - } - - - @Override - public long getSessionInMemoryTimeout() { - return this.sessionInMemoryTimeout; - } - - @Override - public void setSessionInMemoryTimeout(long sessionInMemoryTimeout) { - this.sessionInMemoryTimeout = sessionInMemoryTimeout; - } - - @Override - public int getExpire() { - return this.expire; - } - - @Override - public void setExpire(int expire) { - this.expire = expire; - } - - @Override - public boolean getSessionInMemoryEnabled() { - return this.sessionInMemoryEnabled; - } - - @Override - public void setSessionInMemoryEnabled(boolean sessionInMemoryEnabled) { - this.sessionInMemoryEnabled = sessionInMemoryEnabled; - } - - public static ThreadLocal getSessionsInThread() { - return sessionsInThread; - } -} diff --git a/nz-admin/src/main/java/com/nis/modules/sys/shiro/ShiroUtils.java b/nz-admin/src/main/java/com/nis/modules/sys/shiro/ShiroUtils.java index 40a564a8..1ebb6745 100644 --- a/nz-admin/src/main/java/com/nis/modules/sys/shiro/ShiroUtils.java +++ b/nz-admin/src/main/java/com/nis/modules/sys/shiro/ShiroUtils.java @@ -2,6 +2,7 @@ package com.nis.modules.sys.shiro; import cn.hutool.log.Log; import com.nis.common.utils.SpringContextUtils; +import com.nis.common.utils.Tool; import com.nis.common.utils.ToolUtil; import com.nis.modules.sys.entity.SysUserEntity; import org.apache.shiro.SecurityUtils; @@ -10,9 +11,11 @@ import org.apache.shiro.session.Session; import org.apache.shiro.session.UnknownSessionException; import org.apache.shiro.session.mgt.DefaultSessionKey; import org.apache.shiro.session.mgt.SimpleSession; +import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.subject.SimplePrincipalCollection; import org.apache.shiro.subject.Subject; import org.apache.shiro.subject.support.DefaultSubjectContext; +import org.crazycake.shiro.RedisSessionDAO; import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.ValueOperations; @@ -43,7 +46,11 @@ public class ShiroUtils { } public static Session getSessionById(String sessionId) { - return SecurityUtils.getSecurityManager().getSession(new DefaultSessionKey(sessionId)); + try { + return SecurityUtils.getSecurityManager().getSession(new DefaultSessionKey(sessionId)); + } catch (Exception e) { + return null; + } } public static SysUserEntity getUserEntityBySessionId(String sessionId){ @@ -87,54 +94,50 @@ public class ShiroUtils { SecurityUtils.getSubject().logout(); } + + public static void updateSession(Session session) { + RedisSessionDAO sessionDao = SpringContextUtils.getBean("redisSessionDAO", RedisSessionDAO.class); + sessionDao.update(session); + } + + + public static List<SysUserEntity> getActiveUsers() { + RedisSessionDAO sessionDao = SpringContextUtils.getBean("redisSessionDAO", RedisSessionDAO.class); + Collection<Session> sessions = sessionDao.getActiveSessions(); + List<SysUserEntity> userList = Tool.CollUtil.newArrayList(); + for (Session session : sessions) { + PrincipalCollection primaryPrincipal = (PrincipalCollection) session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY); + if(ToolUtil.isNotEmpty(primaryPrincipal)) { + userList.add((SysUserEntity) primaryPrincipal.getPrimaryPrincipal()); + } + } + return userList; + } + /** * 从 redis 中获取 token 和 用户信息 * * @return */ public static Map<String, SysUserEntity> getShiroSessionInfoMap() { - RedisConnectionFactory factory = SpringContextUtils.getBean("redisConnectionFactory", RedisConnectionFactory.class); - RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); - redisTemplate.setKeySerializer(new StringRedisSerializer()); - redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer()); - redisTemplate.setConnectionFactory(factory); - - redisTemplate.afterPropertiesSet(); - - ValueOperations ops = redisTemplate.opsForValue(); - - Set keys = redisTemplate.keys(ShiroUtils.REDIS_KEYPREFIX + "*"); - List<String> keyList = new ArrayList<>(keys); - List<Object> values = ops.multiGet(keyList); - Map<String, Object> map = new HashMap(); - - int size = keyList.size(); - for (int i = 0; i < size; i++) { - map.put(keyList.get(i), values.get(i)); - } - - Map<String, SysUserEntity> resultMap = new HashMap(map.size()); - for (Map.Entry<String, Object> entry : map.entrySet()) { - Object obj = entry.getValue(); - SimpleSession session = (SimpleSession) obj; - if (ToolUtil.isEmpty(session.getAttributes())) - continue; - SimplePrincipalCollection primaryPrincipal = (SimplePrincipalCollection) session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY); + RedisSessionDAO sessionDao = SpringContextUtils.getBean("redisSessionDAO", RedisSessionDAO.class); + Collection<Session> sessions = sessionDao.getActiveSessions(); + Map<String, SysUserEntity> resultMap = Tool.MapUtil.newHashMap(sessions.size()); + for (Session session : sessions) { + PrincipalCollection primaryPrincipal = (PrincipalCollection) session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY); if(ToolUtil.isNotEmpty(primaryPrincipal)) { - resultMap.put(entry.getKey(), (SysUserEntity) primaryPrincipal.getPrimaryPrincipal()); + resultMap.put(session.getId().toString(), (SysUserEntity) primaryPrincipal.getPrimaryPrincipal()); } } return resultMap; } - public static void removeRedisCacheByToken(List<String> tokens) { - RedisConnectionFactory factory = SpringContextUtils.getBean("redisConnectionFactory", RedisConnectionFactory.class); - RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); - redisTemplate.setKeySerializer(new StringRedisSerializer()); - redisTemplate.setValueSerializer(new JdkSerializationRedisSerializer()); - redisTemplate.setConnectionFactory(factory); - - redisTemplate.afterPropertiesSet(); - redisTemplate.delete(tokens); + public static void deleteSession(List<String> sessionIds) { + RedisSessionDAO sessionDao = SpringContextUtils.getBean("redisSessionDAO", RedisSessionDAO.class); + for(String s : sessionIds) { + SimpleSession ss = new SimpleSession(); + ss.setId(s); + sessionDao.delete(ss); + } } } diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/backend/TerminalHandler.java b/nz-admin/src/main/java/com/nis/modules/terminal/backend/TerminalHandler.java index 5d7ca0cb..e3e76730 100644 --- a/nz-admin/src/main/java/com/nis/modules/terminal/backend/TerminalHandler.java +++ b/nz-admin/src/main/java/com/nis/modules/terminal/backend/TerminalHandler.java @@ -147,7 +147,7 @@ public class TerminalHandler extends TextWebSocketHandler { this.initFieldVal(session); log.info("WebSocket connectioned. after connection established open terminal begin... uuid: {}", uuid); - SysUserEntity userEntity = Tool.MapUtil.get(ShiroUtils.getShiroSessionInfoMap(), StrUtil.concat(true, ShiroUtils.REDIS_KEYPREFIX, token), SysUserEntity.class); + SysUserEntity userEntity = Tool.MapUtil.get(ShiroUtils.getShiroSessionInfoMap(), token, SysUserEntity.class); if (ObjectUtil.isNull(userEntity)) { log.warn("open terminal error. system login token exception. uuid: {}, token: {}", uuid, token); session.sendMessage(new TextMessage("Token error, Please log in to the system first")); diff --git a/nz-admin/src/main/java/com/nis/modules/terminal/backend/TerminalMonitorHandler.java b/nz-admin/src/main/java/com/nis/modules/terminal/backend/TerminalMonitorHandler.java index ed6f38b4..3bb191c7 100644 --- a/nz-admin/src/main/java/com/nis/modules/terminal/backend/TerminalMonitorHandler.java +++ b/nz-admin/src/main/java/com/nis/modules/terminal/backend/TerminalMonitorHandler.java @@ -29,7 +29,7 @@ public class TerminalMonitorHandler extends TextWebSocketHandler { String token = (String) attributes.get("terminalToken"); Map<String, SysUserEntity> shiroSessionInfoMap = ShiroUtils.getShiroSessionInfoMap(); - SysUserEntity user = shiroSessionInfoMap.get(Tool.StrUtil.concat(true, ShiroUtils.REDIS_KEYPREFIX, token)); + SysUserEntity user = shiroSessionInfoMap.get(token); if (user == null) { session.sendMessage(new TextMessage("Token error,Please log in to the system first")); session.close(); |
