下图是shiro中session的存放使用逻辑
使用shiro中的session的步骤
一、创建SessionFactory的实现类,实现createSession方法
@Override
public Session createSession(SessionContext initData){
OnlineSession session = new OnlineSession();
if (initData != null && initData instanceof WebSessionContext)
{
WebSessionContext sessionContext = (WebSessionContext) initData;
HttpServletRequest request = (HttpServletRequest) sessionContext.getServletRequest();
if (request != null)
{
UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
// 获取客户端操作系统
String os = userAgent.getOperatingSystem().getName();
// 获取客户端浏览器
String browser = userAgent.getBrowser().getName();
session.setHost(IpUtils.getIpAddr(request));
session.setBrowser(browser);
session.setOs(os);
}
}
return session;
}
二、创建OnlineSessionDAO类,继承EnterpriseCacheSessionDAO,重写doReadSession,update,doDelete三个方法
通过 service查询数据库中是否存在
@Override
protected Session doReadSession(Serializable sessionId)
{
return sysShiroService.getSession(sessionId);
}
@Override
public void update(Session session) throws UnknownSessionException
{
super.update(session);
}
//删除数据库中的session数据
@Override
protected void doDelete(Session session)
{
OnlineSession onlineSession = (OnlineSession) session;
if (null == onlineSession)
{
return;
}
onlineSession.setStatus(OnlineStatus.off_line);
sysShiroService.deleteSession(onlineSession);
}
三、创建OnlineSession类继承SimpleSession类,添加用户id,登录名、部门...我们的用户对象相关必要属性
@Data
public class OnlineSession extends SimpleSession {
private static final long serialVersionUID = 1L;
/**
* 用户ID
*/
private Long userId;
/**
* 用户名称
*/
private String loginName;
/**
* 部门名称
*/
private String deptName;
/**
* 用户头像
*/
private String avatar;
/**
* 浏览器类型
*/
private String browser;
/**
* 操作系统
*/
private String os;
/**
* 在线状态
*/
private OnlineStatus status = OnlineStatus.on_line;
/**
* 属性是否改变 优化session数据同步
*/
private transient boolean attributeChanged = false;
public void markAttributeChanged() {
this.attributeChanged = true;
}
public void resetAttributeChanged() {
this.attributeChanged = false;
}
public boolean isAttributeChanged() {
return attributeChanged;
}
@Override
public void setAttribute(Object key, Object value) {
super.setAttribute(key, value);
}
@Override
public Object removeAttribute(Object key) {
return super.removeAttribute(key);
}
}
四、将sessionDAO和SessionFactory注入到SecurityManager中
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealms(Arrays.asList(userRealm));
DefaultWebSessionManager manager = new DefaultWebSessionManager();
manager.setSessionDAO(sessionDAO());
// // 自定义sessionFactory
manager.setSessionFactory(sessionFactory());
securityManager.setSessionManager(sessionManager());
五、使用filter拦截请求
/**
-
自定义访问控制
/
@Slf4j
public class OnlineSessionFilter extends AccessControlFilter {
/*- 强制退出后重定向的地址
*/
@Value("${shiro.user.loginUrl}")
private String loginUrl;
private OnlineSessionDAO onlineSessionDAO;
/**
-
表示是否允许访问;mappedValue就是[urls]配置中拦截器参数部分,如果允许访问返回true,否则false;
*/
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
throws Exception {String userKey = "";
try {
String token = JwtUtil.getToken();
if (StringUtils.isNotEmpty(token)) {
String uuid = JwtUtil.getSubJectFromToken(token);
// 解析对应的权限以及用户信息
if (StringUtils.isBlank(uuid)) {
throw new Exception("user no login...");
}
userKey = JwtUtil.getTokenKey(uuid);
}
} catch (Exception e) {
log.error("获取用户信息异常'{}'", e.getMessage());
}
Subject subject = getSubject(request, response);
Session session = onlineSessionDAO.readSession(subject.getSession().getId());if (session != null && session instanceof OnlineSession) {
// session = onlineSessionDAO.readSession(userKey);
OnlineSession onlineSession = (OnlineSession) session;
request.setAttribute(ShiroConstants.ONLINE_SESSION, onlineSession);
// 把user对象设置进去
boolean isGuest = onlineSession.getUserId() == null || onlineSession.getUserId() == 0L;
if (isGuest == true) {
SysUser user = ShiroUtils.getSysUser();
if (user != null) {
onlineSession.setUserId(user.getUserId());
onlineSession.setLoginName(user.getLoginName());
onlineSession.setAvatar(user.getAvatar());
onlineSession.setDeptName(user.getDept().getDeptName());
onlineSession.markAttributeChanged();
}
}if (onlineSession.getStatus() == OnlineStatus.off_line) { return false; }
}
return true;
}
/**
- 表示当访问拒绝时是否已经处理了;如果返回true表示需要继续处理;如果返回false表示该拦截器实例已经处理了,将直接返回即可。
*/
@Override
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
Subject subject = getSubject(request, response);
if (subject != null) {
subject.logout();
}
saveRequestAndRedirectToLogin(request, response);
return false;
}
// 跳转到登录页
@Override
protected void redirectToLogin(ServletRequest request, ServletResponse response) throws IOException {
WebUtils.issueRedirect(request, response, loginUrl);
}public void setOnlineSessionDAO(OnlineSessionDAO onlineSessionDAO) {
this.onlineSessionDAO = onlineSessionDAO;
}
} - 强制退出后重定向的地址