Shiro (http:/xxxxx/;JSESSIONID=xxxx) InvalidRequestFilter 400无法跳转到登录页问题

39 篇文章 3 订阅

shiro: 1.6

spring: 5.2

访问:http://localhost:8080/demo/;JSESSIONID=655def62-75b3-4ab1-ae27-b7d0e42c431a时, 出现400错误页面,无法跳转到登录页。

当浏览器本地cookie禁用或者部分链接跳转时,会默认加上 ;JSESSIONID=  参数传递cookie中存储的sessionId, 后端Filter过滤器会首先尝试从cookie中获取sessionId,获取不到时尝试解析uri连接(;/JSESSIONID=xxx)获取sessionId,再获取不到尝试从请求参数中获取。

正常情况下,访问该链接,若session过期,会自动跳转到登录页。

但是再shiro:1.6开始,新增了一个InvalidRequestFilter的过滤器,用于拦截存在安全问题的uri,该过滤器拦截三种类型的uri并返回400拒绝访问:(http://xxx/;JSESSIONID=xxx中存在分号)

public class InvalidRequestFilter extends AccessControlFilter {

    private static final List<String> SEMICOLON = Collections.unmodifiableList(Arrays.asList(";", "%3b", "%3B"));

    private static final List<String> BACKSLASH = Collections.unmodifiableList(Arrays.asList("\\", "%5c", "%5C"));

    // 拦截uri地址中存在分号的请求
    private boolean blockSemicolon = true;
    // 拦截uri中存在反斜杠的请求
    private boolean blockBackslash = true;
    // 拦截uri中存在非ascii码的请求
    private boolean blockNonAscii = true;


    ....省略....


    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        String uri = WebUtils.toHttp(request).getRequestURI();
        return !containsSemicolon(uri)
            && !containsBackslash(uri)
            && !containsNonAsciiCharacters(uri);
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        WebUtils.toHttp(response).sendError(400, "Invalid request");
        return false;
    }
}

对于所有进来的请求,过滤器都会进行一次前置和后置判断,确认是否继续执行剩余未执行的过滤器。

AdviceFilter:

    public void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain)
            throws ServletException, IOException {

        Exception exception = null;

        try {
            // 当请求uri被认为不合法是返回false
            boolean continueChain = preHandle(request, response);
            if (log.isTraceEnabled()) {
                log.trace("Invoked preHandle method.  Continuing chain?: [" + continueChain + "]");
            }

            if (continueChain) {
                executeChain(request, response, chain);
            }

            postHandle(request, response);
            if (log.isTraceEnabled()) {
                log.trace("Successfully invoked postHandle method");
            }

        } catch (Exception e) {
            exception = e;
        } finally {
            cleanup(request, response, exception);
        }
    }

preHandle方法最终实现再AccessControlFilter中:

    public boolean onPreHandle(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
        // 这两个方法就是InvalidRequestFilter中的方法,InvalidRequestFilter是AccessControlFilter的子类
        return isAccessAllowed(request, response, mappedValue) || onAccessDenied(request, response, mappedValue);
    }

处理方法主要有三种:

1. xml配置覆盖默认的InvalidRequestFilter:  blockSemicolon设置为false

	<bean id="invalidRequestFilter" class="org.apache.shiro.web.filter.InvalidRequestFilter">
		<property name="blockSemicolon" value="false" />
	</bean>

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
         ....省略...
		<property name="filters">
			<map>
                名字key要与默认(invalidRequest)的相同才能覆盖初始化时的InvalidRequestFilter
				<entry key="invalidRequest" value-ref="invalidRequestFilter" />
			</map>
		</property>
	</bean>

2. shiro降到1.6之前(或许1.6之后有改进,暂时没有关注)

3. 自定义ShiroFilter并设置setEnable(false) 将不在进行上述三种类型uri安全性拦截

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值