首页 > 其他分享 >shiro中session的使用

shiro中session的使用

时间:2024-07-24 17:22:11浏览次数:13  
标签:String request private onlineSession session 使用 public shiro

下图是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;
    }
    }

标签:String,request,private,onlineSession,session,使用,public,shiro
From: https://www.cnblogs.com/velloLei/p/18321299

相关文章

  • php使用ZipArchive解压压缩包
    //处理照片压缩包$zip=new\ZipArchive();//获取压缩包内容照片数量$path='static/oa/img/staImport/'.date('Ymd').'/'.date('His');if($zip->open($param['fileUrl'])===TRU......
  • 在WPS的表格 里使用VBA,批量进行替换内容
    需求:在今日的工作过程中,发现有大量的内容需要从另外一个表格前两列里匹配进行替换。从编号替换成具体内容,但是有一些地方编号有多个用逗号连接在一起,需要先分隔开来。解决方案:找了很多方案,但是没有现成的公式能满足这个需求,简单的脚本无法满足,于是找了宏脚本,先录制一个简单的替换......
  • 泰凌微8258学习日记-6:LCD屏幕的点亮以及使用
            点亮LCD对我而言算是比较难的操作了,在了解到LCD点亮的步骤以后(开SPI,导入LCD驱动,主函数调用),我开始学习LCD的引脚功能,SPI如何使用,后面拿到中景园给的LCD例程(STM32的),修改LCD驱动(这一步是最难的)。好在有位大哥帮我,也是顺利完成了驱动的修改。......
  • 如何使用 instaloader 下载特定数量的照片(而不是整个帖子)
    我正在使用名为instaloader的Instagramapi。我正在尝试从数组中的每个配置文件下载25张图片。我尝试使用get_postsforpostinprofile.get_posts():#downloadpostsL.download_post(post,target=data_path/p_name)但这会下载图片以及所有评论和元......
  • 如何使用 Google Drive API 识别和删除大型 Google Takeout ZIP 文件?
    如何使用GoogleDriveAPI识别和删除大型GoogleTakeoutZIP文件?正文:我遇到一个问题:GoogleTakeout不断在我的Google云端硬盘中创建大型ZIP文件,导致其达到存储限制。我需要使用GoogleDriveAPI以编程方式识别和删除这些文件。我注意到文件名遵循类似takeou......
  • Ubuntu中如何使用Update-rc.d命令(转)
    在Ubuntu中,update-rc.d命令用于管理系统的服务(init脚本)的启动和停止顺序。它允许你将服务添加到特定的运行级别,并设置服务在系统启动时是否自动启动。以下是一些常用的update-rc.d命令示例及其说明:添加服务到特定运行级别:sudo update-rc.d  defaults将指定的服务添加到默认......
  • 如何使用 mypy 的类型检查来强制可调用类型的签名
    我有一个函数,它接受另一个函数x作为其参数。函数x可以有2种不同类型的签名,我想通过类型提示来强制执行此操作:TYPE_A=Callable[[int,int],int]TYPE_B=Callable[[int],int]defmy_func(x:Union[TYPE_A,TYPE_B])->None:...determinexisofwhichtype......
  • 每日一面—— 不使用任何中间变量如何将a、b的值进行交换
    请参考以下C++程序代码。1#include<stdio.h>23voidswap1(int&a,int&b)4{5inttemp=a;//使用局部变量temp完成交换6a=b;7b=temp;8};910voidswap2(int&a,int&b)11{12a=a+b;//使用加减运算完成交换13b=a-b;14......
  • Windows使用NVM管理node.js
    NVM(NodeVersionManager)是一个开源的命令行工具,用于管理多个版本的Node.js在同一台计算机上。NVM允许开发者轻松地安装、切换和管理不同版本的Node.js,这对于在多个项目上工作或测试Node.js的不同特性时非常有用。在macOS或Linux上,通常通过curl或wget下载安......
  • ETL工具Kettle使用总结
    好久没有发布文章了,就用最近工作常用的kettle工具做为素材写一下随笔,方便以后碰到相同的问题快速解决。kettle的简介我就不介绍了,大家随便百度一下就可以查到,主要作用就是用于从一个或多个数据源中提取数据,对数据进行转换和清洗(这个过程就是ETL),然后加载到目标数据存储中,以......