Commit f6cc3205 authored by cy's avatar cy

shrio转移到service模块

parent 7c770313
......@@ -108,10 +108,10 @@
<where>
is_delete =0
<if test="upGrade != null">
and #{upGrade} > lowest_mark
and #{upGrade} >= lowest_mark
</if>
<if test="downGrade != null">
and lowest_mark >#{downGrade}
and lowest_mark >=#{downGrade}
</if>
<if test="type != null">
and type =#{type}
......@@ -151,7 +151,7 @@
and #{upGrade} >= lowest_mark
</if>
<if test="downGrade != null">
and lowest_mark >=#{downGrade}
and lowest_mark >= #{downGrade}
</if>
<if test="type != null">
and type =#{type}
......
......@@ -81,6 +81,17 @@
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>org.crazycake</groupId>
<artifactId>shiro-redis</artifactId>
<version>3.1.0</version>
</dependency>
</dependencies>
<!-- MAVEN构建 -->
......
......@@ -19,6 +19,7 @@ import cn.wisenergy.service.app.UserLoginService;
import cn.wisenergy.service.cache.RedisService;
import cn.wisenergy.service.common.Common;
import cn.wisenergy.service.common.VolunteerManager;
import cn.wisenergy.service.shir.filter.KickoutSessionControlFilter;
import cn.wisenergy.service.util.UserToken;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
......@@ -29,18 +30,12 @@ import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;
/**
* @author 86187
......@@ -211,7 +206,8 @@ public class UserLoginServiceImpl extends ServiceImpl<UsersMapper, User> impleme
UserToken userToken = new UserToken(userVo.getPhone(), credentialsSalt, USER_LOGIN_TYPE);
try {
subject.login(userToken);
KickoutSessionControlFilter kitOut = new KickoutSessionControlFilter();
kitOut.changeSession(1);
//3、构造返回参数
UserInfoVo userInfoVo = new UserInfoVo();
userInfoVo.setUserId(user.getId());
......
package cn.wisenergy.service.shir.cache;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.util.WebUtils;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.Serializable;
public class MySessionManager extends DefaultWebSessionManager {
//前端传递sessionid参数名称
private static final String AUTHORIZATION = "sessionId";
private static final String REFERENCED_SESSION_ID_SOURCE = "Stateless request";
public MySessionManager() {
super();
}
@Override
protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
String id = WebUtils.toHttp(request).getHeader(AUTHORIZATION);
//如果请求头中有 token 则其值为sessionId
if (!StringUtils.isEmpty(id)) {
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, REFERENCED_SESSION_ID_SOURCE);
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
return id;
} else {
//否则按默认规则从cookie取sessionId
return super.getSessionId(request, response);
}
}
}
package cn.wisenergy.service.shir.config;
import cn.wisenergy.service.shir.cache.MySessionManager;
import cn.wisenergy.service.shir.filter.AuthenticationFilter;
import cn.wisenergy.service.shir.filter.KickoutSessionControlFilter;
import cn.wisenergy.service.shir.realm.AdminRealm;
import cn.wisenergy.service.shir.realm.CodeRealm;
import cn.wisenergy.service.shir.realm.StaffRealm;
import cn.wisenergy.service.shir.realm.UserRealm;
import cn.wisenergy.service.shir.util.UserModularRealmAuthenticator;
import org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.crazycake.shiro.IRedisManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.Filter;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@Configuration
public class ShiroConfig {
//redis地址
@Value("${spring.redis.host}")
private String host;
//redis端口
@Value("${spring.redis.port}")
private int port;
//redis连接超时时间
@Value("${spring.redis.timeout}")
private String timeout;
//redis密码
@Value("${spring.redis.password}")
private String password;
//设置session会话过期时间为两小时
private static final Integer expireTime = 3600 * 2;
/**
* 创建ShrioFilterFactoryBean
*/
@Bean("shiroFilter")
public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
//添加shrio内置过滤器
/**
* 常用的过滤器:
* anon:无需认证(登录)就可以访问
* authc:必须认证才能访问
* user:使用rememberMe功能可以直接访问
* perms:该资源必须得到资源权限才能访问
* role:该资源必须得到角色权限才能访问
*/
Map<String,String> filterChainDefinitionMap=new LinkedHashMap<>();
//自定义拦截器
Map<String, Filter> filtersMap = new LinkedHashMap<>();
filtersMap.put("authc", new AuthenticationFilter());
filtersMap.put("kickout",kickoutSessionControlFilter());
shiroFilterFactoryBean.setFilters(filtersMap);
filterChainDefinitionMap.put("/authInformation/save", "anon");//存储设备IMEI号和手机SIM卡ID号
filterChainDefinitionMap.put("/user/login/*", "anon"); // 登录页面-身份认证
filterChainDefinitionMap.put("/user/sendSms", "anon"); // 发送验证码
filterChainDefinitionMap.put("/user/valid", "anon"); // 缓存验证码
filterChainDefinitionMap.put("/account/login", "anon"); // 登录页面-身份认证
filterChainDefinitionMap.put("/staffUser/login", "anon"); // 登录页面-身份认证
filterChainDefinitionMap.put("/swagger-ui.html", "anon"); // swagger接口-匿名访问
filterChainDefinitionMap.put("/swagger/**", "anon");
filterChainDefinitionMap.put("/admin/anon/**", "anon");
filterChainDefinitionMap.put("/webjars/springfox-swagger-ui/**", "anon");
filterChainDefinitionMap.put("/swagger-resources/**", "anon");
filterChainDefinitionMap.put("/v2/api-docs", "anon");
filterChainDefinitionMap.put("/upload_flowChart/**", "anon");//图片地址
filterChainDefinitionMap.put("/webSocket/**", "anon");//socket
filterChainDefinitionMap.put("/message/**", "anon");//消息推送接口
filterChainDefinitionMap.put("/**", "authc");
filterChainDefinitionMap.put("/account/**", "kickout");
filterChainDefinitionMap.put("/banner/**", "kickout");
filterChainDefinitionMap.put("/pic/**", "kickout");
filterChainDefinitionMap.put("/school/**", "kickout");
filterChainDefinitionMap.put("/pay/**", "kickout");
filterChainDefinitionMap.put("/price/**", "kickout");
filterChainDefinitionMap.put("/profession/**", "kickout");
filterChainDefinitionMap.put("/refillCard/**", "kickout");
filterChainDefinitionMap.put("/scheme/**", "kickout");
filterChainDefinitionMap.put("/user/**", "kickout");
filterChainDefinitionMap.put("/staff/**", "kickout");
filterChainDefinitionMap.put("/staffUser/**", "kickout");
filterChainDefinitionMap.put("/volunteer/**", "kickout");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
/**
* 创建DefaultWebSecurityManager
*/
@Bean
public DefaultWebSecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setAuthenticator(modularRealmAuthenticator());
List<Realm> realms = new ArrayList<>();
realms.add(adminRealm());
realms.add(userRealm());
realms.add(staffRealm());
realms.add(codeRealm());
securityManager.setRealms(realms);
// 自定义session管理 使用redis
securityManager.setSessionManager(sessionManager());
// 自定义缓存实现 使用redis
securityManager.setCacheManager(cacheManagers());
return securityManager;
}
/**
* 创建Realm
*/
@Bean
public ModularRealmAuthenticator modularRealmAuthenticator(){
//自己重写的ModularRealmAuthenticator
UserModularRealmAuthenticator modularRealmAuthenticator = new UserModularRealmAuthenticator();
modularRealmAuthenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
return modularRealmAuthenticator;
}
@Bean
public AdminRealm adminRealm() {
AdminRealm adminRealm = new AdminRealm();
return adminRealm;
}
@Bean
public StaffRealm staffRealm() {
StaffRealm staffRealm = new StaffRealm();
return staffRealm;
}
@Bean
public CodeRealm codeRealm() {
CodeRealm adminShiroRealm = new CodeRealm();
return adminShiroRealm;
}
@Bean
public UserRealm userRealm() {
UserRealm userRealm = new UserRealm();
return userRealm;
}
/**
* 开启shrio注解
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}
/**
*自定义sessionManager
*/
@Bean
public MySessionManager sessionManager() {
MySessionManager mySessionManager = new MySessionManager();
mySessionManager.setSessionDAO(redisSessionDAO());
return mySessionManager;
}
/**
* 配置shiro redisManager
* 使用的是shiro-redis开源插件
*/
public IRedisManager redisManager() {
RedisManager redisManager = new RedisManager();
redisManager.setHost(host);
redisManager.setPort(port);
redisManager.setPassword(password);
redisManager.setDatabase(5);
return redisManager;
}
/**
* cacheManager 缓存 redis实现
* 使用的是shiro-redis开源插件
*/
@Bean
public RedisCacheManager cacheManagers() {
RedisCacheManager redisCacheManager = new RedisCacheManager();
redisCacheManager.setRedisManager(redisManager());
redisCacheManager.setExpire(expireTime);
return redisCacheManager;
}
/**
* RedisSessionDAO shiro sessionDao层的实现 通过redis
* SessionDAO的作用是为Session提供CRUD并进行持久化的一个shiro组件
* MemorySessionDAO 直接在内存中进行会话维护
* EnterpriseCacheSessionDAO 提供了缓存功能的会话维护,默认情况下使用MapCache实现,内部使用ConcurrentHashMap保存缓存的会话。
*/
@Bean
public RedisSessionDAO redisSessionDAO() {
RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
redisSessionDAO.setRedisManager(redisManager());
redisSessionDAO.setExpire(expireTime);
return redisSessionDAO;
}
/**
* 限制同一账号登录同时登录人数控制
*
* @return
*/
@Bean
public KickoutSessionControlFilter kickoutSessionControlFilter() {
KickoutSessionControlFilter kickoutSessionControlFilter = new KickoutSessionControlFilter();
kickoutSessionControlFilter.setCacheManager(cacheManagers());
kickoutSessionControlFilter.setSessionManager(sessionManager());
kickoutSessionControlFilter.setKickoutAfter(false);
kickoutSessionControlFilter.setMaxSession(1);
return kickoutSessionControlFilter;
}
}
package cn.wisenergy.service.shir.filter;
import com.alibaba.fastjson.JSONObject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.springframework.http.HttpStatus;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
/**
* 跨域配置拦截器,继承FormAuthenticationFilter
*/
public class AuthenticationFilter extends FormAuthenticationFilter {
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
// 错误异常提示
HttpServletResponse httpResponse = (HttpServletResponse) response;
HttpServletRequest httpRequest = (HttpServletRequest) request;
String sessionId = ((HttpServletRequest) request).getHeader("sessionId");
if (sessionId == null) {
setHeader(httpRequest, httpResponse);
httpResponse.setCharacterEncoding("UTF-8");
httpResponse.setContentType("application/json");
Map<String, Object> map = new HashMap<>();
map.put("status", "1001");
map.put("message", "登录已超时,请重新登录!");
httpResponse.getWriter().write(JSONObject.toJSONString(map));
return false;
} else {
return true;
}
}
/**
* 为response设置header,实现跨域
*/
private void setHeader(HttpServletRequest request, HttpServletResponse response) {
//跨域的header设置
response.setHeader("Access-control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Methods", request.getMethod());
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers"));
//防止乱码,适用于传输JSON数据
//Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild
response.setHeader("Content-Type", "application/json;charset=UTF-8");
response.setStatus(HttpStatus.OK.value());
}
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
if (request instanceof HttpServletRequest) {
if (((HttpServletRequest) request).getMethod().toUpperCase().equals("OPTIONS")) {
return true;
}
}
//小程序放行
if(isFilter((HttpServletRequest) request)){
return true;
}
return super.isAccessAllowed(request, response, mappedValue);
}
//判断请求头中是否带有identity(标识是小程序)
public boolean isFilter(HttpServletRequest request) {
return null != request.getHeader("identity") && request.getHeader("identity").equals("miniprogram");
}
}
package cn.wisenergy.service.shir.filter;
import cn.wisenergy.model.app.AccountInfo;
import cn.wisenergy.model.app.Staff;
import cn.wisenergy.model.app.User;
import cn.wisenergy.service.shir.cache.MySessionManager;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.itextpdf.text.log.Logger;
import com.itextpdf.text.log.LoggerFactory;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.DefaultSessionKey;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.apache.shiro.cache.CacheManager;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.util.Deque;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
public class KickoutSessionControlFilter extends AccessControlFilter {
private final Logger logger = LoggerFactory.getLogger(KickoutSessionControlFilter.class);
private boolean kickoutAfter = false; //踢出之前登录的/之后登录的用户 默认踢出之前登录的用户
private int maxSession = 1; //同一个帐号最大会话数 默认1
private MySessionManager sessionManager;
private Cache<String, Deque<Serializable>> cache;
public void setKickoutAfter(boolean kickoutAfter) {
this.kickoutAfter = kickoutAfter;
}
public void setMaxSession(int maxSession) {
this.maxSession = maxSession;
}
public void setSessionManager(MySessionManager sessionManager) {
this.sessionManager = sessionManager;
}
//设置Cache的key的前缀
public void setCacheManager(CacheManager cacheManager) {
this.cache = cacheManager.getCache("shiro_redis_cache");
}
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
//如果是小程序,就放行
boolean filter = isFilter((HttpServletRequest) request);
return filter;
}
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
Subject subject = getSubject(request, response);
Map<String, Object> map = new HashMap<>();
//判断是否登录
if (!subject.isAuthenticated() && !subject.isRemembered()) {
return true;
}
Session session = subject.getSession();
//设置session超时时长,30分钟(1800000毫秒)
//session.setTimeout(1800000);
//5分钟
session.setTimeout(300000);
Serializable sessionId = null;
String username = null;
// Deque<Serializable> deque = null;
try {
//客户端
User user = (User) SecurityUtils.getSubject().getPrincipal();
username = user.getPhone();
sessionId = session.getId();
//读取缓存,没有就存入
//deque = cache.get(username);
} catch (Exception e) {
try {
//管理端
sessionId = session.getId();
AccountInfo accountInfo = (AccountInfo) SecurityUtils.getSubject().getPrincipal();
username = accountInfo.getUserName();
//读取缓存,没有就存入
//deque = cache.get(username);
} catch (Exception en) {
//员工端
Staff staff = (Staff) SecurityUtils.getSubject().getPrincipal();
username = staff.getLoginName();
sessionId = session.getId();
//读取缓存,没有就存入
//deque = cache.get(username);
}
}
/* //如果此用户没有session队列,也就是还没有登录过,缓存中没有,就new一个空队列,不然deque对象为空,会报空指针
if (deque == null) {
deque = new LinkedList<>();
}
//如果队列里没有此sessionId,且用户没有被踢出;放入队列
if (!deque.contains(sessionId) && session.getAttribute("kickout") == null) {
//将sessionId存入队列
deque.push(sessionId);
//将用户的sessionId队列缓存
cache.put(username, deque);
}
//如果队列里的sessionId数超出最大会话数,开始踢人
while (deque.size() > maxSession) {
Serializable kickoutSessionId;
if (kickoutAfter) { //如果踢出后者
kickoutSessionId = deque.removeFirst();
//踢出后再更新下缓存队列
} else { //否则踢出前者
kickoutSessionId = deque.removeLast();
//踢出后再更新下缓存队列
}
cache.put(username, deque);
try {
//获取被踢出的sessionId的session对象
DefaultSessionKey defaultSessionKey = new DefaultSessionKey(kickoutSessionId);
Session kickoutSession = sessionManager.getSession(defaultSessionKey);
//Session kickoutSession = (Session) sessionManager.getSession(String.valueOf(new DefaultSessionKey(kickoutSessionId)));
if (kickoutSession != null) {
//设置会话的kickout属性表示踢出了
kickoutSession.setAttribute("kickout", true);
}
} catch (Exception e) {
}
}*/
//如果被踢出了,直接退出,重定向到踢出后的地址
if (session.getAttribute("kickout") != null) {
logger.info("------" + "踢出用户" + username + "登录sessionId=" + sessionId + "------");
//会话被踢出了
try {
//退出登录
subject.logout();
} catch (Exception e) {
}
saveRequest(request);
map.put("status", "1002");
map.put("message", "您已经在其他地方登录,请重新登录。如有疑问请联系管理员!");
out(response, map);
return false;
}
return true;
}
private void out(ServletResponse response, Map<String, Object> map) throws IOException {
response.setContentType("text/json");
//设置字符集为'UTF-8'
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
out.write(JSON.toJSONString(map, SerializerFeature.WriteMapNullValue));
out.flush();
out.close();
}
public boolean isFilter(HttpServletRequest request) {
return null != request.getHeader("identity") && request.getHeader("identity").equals("miniprogram");
}
public void changeSession(int type){
Subject subject = SecurityUtils.getSubject();
Session session = subject.getSession();
session.setTimeout(300000);
Serializable sessionId = session.getId();
String username = null;
Deque<Serializable> deque = null;
if(type == 1){
User user=(User)subject.getPrincipal();
username=user.getPhone();
}else if(type == 2){
AccountInfo account=(AccountInfo)subject.getPrincipal();
username=account.getUserName();
}else{
Staff staff=(Staff)subject.getPrincipal();
username=staff.getLoginName();
}
//读取缓存,没有就存入
deque = cache.get(username);
//如果此用户没有session队列,也就是还没有登录过,缓存中没有,就new一个空队列,不然deque对象为空,会报空指针
if (deque == null) {
deque = new LinkedList<>();
}
//如果队列里没有此sessionId,且用户没有被踢出;放入队列
if (!deque.contains(sessionId) && session.getAttribute("kickout") == null) {
//将sessionId存入队列
deque.push(sessionId);
//将用户的sessionId队列缓存
cache.put(username, deque);
}
//如果队列里的sessionId数超出最大会话数,开始踢人
while (deque.size() > maxSession) {
Serializable kickoutSessionId;
if (kickoutAfter) { //如果踢出后者
kickoutSessionId = deque.removeFirst();
//踢出后再更新下缓存队列
} else { //否则踢出前者
kickoutSessionId = deque.removeLast();
//踢出后再更新下缓存队列
}
cache.put(username, deque);
try {
//获取被踢出的sessionId的session对象
DefaultSessionKey defaultSessionKey = new DefaultSessionKey(kickoutSessionId);
Session kickoutSession = sessionManager.getSession(defaultSessionKey);
//Session kickoutSession = (Session) sessionManager.getSession(String.valueOf(new DefaultSessionKey(kickoutSessionId)));
if (kickoutSession != null) {
//设置会话的kickout属性表示踢出了
kickoutSession.setAttribute("kickout", true);
}
} catch (Exception e) {
}
}
}
}
package cn.wisenergy.service.shir.realm;
import cn.wisenergy.common.utils.Md5Util;
import cn.wisenergy.mapper.AccountMapper;
import cn.wisenergy.model.app.AccountInfo;
import cn.wisenergy.service.util.UserToken;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
public class AdminRealm extends AuthorizingRealm {
@Autowired
private AccountMapper accountMapper;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
UserToken userToken = (UserToken)token;
String userName=userToken.getUsername();
QueryWrapper<AccountInfo> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("user_name", userName);
queryWrapper.eq("is_delete", 0);
AccountInfo accountInfo = accountMapper.selectOne(queryWrapper);
if (accountInfo == null) {
return null;
}
String password = Md5Util.digestMD5(accountInfo.getPassword());
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
accountInfo,
password,
accountInfo.getUserName()
);
return authenticationInfo;
}
}
package cn.wisenergy.service.shir.realm;
import cn.wisenergy.mapper.UsersMapper;
import cn.wisenergy.model.app.User;
import cn.wisenergy.model.enums.SourceType;
import cn.wisenergy.service.cache.RedisService;
import cn.wisenergy.service.common.CachePrefix;
import cn.wisenergy.service.util.UserToken;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
public class CodeRealm extends AuthorizingRealm {
@Autowired
private UsersMapper usersMapper;
@Autowired
private RedisService redisService;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
UserToken userToken = (UserToken)token;
String userName=userToken.getUsername();
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("phone", userName);
queryWrapper.eq("is_delete", 0);
User userInfo = usersMapper.selectOne(queryWrapper);
if (userInfo == null) {
return null;
}
String source = SourceType.getByCode(userInfo.getSource());
//获取短信验证码key
String key = CachePrefix.SMS_CODE.getPrefix() + "_" + source + "_" + userInfo.getPhone();
Object obj = redisService.get(key);
String code = obj.toString();
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
userInfo,
code,
userInfo.getPhone()
);
return authenticationInfo;
}
}
package cn.wisenergy.service.shir.realm;
import cn.wisenergy.mapper.StaffMapper;
import cn.wisenergy.model.app.Staff;
import cn.wisenergy.service.util.UserToken;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
public class StaffRealm extends AuthorizingRealm {
@Autowired
private StaffMapper staffMapper;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
UserToken userToken = (UserToken)token;
String userName=userToken.getUsername();
QueryWrapper<Staff> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("login_name", userName);
queryWrapper.eq("is_delete", 0);
Staff staff = staffMapper.selectOne(queryWrapper);
if (staff == null) {
return null;
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
staff,
staff.getPassword(),
staff.getLoginName()
);
return authenticationInfo;
}
}
package cn.wisenergy.service.shir.realm;
import cn.wisenergy.mapper.UsersMapper;
import cn.wisenergy.model.app.User;
import cn.wisenergy.service.util.UserToken;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
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.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
public class UserRealm extends AuthorizingRealm {
@Autowired
private UsersMapper usersMapper;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
UserToken userToken = (UserToken)token;
String userName=userToken.getUsername();
//通过username从数据库中查找 User对象
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("phone", userName);
queryWrapper.eq("is_delete", 0);
User userInfo = usersMapper.selectOne(queryWrapper);
if (userInfo == null) {
return null;
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
userInfo,
userInfo.getPassword(),
userInfo.getPhone()
);
return authenticationInfo;
}
}
package cn.wisenergy.service.shir.util;
import cn.wisenergy.model.app.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.Authenticator;
import org.apache.shiro.authc.LogoutAware;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.crazycake.shiro.RedisSessionDAO;
import java.util.Collection;
import java.util.Objects;
public class ShiroUtils {
/**
* 私有构造器
**/
private ShiroUtils() {
}
private static RedisSessionDAO redisSessionDAO = SpringUtil.getBean(RedisSessionDAO.class);
/**
* 获取当前用户Session
*
* @Return SysUserEntity 用户信息
*/
public static Session getSession() {
return SecurityUtils.getSubject().getSession();
}
/**
* 用户登出
*/
public static void logout() {
SecurityUtils.getSubject().logout();
}
/**
* 获取当前用户信息
*
* @Return SysUserEntity 用户信息
*/
public static User getUserInfo() {
User user = (User) SecurityUtils.getSubject().getPrincipal();
return user;
}
/**
* 获取登录用户的id
*
* @return
*/
public static Integer getLoginUserId() {
return getUserInfo().getId();
}
/**
* 获取登录用户的名称
*
* @return
*/
public static String getLoginUserName() {
return getUserInfo().getUserName();
}
/**
* 删除用户缓存信息
*
* @Param username 用户名称
* @Param isRemoveSession 是否删除Session,删除后用户需重新登录 如果为false代表只需要重新授权即可
*/
public static void deleteCache(String username, boolean isRemoveSession) {
//从缓存中获取Session
Session session = null;
// 获取当前已登录的用户session列表
Collection<Session> sessions = redisSessionDAO.getActiveSessions();
Object attribute = null;
// 遍历Session,找到该用户名称对应的Session
for (Session sessionInfo : sessions) {
attribute = sessionInfo.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
if (attribute == null) {
continue;
}
String name = ((SimplePrincipalCollection) attribute).getPrimaryPrincipal().toString();
if (name == null) {
continue;
}
if (Objects.equals(name, username)) {
session = sessionInfo;
// 清除该用户以前登录时保存的session,强制退出 -> 单用户登录处理
if (isRemoveSession) {
redisSessionDAO.delete(session);
}
}
}
if (session == null || attribute == null) {
return;
}
//删除session重新登录
if (isRemoveSession) {
redisSessionDAO.delete(session);
}
//删除Cache,再访问受限接口时会重新授权
DefaultWebSecurityManager securityManager = (DefaultWebSecurityManager) SecurityUtils.getSecurityManager();
Authenticator authc = securityManager.getAuthenticator();
((LogoutAware) authc).onLogout((SimplePrincipalCollection) attribute);
}
/**
* 从缓存中获取指定用户名的Session
*
* @param username
*/
private static Session getSessionByUsername(String username) {
// 获取当前已登录的用户session列表
Collection<Session> sessions = redisSessionDAO.getActiveSessions();
User user;
Object attribute;
// 遍历Session,找到该用户名称对应的Session
for (Session session : sessions) {
attribute = session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
if (attribute == null) {
continue;
}
user = (User) ((SimplePrincipalCollection) attribute).getPrimaryPrincipal();
if (user == null) {
continue;
}
if (Objects.equals(user.getPhone(), username)) {
return session;
}
}
return null;
}
}
package cn.wisenergy.service.shir.util;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class SpringUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if(SpringUtil.applicationContext == null) {
SpringUtil.applicationContext = applicationContext;
}
System.out.println("========ApplicationContext配置成功,在普通类可以通过调用SpringUtils.getAppContext()获取applicationContext对象,applicationContext="+SpringUtil.applicationContext+"========");
System.out.println("---------------------------------------------------------------------");
}
//获取applicationContext
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
//通过name获取 Bean.
public static Object getBean(String name){
return getApplicationContext().getBean(name);
}
//通过class获取Bean.
public static <T> T getBean(Class<T> clazz){
return getApplicationContext().getBean(clazz);
}
//通过name,以及Clazz返回指定的Bean
public static <T> T getBean(String name,Class<T> clazz){
return getApplicationContext().getBean(name, clazz);
}
}
package cn.wisenergy.service.shir.util;
import cn.wisenergy.service.util.UserToken;
import com.itextpdf.text.log.Logger;
import com.itextpdf.text.log.LoggerFactory;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.realm.Realm;
import java.util.ArrayList;
import java.util.Collection;
public class UserModularRealmAuthenticator extends ModularRealmAuthenticator {
private static final Logger logger = LoggerFactory.getLogger(UserModularRealmAuthenticator.class);
@Override
protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken)
throws AuthenticationException {
logger.info("UserModularRealmAuthenticator:method doAuthenticate() execute ");
// 判断getRealms()是否返回为空
assertRealmsConfigured();
// 强制转换回自定义的CustomizedToken
UserToken userToken = (UserToken) authenticationToken;
// 登录类型
String loginType = userToken.getLoginType();
// 所有Realm
Collection<Realm> realms = getRealms();
// 登录类型对应的所有Realm
Collection<Realm> typeRealms = new ArrayList<>();
for (Realm realm : realms) {
if (realm.getName().contains(loginType));
typeRealms.add(realm);
}
// 判断是单Realm还是多Realm
if (typeRealms.size() == 1){
logger.info("doSingleRealmAuthentication() execute ");
return doSingleRealmAuthentication(((ArrayList<Realm>) typeRealms).get(0), userToken);
}
else{
logger.info("doMultiRealmAuthentication() execute ");
return doMultiRealmAuthentication(typeRealms, userToken);
}
}
}
package cn.wisenergy.service.util;
import cn.wisenergy.model.vo.UserLoginVo;
import cn.wisenergy.service.cache.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class SessionUntil {
@Autowired
private RedisService redisService;
public String saveSession(UserLoginVo userVo, HttpServletRequest request, HttpServletResponse response){
request.getSession().setAttribute("user",userVo);
redisService.set("","");
return null;
}
}
......@@ -133,17 +133,6 @@
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.9.8" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.9.8" level="project" />
<orderEntry type="library" name="Maven: joda-time:joda-time:2.10.2" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-core:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-lang:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-cache:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-crypto-hash:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-crypto-core:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-crypto-cipher:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-config-core:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-config-ogdl:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-event:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-spring:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-web:1.4.0" level="project" />
<orderEntry type="library" name="Maven: cn.hutool:hutool-all:4.6.7" level="project" />
<orderEntry type="library" name="Maven: io.swagger:swagger-annotations:1.5.23" level="project" />
<orderEntry type="library" name="Maven: com.hikvision.ga:artemis-http-client:1.1.3" level="project" />
......@@ -180,6 +169,25 @@
<orderEntry type="library" name="Maven: org.bouncycastle:bcpkix-jdk15on:1.59" level="project" />
<orderEntry type="library" name="Maven: com.itextpdf:itextpdf:5.5.13" level="project" />
<orderEntry type="library" name="Maven: com.itextpdf:itext-asian:5.2.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-spring:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-core:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-lang:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-cache:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-crypto-hash:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-crypto-core:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-crypto-cipher:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-config-core:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-config-ogdl:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-event:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.apache.shiro:shiro-web:1.4.0" level="project" />
<orderEntry type="library" name="Maven: org.crazycake:shiro-redis:3.1.0" level="project" />
<orderEntry type="library" name="Maven: redis.clients:jedis:2.9.3" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-pool2:2.6.2" level="project" />
<orderEntry type="library" name="Maven: com.puppycrawl.tools:checkstyle:8.3" level="project" />
<orderEntry type="library" name="Maven: antlr:antlr:2.7.7" level="project" />
<orderEntry type="library" name="Maven: org.antlr:antlr4-runtime:4.7" level="project" />
<orderEntry type="library" name="Maven: commons-cli:commons-cli:1.4" level="project" />
<orderEntry type="library" name="Maven: net.sf.saxon:Saxon-HE:9.8.0-4" level="project" />
<orderEntry type="library" name="Maven: org.apache.commons:commons-lang3:3.8.1" level="project" />
<orderEntry type="library" name="Maven: commons-lang:commons-lang:2.6" level="project" />
<orderEntry type="library" name="Maven: commons-pool:commons-pool:1.6" level="project" />
......
......@@ -7,6 +7,7 @@ import cn.wisenergy.web.shir.realm.AdminRealm;
import cn.wisenergy.web.shir.realm.CodeRealm;
import cn.wisenergy.web.shir.realm.StaffRealm;
import cn.wisenergy.web.shir.realm.UserRealm;
import cn.wisenergy.web.shir.util.SessionUntil;
import cn.wisenergy.web.shir.util.UserModularRealmAuthenticator;
import org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
......@@ -28,7 +29,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@Configuration
/*@Configuration*/
public class ShiroConfig {
//redis地址
......@@ -66,7 +67,7 @@ public class ShiroConfig {
*/
Map<String,String> filterChainDefinitionMap=new LinkedHashMap<>();
//自定义拦截器
/* //自定义拦截器
Map<String, Filter> filtersMap = new LinkedHashMap<>();
filtersMap.put("authc", new AuthenticationFilter());
filtersMap.put("kickout",kickoutSessionControlFilter());
......@@ -101,7 +102,7 @@ public class ShiroConfig {
filterChainDefinitionMap.put("/staff/**", "kickout");
filterChainDefinitionMap.put("/staffUser/**", "kickout");
filterChainDefinitionMap.put("/volunteer/**", "kickout");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);*/
return shiroFilterFactoryBean;
}
......@@ -225,12 +226,21 @@ public class ShiroConfig {
@Bean
public KickoutSessionControlFilter kickoutSessionControlFilter() {
KickoutSessionControlFilter kickoutSessionControlFilter = new KickoutSessionControlFilter();
kickoutSessionControlFilter.setCacheManager(cacheManagers());
// kickoutSessionControlFilter.setCacheManager(cacheManagers());
kickoutSessionControlFilter.setSessionManager(sessionManager());
kickoutSessionControlFilter.setKickoutAfter(false);
kickoutSessionControlFilter.setMaxSession(1);
return kickoutSessionControlFilter;
}
@Bean
public SessionUntil sessionUntil(){
SessionUntil sessionUntil = new SessionUntil();
sessionUntil.setCacheManager(cacheManagers());
sessionUntil.setSessionManager(sessionManager());
sessionUntil.setKickoutAfter(false);
sessionUntil.setMaxSession(1);
return sessionUntil;
}
}
......@@ -54,9 +54,9 @@ public class KickoutSessionControlFilter extends AccessControlFilter {
}
//设置Cache的key的前缀
public void setCacheManager(CacheManager cacheManager) {
/* public void setCacheManager(CacheManager cacheManager) {
this.cache = cacheManager.getCache("shiro_redis_cache");
}
}*/
@Override
......@@ -84,7 +84,7 @@ public class KickoutSessionControlFilter extends AccessControlFilter {
Serializable sessionId = null;
String username = null;
Deque<Serializable> deque = null;
// Deque<Serializable> deque = null;
try {
//客户端
......@@ -92,7 +92,7 @@ public class KickoutSessionControlFilter extends AccessControlFilter {
username = user.getPhone();
sessionId = session.getId();
//读取缓存,没有就存入
deque = cache.get(username);
//deque = cache.get(username);
} catch (Exception e) {
try {
//管理端
......@@ -100,18 +100,17 @@ public class KickoutSessionControlFilter extends AccessControlFilter {
AccountInfo accountInfo = (AccountInfo) SecurityUtils.getSubject().getPrincipal();
username = accountInfo.getUserName();
//读取缓存,没有就存入
deque = cache.get(username);
//deque = cache.get(username);
} catch (Exception en) {
//员工端
Staff staff = (Staff) SecurityUtils.getSubject().getPrincipal();
username = staff.getLoginName();
sessionId = session.getId();
//读取缓存,没有就存入
deque = cache.get(username);
//deque = cache.get(username);
}
}
//如果此用户没有session队列,也就是还没有登录过,缓存中没有,就new一个空队列,不然deque对象为空,会报空指针
/* //如果此用户没有session队列,也就是还没有登录过,缓存中没有,就new一个空队列,不然deque对象为空,会报空指针
if (deque == null) {
deque = new LinkedList<>();
}
......@@ -144,7 +143,7 @@ public class KickoutSessionControlFilter extends AccessControlFilter {
}
} catch (Exception e) {
}
}
}*/
//如果被踢出了,直接退出,重定向到踢出后的地址
if (session.getAttribute("kickout") != null) {
logger.info("------" + "踢出用户" + username + "登录sessionId=" + sessionId + "------");
......
......@@ -4,6 +4,7 @@ import cn.wisenergy.common.utils.Md5Util;
import cn.wisenergy.mapper.AccountMapper;
import cn.wisenergy.model.app.AccountInfo;
import cn.wisenergy.service.util.UserToken;
import cn.wisenergy.web.shir.util.SessionUntil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
......@@ -39,7 +40,8 @@ public class AdminRealm extends AuthorizingRealm {
password,
accountInfo.getUserName()
);
SessionUntil sessionUntil = new SessionUntil();
sessionUntil.changeSession(2);
return authenticationInfo;
}
}
......@@ -5,7 +5,9 @@ import cn.wisenergy.model.app.User;
import cn.wisenergy.model.enums.SourceType;
import cn.wisenergy.service.cache.RedisService;
import cn.wisenergy.service.common.CachePrefix;
import cn.wisenergy.service.common.Common;
import cn.wisenergy.service.util.UserToken;
import cn.wisenergy.web.shir.util.SessionUntil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
......@@ -39,13 +41,16 @@ public class CodeRealm extends AuthorizingRealm {
}
String source = SourceType.getByCode(userInfo.getSource());
//获取短信验证码key
String key = CachePrefix.SMS_CODE.getPrefix() + source + "_" + userInfo.getPhone();
String code = redisService.get(key).toString();
String key = CachePrefix.SMS_CODE.getPrefix() + "_" + source + "_" + userInfo.getPhone();
Object obj = redisService.get(key);
String code = obj.toString();
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
userInfo,
code,
userInfo.getPhone()
);
SessionUntil sessionUntil = new SessionUntil();
sessionUntil.changeSession(1);
return authenticationInfo;
}
}
......@@ -3,6 +3,7 @@ package cn.wisenergy.web.shir.realm;
import cn.wisenergy.mapper.StaffMapper;
import cn.wisenergy.model.app.Staff;
import cn.wisenergy.service.util.UserToken;
import cn.wisenergy.web.shir.util.SessionUntil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
......@@ -37,6 +38,8 @@ public class StaffRealm extends AuthorizingRealm {
staff.getPassword(),
staff.getLoginName()
);
SessionUntil sessionUntil = new SessionUntil();
sessionUntil.changeSession(3);
return authenticationInfo;
}
}
......@@ -3,7 +3,9 @@ package cn.wisenergy.web.shir.realm;
import cn.wisenergy.mapper.UsersMapper;
import cn.wisenergy.model.app.User;
import cn.wisenergy.service.util.UserToken;
import cn.wisenergy.web.shir.util.SessionUntil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
......@@ -11,8 +13,11 @@ import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import java.io.Serializable;
public class UserRealm extends AuthorizingRealm {
@Autowired
private UsersMapper usersMapper;
......@@ -38,6 +43,8 @@ public class UserRealm extends AuthorizingRealm {
userInfo.getPassword(),
userInfo.getPhone()
);
return authenticationInfo;
}
}
package cn.wisenergy.web.shir.util;
import cn.wisenergy.model.app.AccountInfo;
import cn.wisenergy.model.app.Staff;
import cn.wisenergy.model.app.User;
import cn.wisenergy.web.shir.cache.MySessionManager;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.DefaultSessionKey;
import org.apache.shiro.subject.Subject;
import java.io.Serializable;
import java.util.Deque;
import java.util.LinkedList;
public class SessionUntil {
private boolean kickoutAfter = false; //踢出之前登录的/之后登录的用户 默认踢出之前登录的用户
private int maxSession = 1; //同一个帐号最大会话数 默认1
private MySessionManager sessionManager;
private Cache<String, Deque<Serializable>> cache;
public void setKickoutAfter(boolean kickoutAfter) {
this.kickoutAfter = kickoutAfter;
}
public void setMaxSession(int maxSession) {
this.maxSession = maxSession;
}
public void setSessionManager(MySessionManager sessionManager) {
this.sessionManager = sessionManager;
}
//设置Cache的key的前缀
public void setCacheManager(CacheManager cacheManager) {
this.cache = cacheManager.getCache("shiro_redis_cache");
}
public void changeSession(int type){
Subject subject = SecurityUtils.getSubject();
Session session = subject.getSession();
session.setTimeout(300000);
Serializable sessionId = session.getId();
String username = null;
Deque<Serializable> deque = null;
if(type == 1){
User user=(User)subject.getPrincipal();
username=user.getPhone();
}else if(type == 2){
AccountInfo account=(AccountInfo)subject.getPrincipal();
username=account.getUserName();
}else{
Staff staff=(Staff)subject.getPrincipal();
username=staff.getLoginName();
}
//读取缓存,没有就存入
deque = cache.get(username);
//如果此用户没有session队列,也就是还没有登录过,缓存中没有,就new一个空队列,不然deque对象为空,会报空指针
if (deque == null) {
deque = new LinkedList<>();
}
//如果队列里没有此sessionId,且用户没有被踢出;放入队列
if (!deque.contains(sessionId) && session.getAttribute("kickout") == null) {
//将sessionId存入队列
deque.push(sessionId);
//将用户的sessionId队列缓存
cache.put(username, deque);
}
//如果队列里的sessionId数超出最大会话数,开始踢人
while (deque.size() > maxSession) {
Serializable kickoutSessionId;
if (kickoutAfter) { //如果踢出后者
kickoutSessionId = deque.removeFirst();
//踢出后再更新下缓存队列
} else { //否则踢出前者
kickoutSessionId = deque.removeLast();
//踢出后再更新下缓存队列
}
cache.put(username, deque);
try {
//获取被踢出的sessionId的session对象
DefaultSessionKey defaultSessionKey = new DefaultSessionKey(kickoutSessionId);
Session kickoutSession = sessionManager.getSession(defaultSessionKey);
//Session kickoutSession = (Session) sessionManager.getSession(String.valueOf(new DefaultSessionKey(kickoutSessionId)));
if (kickoutSession != null) {
//设置会话的kickout属性表示踢出了
kickoutSession.setAttribute("kickout", true);
}
} catch (Exception e) {
}
}
}
}
......@@ -5,7 +5,7 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
/*@Component*/
public class SpringUtil implements ApplicationContextAware {
private static ApplicationContext applicationContext;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment