shiro:sessionManager配置

1.使用session

    Subject currentUser = SecurityUtils.getSubject();
    Session session = currentUser.getSession(); 
    session.setAttribute("someKey", someValue);   
 
    //subject.getSession()方法是调用 currentUser.getSubject(true)的快捷方式。   
    //对于那些熟悉 HttpServletRequest API 的,Subject.getSession(boolean create)方法与 HttpServletRequest.getSession(boolean create)方法有着异曲同工之效。 
    // 如果该 Subject 已经拥有一个 Session,则 boolean 参数被忽略且 Session 被立即返回。
    // 如果该 Subject 还没有一个 Session 且 create 参数为 true,则创建一个新的会话并返回该会话。
    //如果该 Subject 还没有一个 Session 且 create 参数为 false,则不会创建新的会话且返回 null。
    //当开发框架代码来确保一个 Session 没有被创建是没有必要的时候,subject.getSession(false)可以起到很好的作用

2.配置sessionManager

默认的 SecurityManger 实现是默认使用立即可用的 DefaultSessionManager
DefaultSessionManager 的实现提供一个 应用程序所需的所有企业级会话管理,如 Session 验证,orphan cleanup,等等。这可以在任何应用程序中使用

/**
     * Session Manager:会话管理
     * 即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;
     * 会话可以是普通JavaSE环境的,也可以是如Web环境的;
     */
    @Bean("sessionManager")
    public SessionManager sessionManager(){
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        //设置session过期时间
        sessionManager.setGlobalSessionTimeout(60 * 60 * 1000);
        //定期验证session
        sessionManager.setSessionValidationSchedulerEnabled(true);
        //删除无效session
        sessionManager.setDeleteInvalidSessions(true);
        // 去掉shiro登录时url里的JSESSIONID
        sessionManager.setSessionIdUrlRewritingEnabled(false);
        //设置sessionDAO
        sessionManager.setSessionDAO(sessionDAO());
        sessionManager.setSessionIdCookieEnabled(true);
        return sessionManager;
    }

	@Bean(name = "sessionDao")
    public RedisSessionDao sessionDAO(){
        return new RedisSessionDao(redisTemplate());
    }

    @Bean(name = "redisTemplate")
    public RedisTemplate<Serializable, Session> redisTemplate() {
        RedisTemplate<Serializable, Session> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory());
        return template;
    }

    @Bean
    public JedisConnectionFactory connectionFactory() {
        String redisHost = "127.0.0.1";
        String redisPort = "6379";
        //redis配置单节点
        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
        redisStandaloneConfiguration.setHostName(redisHost);
        redisStandaloneConfiguration.setPort(Integer.parseInt(redisPort));
        JedisConnectionFactory conn = new JedisConnectionFactory(redisStandaloneConfiguration);
        conn.setTimeout(10000);
        return conn;
    }

3.sessionDAO

1.什么是sessionDAO,有什么意义?

每当一个会话被创建或更新时,它的数据需要持久化到一个存储位置以便它能够被稍后的应用程序访问。同样地, 当一个会话失效且不再被使用时,它需要从存储中删除以便会话数据存储空间不会被耗尽。SessionManager 实现委 托这些 Create/Read/Update/Delete(CRUD)操作为内部组件,同时,SessionDAO,反映了数据访问对象(DAO)设计 模式。 SessionDAO 的权力是你能够实现该接口来与你想要的任何数据存储进行通信。这意味着你的会话数据可以驻留在内 存中,文件系统,关系数据库或 NoSQL 的数据存储,或其他任何你需要的位置。你得控制持久性行为。

2.shiro中的sessionDAO

    //顶层接口,定义了增删改查的方法
  
    public interface SessionDAO {
        Serializable create(Session var1);
    
        Session readSession(Serializable var1) throws UnknownSessionException;
    
        void update(Session var1) throws UnknownSessionException;
    
        void delete(Session var1);
    
        Collection<Session> getActiveSessions();
    }

    //抽象实现类
    public abstract class AbstractSessionDAO implements SessionDAO{
          ..........
    }

    //四个实现类
    public class RedisSessionDAO extends AbstractSessionDAO {}
    public abstract class CachingSessionDAO extends AbstractSessionDAO implements CacheManagerAware {}
    public class EnterpriseCacheSessionDAO extends CachingSessionDAO {}
    public class MemorySessionDAO extends AbstractSessionDAO {

3.redisSessionDAO

package com.mye.hl19springbootshiro.shiro;

import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.TimeUnit;


@Component
public class RedisSessionDao extends AbstractSessionDAO {
    private static final String ACTIVE_SESSION = "atv:session:";
    private static final Logger logger = LoggerFactory.getLogger(RedisSessionDao.class);

    private final RedisTemplate<Serializable, Session> redisTemplate;
    private final ValueOperations<Serializable, Session> sessionOperations;

    public RedisSessionDao(RedisTemplate<Serializable, Session> redisTemplate) {
        this.redisTemplate = redisTemplate;
        sessionOperations = redisTemplate.opsForValue();
    }

    //序列化方法
    @Override
    protected Serializable doCreate(Session session) {
        final Serializable sessionId = generateSessionId(session);
        assignSessionId(session, sessionId);
        sessionOperations.set(sessionId, session, 3600, TimeUnit.SECONDS);
        return sessionId;
    }

    //读取session
    @Override
    protected Session doReadSession(Serializable sessionId) {
        return sessionOperations.get(sessionId);
    }

    //缓存更新
    @Override
    public void update(Session session) throws UnknownSessionException {
        sessionOperations.set(session.getId(), session, 3600, TimeUnit.SECONDS);
    }

    //删除缓存
    @Override
    public void delete(Session session) {
        final Serializable sessionId = session.getId();
        redisTemplate.delete(sessionId);
    }

    //读取缓存
    @Override
    public Collection<Session> getActiveSessions() {
        return Collections.emptySet();
    }
}
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐