侧边栏壁纸
博主头像
张种恩的技术小栈博主等级

行动起来,活在当下

  • 累计撰写 748 篇文章
  • 累计创建 65 个标签
  • 累计收到 39 条评论

目 录CONTENT

文章目录

安全/权限框架Shiro(13)之会话管理

zze
zze
2018-06-24 / 0 评论 / 0 点赞 / 392 阅读 / 4365 字

不定期更新相关视频,抖音点击左上角加号后扫一扫右方侧边栏二维码关注我~正在更新《Shell其实很简单》系列

相关 API

  • Subject.getSession() :即刻获取会话,等价于 Subject.getSession(true) ,即如果当前没有创建 Session 对象则会立即创建一个;而 Subject.getSession(false) 则是如果当前没有 Session 则返回 null
  • session.getId() :获取当前会话的唯一标识。
  • session.getHost() :获取当前会话的主机地址。
  • session.getTimeout()&session.setTimeout(毫秒) :获取/设置当前 Session 的过期时间。
  • session.getStartTimestamp()&session.getLastAccessTime() :获取会话的启动时间及最后访问时间。如果是 JavaSE 应用需要自己定期调用 session.touch() 去更新最后访问时间;如果是 web 应用,每次进入 ShiroFilter 都会自动调用 session.touch() 来更新最后访问时间。
  • session.touch()&session.stop() :更新会话最后访问时间及销毁会话。当执行 Subject.logout() 时会自动调用 session.stop() 方法来销毁会话。如果在 Web 应用程序中,调用 HttpSession.invalidate() 也会自动调用 Shiro 的 session.stop() 来销毁 Shiro 的会话。
  • session.setAttribute(key,val)&session.getAttribute(key)&session.removeAttribute(key) :设置/获取/删除会话属性。

Shiro 提供的 Session 有一个特点就是非侵入式,看如下示例:

// com.zze.shiro.web.controller.TestController
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpSession;

@Controller
public class TestController {

    @RequestMapping("testSession")
    public void test(HttpSession httpSession){
        httpSession.setAttribute("key","from HttpSessionValue");
        Session shiroSession = SecurityUtils.getSubject().getSession();
        Object key = shiroSession.getAttribute("key");
        System.out.println(key);
        //输出 from HttpSessionValue
    }
}

在上面代码中,我们往当前的 HttpSession 实例中存放了一个键值对,接着我们从 Shiro 提供的 Session 中获取到了之前存放在 HttpSession 中的键值对。这个现象说明了我们可以在当前会话中的任意位置获取到 Session 中的数据,例如 Service 中。

会话监听器

会话监听器用于监听会话的创建、过期即停止事件。需要实现 SessionListener 接口:

package org.apache.shiro.session;

public interface SessionListener {
    // 会话开始
    void onStart(Session session);
    // 会话销毁
    void onStop(Session session);
    // 会话过期
    void onExpiration(Session session);
}

使用如下:

1、自定义一个会话监听器类:

// com.zze.shiro.web.listener.ShiroSessionListener
import org.apache.shiro.session.Session;
import org.apache.shiro.session.SessionListener;

public class ShiroSessionListener implements SessionListener {
    public void onStart(Session session) {
        System.out.println("session 创建");
    }

    public void onStop(Session session) {
        System.out.println("session 销毁");
    }

    public void onExpiration(Session session) {
        System.out.println("session 过期");
    }
}

2、在 Spring 核心配置文件中配置会话管理器,注入自定义会话监听器,接着把会话管理器注入给安全管理器:

<!-- 自定义session监听器 -->
<bean id="shiroSessionListener" class="com.zze.shiro.web.listener.ShiroSessionListener"/>
<!-- 会话管理器 -->
<bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager">
    <property name="sessionListeners">
        <list>
            <ref bean="shiroSessionListener"/>
        </list>
    </property>
</bean>

<!--
配置安全管理器 SecurityManager
-->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    <property name="cacheManager" ref="cacheManager"/>
    <property name="authenticator" ref="authenticator"/>
    <!--配置多 Realm-->
    <property name="realms">
        <list>
            <ref bean="jdbcRealm"/>
            <ref bean="secondRealm"/>
        </list>
    </property>
    <property name="sessionManager" ref="sessionManager"/>
</bean>
0

评论区