sessionIdUrlRewritingEnabled无效问题处理

为了处理shiro自动跳转登录也面不自动在URL后面拼接:JSESSIONID,逐步排查定位到shiro,根据资料需要增加sessionIdUrlRewritingEnabled的配置,但是增加后依然无效。

而且我发现在我使用的1.7.1版本的shiro里,sessionIdUrlRewritingEnabled的初始值已经被设置成false了,所以根本不需要再设置。

public class DefaultWebSessionManager extends DefaultSessionManager implements WebSessionManager {
    private static final Logger log = LoggerFactory.getLogger(DefaultWebSessionManager.class);
    private Cookie sessionIdCookie;
    private boolean sessionIdCookieEnabled;
    private boolean sessionIdUrlRewritingEnabled;

    public DefaultWebSessionManager() {
        Cookie cookie = new SimpleCookie("JSESSIONID");
        cookie.setHttpOnly(true);
        this.sessionIdCookie = cookie;
        this.sessionIdCookieEnabled = true;
        this.sessionIdUrlRewritingEnabled = false;
    }

那么问题出在哪里?

后续经过排查,问题出在项目中sessionManager是继承的DefaultWebSessionManager,

重写了getSessionId方法,主要是为了自定义获取sessionid的途径,在分析原super.getSessionId

方法的源码后发现一下代码,这里可以看到sessionIdUrlRewritingEnabled这个配置是在第一次请求获取sessionid的时候设置到request里面的,后续的跳转也会根据这个配置设置url后面的JSESSIONID:

 private Serializable getReferencedSessionId(ServletRequest request, ServletResponse response) {
        String id = this.getSessionIdCookieValue(request, response);
        if (id != null) {
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, "cookie");
        } else {
            id = this.getUriPathSegmentParamValue(request, "JSESSIONID");
            if (id == null) {
                String name = this.getSessionIdName();
                id = request.getParameter(name);
                if (id == null) {
                    id = request.getParameter(name.toLowerCase());
                }
            }

            if (id != null) {
                request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, "url");
            }
        }

        if (id != null) {
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
        }

        request.setAttribute(ShiroHttpServletRequest.SESSION_ID_URL_REWRITING_ENABLED, this.isSessionIdUrlRewritingEnabled());
        return id;
    }

所以修改如下,在自定义的getSessionId方法里也增加request的这几个信息

	@Override
	protected Serializable getSessionId(ServletRequest request, ServletResponse response) {

		String sid = request.getParameter("__sid");
		if (StringUtils.isNotBlank(sid)) { 
			request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, "url");
			request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, sid);
			request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
			//禁止在url上拼接SessionId
			request.setAttribute(ShiroHttpServletRequest.SESSION_ID_URL_REWRITING_ENABLED, this.isSessionIdUrlRewritingEnabled());

        	return sid;
		}else{
			return super.getSessionId(request, response);
		}
	}

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
在 Shiro 中,SessionManager 负责管理用户的会话信息,其主要职责包括创建、获取、删除和管理会话等。下面是一个简单的 Shiro SessionManager 的配置示例: ```xml <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"> <!-- session过期时间,单位:毫秒 --> <property name="globalSessionTimeout" value="1800000" /> <!-- 是否开启URL地址栏中的SessionID重写 --> <property name="sessionIdUrlRewritingEnabled" value="false" /> <!-- 是否开启删除无效的session对象 --> <property name="deleteInvalidSessions" value="true" /> <!-- 是否开启定时调度器检测失效的session对象 --> <property name="sessionValidationSchedulerEnabled" value="true" /> <!-- 定时清理失效session的时间间隔,单位:毫秒;默认1小时 --> <property name="sessionValidationInterval" value="3600000" /> <!-- 会话DAO --> <property name="sessionDAO" ref="redisSessionDAO" /> </bean> ``` 其中,`DefaultWebSessionManager` 是 Shiro 默认提供的 Web 环境下的 SessionManager 实现类,我们可以通过配置它的属性来实现相关功能。具体的属性含义如下: - `globalSessionTimeout`:会话超时时间,单位为毫秒,默认为30分钟。 - `sessionIdUrlRewritingEnabled`:是否在URL地址栏中重写Session ID,默认为false,建议不开启,因为这会让URL泄漏了Session ID,存在安全风险。 - `deleteInvalidSessions`:是否开启删除无效Session对象,默认为true,表示当Session超时或者被踢出时自动删除相应的Session对象。 - `sessionValidationSchedulerEnabled`:是否开启定时调度器检测失效的Session对象,默认为true,表示在应用启动时会启动一个定时任务,定期检测失效的Session并删除它们。 - `sessionValidationInterval`:定时清理失效Session的时间间隔,单位为毫秒,默认为1小时。 - `sessionDAO`:指定会话DAO,即会话的存储方式。这里我们使用 Redis 作为会话存储方式,所以指定了 `redisSessionDAO`。 需要注意的是,如果要使用 Redis 作为会话存储方式,还需要配置相应的 `redisSessionDAO`。具体的配置可以参考下面的示例: ```xml <bean id="redisSessionDAO" class="org.crazycake.shiro.RedisSessionDAO"> <!-- 配置RedisManager --> <property name="redisManager" ref="redisManager" /> <!-- session在Redis中的过期时间,单位是秒 --> <property name="expire" value="1800" /> </bean> <bean id="redisManager" class="org.crazycake.shiro.RedisManager"> <!-- Redis服务器地址,格式为:host:port --> <property name="host" value="127.0.0.1:6379" /> <!-- Redis服务器连接超时时间,单位为毫秒,默认为2000ms --> <property name="timeout" value="2000" /> <!-- Redis服务器密码,如果没有设置可以不填 --> <property name="password" value="your_password" /> <!-- Redis数据库编号,默认为0 --> <property name="database" value="0" /> </bean> ``` 其中,`RedisSessionDAO` 是一个实现了 Shiro `SessionDAO` 接口的 Redis Session 存储类。`RedisManager` 则是一个 Redis 连接管理类,用于管理与 Redis 服务器的连接。需要注意的是,上面的 `redisSessionDAO` 和 `redisManager` 需要通过 Spring 容器进行管理,所以需要在 Spring 配置文件中进行相应的配置。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值