shiro 减少用redis实现的自定义SessionDAO的doUpdate的调用次数

由于SimpleSession lastAccessTime更改后也会调用SessionDao update方法,更新的字段只有LastAccessTime(最后一次访问时间),由于会话失效是由Redis数据过期实现的,这个字段意义不大,为了减少对Redis的访问,降低网络压力,实现自己的Session,在SimpleSession上套一层,增加一个标识位,如果Session除lastAccessTime意外其它字段修改,就标识一下,只有标识为修改的才可以通过doUpdate访问Redis,否则直接返回。


import org.apache.shiro.session.mgt.SimpleSession;  
  
import java.io.Serializable;  
import java.util.Date;  
import java.util.Map;  
  
  
/** 
 * 由于SimpleSession lastAccessTime更改后也会调用SessionDao update方法, 
 * 增加标识位,如果只是更新lastAccessTime SessionDao update方法直接返回 
 */  
public class ShiroSession extends SimpleSession implements Serializable {  
    // 除lastAccessTime以外其他字段发生改变时为true  
    private boolean isChanged;  
  
    public ShiroSession() {  
        super();  
        this.setChanged(true);  
    }  
  
    public ShiroSession(String host) {  
        super(host);  
        this.setChanged(true);  
    }  
  
  
    @Override  
    public void setId(Serializable id) {  
        super.setId(id);  
        this.setChanged(true);  
    }  
  
    @Override  
    public void setStopTimestamp(Date stopTimestamp) {  
        super.setStopTimestamp(stopTimestamp);  
        this.setChanged(true);  
    }  
  
    @Override  
    public void setExpired(boolean expired) {  
        super.setExpired(expired);  
        this.setChanged(true);  
    }  
  
    @Override  
    public void setTimeout(long timeout) {  
        super.setTimeout(timeout);  
        this.setChanged(true);  
    }  
  
    @Override  
    public void setHost(String host) {  
        super.setHost(host);  
        this.setChanged(true);  
    }  
  
    @Override  
    public void setAttributes(Map<Object, Object> attributes) {  
        super.setAttributes(attributes);  
        this.setChanged(true);  
    }  
  
    @Override  
    public void setAttribute(Object key, Object value) {  
        super.setAttribute(key, value);  
        this.setChanged(true);  
    }  
  
    @Override  
    public Object removeAttribute(Object key) {  
        this.setChanged(true);  
        return super.removeAttribute(key);  
    }  
  
    /** 
     * 停止 
     */  
    @Override  
    public void stop() {  
        super.stop();  
        this.setChanged(true);  
    }  
  
    /** 
     * 设置过期 
     */  
    @Override  
    protected void expire() {  
        this.stop();  
        this.setExpired(true);  
    }  
  
    public boolean isChanged() {  
        return isChanged;  
    }  
  
    public void setChanged(boolean isChanged) {  
        this.isChanged = isChanged;  
    }  
  
    @Override  
    public boolean equals(Object obj) {  
        return super.equals(obj);  
    }  
  
    @Override  
    protected boolean onEquals(SimpleSession ss) {  
        return super.onEquals(ss);  
    }  
  
    @Override  
    public int hashCode() {  
        return super.hashCode();  
    }  
  
    @Override  
    public String toString() {  
        return super.toString();  
    }  
}  


import org.apache.commons.lang3.StringUtils;  
import org.apache.shiro.session.Session;  
import org.apache.shiro.session.mgt.SessionContext;  
import org.apache.shiro.session.mgt.SessionFactory;  
import org.apache.shiro.web.session.mgt.DefaultWebSessionContext;  
import org.slf4j.Logger;  
import org.slf4j.LoggerFactory;  
  
import javax.servlet.http.HttpServletRequest;  
  
public class ShiroSessionFactory implements SessionFactory {  
    private static final Logger logger = LoggerFactory.getLogger(ShiroSessionFactory.class);  
  
    @Override  
    public Session createSession(SessionContext initData) {  
        ShiroSession session = new ShiroSession();  
        HttpServletRequest request = (HttpServletRequest)initData.get(DefaultWebSessionContext.class.getName() + ".SERVLET_REQUEST");  
        session.setHost(getIpAddress(request));  
        return session;  
    }  
  
    public static String getIpAddress(HttpServletRequest request) {  
        String localIP = "127.0.0.1";  
        String ip = request.getHeader("x-forwarded-for");  
        if (StringUtils.isBlank(ip) || (ip.equalsIgnoreCase(localIP)) || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("Proxy-Client-IP");  
        }  
        if (StringUtils.isBlank(ip) || (ip.equalsIgnoreCase(localIP)) || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("WL-Proxy-Client-IP");  
        }  
        if (StringUtils.isBlank(ip) || (ip.equalsIgnoreCase(localIP)) || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getRemoteAddr();  
        }  
        return ip;  
    }  
}  


在自定义的RedisDAO中的做判断

    /** 
     * 更新会话;如更新会话最后访问时间/停止会话/设置超时时间/设置移除属性等会调用 
     */  
    @Override  
    protected void doUpdate(Session session) {  
        //如果会话过期/停止 没必要再更新了  
        try {  
            if (session instanceof ValidatingSession && !((ValidatingSession) session).isValid()) {  
                return;  
            }  

            if (session instanceof ShiroSession) {  
                // 如果没有主要字段(除lastAccessTime以外其他字段)发生改变  
                ShiroSession ss = (ShiroSession) session;  
                if (!ss.isChanged()) {  
                    return;  
                }  
                //更新redis
                ......				
        } catch (Exception e) {  
            logger.warn("更新Session失败", e);  
        }   
    }  


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Spring Boot是一个用于快速开发Java应用程序的开源框架,Shiro是一个强大且易于使用的Java安全框架,Redis是一个开源的内存数据库。结合使用这些技术可以实现单点登录功能。 在Spring Boot中使用Shiro来处理认证和授权,可以通过配置Shiro的Realm来实现用户的登录认证和权限控制。将用户的信息存储在Redis中,利用Redis的持久化特性来实现用户登录状态的共享和存储。 首先,在Spring Boot项目的配置文件中配置Redis的连接信息,以便连接到Redis数据库。 然后,创建一个自定义Shiro的Realm,在其中重写认证和授权的方法。在认证方法中,将用户的登录信息存储到Redis中,以便其他服务可以进行验证。在授权方法中,根据用户的角色和权限进行相应的授权操作。 接着,在Spring Boot项目的配置类中配置Shiro的相关设置,包括Realm、Session管理器、Cookie管理器等。 最后,可以在Controller层中使用Shiro的注解来标记需要进行认证和授权的接口,以确保只有登录后且具备相应权限的用户才能访问这些接口。 总的来说,通过使用Spring Boot、ShiroRedis的组合,可以实现单点登录的功能。用户在登录后,将登录信息存储到Redis中,其他服务可以通过验证Redis中的数据来判断用户的登录状态。同时,Shiro提供了强大的认证和授权功能,可以确保只有具备相应权限的用户才能访问受保护的接口。这些功能的具体实现可以通过深入研究Spring Boot、ShiroRedis的源码来了解。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值