有关Session的碎碎念-ban掉cookie之后

有关Session的碎碎念-ban掉cookie之后

    java web中, 用session来表示用户浏览器(客户端)与服务器建立的一次会话。

    通常用sessionId来标记一个session,在Java中,有很简单的方式直接获取sessionId;

        HttpSession session = request.getSession();
        String sessionId = session.getId();

    但是sessionId并不是session的特性,实际上,sessionId是在客户端首次创建会话时将生成的sessionId存入cookie中,在之后的访问中直接读取这个id值。

    当客户端禁止了cookie行为后,SessionId在每次刷新页面时都会更新,利用id来表示会话也成为了妄想,此篇文章意在说明,如何操作能使SessionId能够独立于cookie使用。

    这种操作其实在shiro中已经被应用了,当我们进入登录页面中,url后会出现";jssionid=xxxxxx",将sessionid显示的标注在url中,可以使用:

response.encodeURL(url);

    当cookie被禁用时,该方法会在url后面添加字符,返回一个带有sessionid的url字符串,Java中会自动从中获取sessionId,可以直接使用如下方法处理我们要做转发的请求url:

response.encodeRedirectURL(request.getRequestURI());

    注意,encodeURL底层中核心逻辑代码是这样的:

@Override
public String encodeURL(String url) {
    //绝对url
    String absolute;
    try {
        absolute = toAbsolute(url);
    } catch (IllegalArgumentException iae) {
        // Relative URL
        return url;
    }
        
    if (isEncodeable(absolute)) {
        // W3c spec clearly said
        if (url.equalsIgnoreCase("")) {
            url = absolute;
        } else if (url.equals(absolute) && !hasPath(url)) {
            url += '/';
        }
        return (toEncoded(url, request.getSessionInternal().getIdInternal()));
    } else {
        return (url);
    }

}


protected boolean isEncodeable(final String location) {

    if (location == null) {
        return false;
    }

    // Is this an intra-document reference?
    if (location.startsWith("#")) {
        return false;
    }

    // Are we in a valid session that is not using cookies?
    final Request hreq = request;
    //这里的false指若session为空,不自动生成session
    final Session session = hreq.getSessionInternal(false);
    //这里session
    if (session == null) {
        return false;
    }
    //判断如果session来自cookie,则不作url处理
    if (hreq.isRequestedSessionIdFromCookie()) {
        return false;
    }

    // Is URL encoding permitted
    if (!hreq.getServletContext().getEffectiveSessionTrackingModes().
            contains(SessionTrackingMode.URL)) {
        return false;
    }

    if (SecurityUtil.isPackageProtectionEnabled()) {
        return (
            AccessController.doPrivileged(new PrivilegedAction<Boolean>() {

            @Override
            public Boolean run(){
                return Boolean.valueOf(doIsEncodeable(hreq, session, location));
            }
        })).booleanValue();
    } else {
        return doIsEncodeable(hreq, session, location);
    }
}

    很多版本的包中,判断session是否为空时,并没有生成新的session,若是用户禁止cookie,程序中也不会生成session,最终还是不能正确的做请求跳转,所以在跳转前,先做request.getSession()处理。

    获取url之后,我们要手动处理逻辑,可以使用拦截器进行统一内容处理,在拦截器中:

request.getSession(true);
String url=response.encodeURL(request.getRequestURI());
//不作处理会死循环
if(!url.equals(request.getRequestURI())){
    try {
        response.sendRedirect(url);
    } catch (IOException e) {
        //do something
    }
}else{
    
}


2019-03-08鱼鱼

{{blog.title}}

创建于 {{blog.createTimeStr}}   created  by  {{blog.author}} {{tag}}
最后修改于 {{blog.timelineStr}}
修改文档