今天看啥
热点:

Tomcat部署应用,客户端阻止cookie时,成功登录后,还是出现登录失败的问题解决,tomcatcookie


一、提出问题

如果用户浏览器设置的阻止cookie,当服务器完成登录后,并标记当前session已登录,那么在浏览器进入转向页面时,可能出现引入js无法下载,点击页面中超链接后提示用户未登录。

二、解决问题

使用response.encodeURL(“url”)。

   <script type="text/javascript" src="<%=response.encodeURL("jquery/jquery-min.js") %>" charset="UTF-8"></script>
   <a href="<%=response.encodeURL("download.do?id=1") %>">下载文件</>
最终渲染到浏览器时,查看源代码,内容变为:

	<script type="text/javascript" src="jquery/jquery-min.js;jsessionid=FEF549911390D7ADC6E85D06128405CF" charset="UTF-8"></script>
	<a href="download.do;jsessionid=FEF549911390D7ADC6E85D06128405CF?id=1">下载文件</>

三、追根求底

查看Tomcat源代码(http://blog.csdn.net/asiaasia666/article/details/45870049)。  request实现:org.apache.coyote.tomcat5.CoyoteRequestFacade
  session实现:org.apache.catalina.session.StandardSessionFacade
  response实现:org.apache.coyote.tomcat5.CoyoteResponseFacade

3.1,session创建

时机:request.getSession 方法时  。 贴代码吧
/**
 * Wrapper object for the Coyote request.
 *
 * @author Remy Maucherat
 * @author Craig R. McClanahan
 * @version $Revision: 1.37 $ $Date: 2004/06/07 16:54:58 $
 */

public class CoyoteRequest
    implements HttpRequest, HttpServletRequest {

    /**
     * Return the session associated with this Request, creating one
     * if necessary.
     */
    public HttpSession getSession() {
        return (getSession(true));
    }


    /**
     * Return the session associated with this Request, creating one
     * if necessary and requested.
     *
     * @param create Create a new session if one does not exist
     */
    public HttpSession getSession(boolean create) {
        
        return doGetSession(create);

    }

    protected HttpSession doGetSession(boolean create) {

        // There cannot be a session if no context has been assigned yet
        if (context == null)
            return (null);

        // Return the current session if it exists and is valid
        if ((session != null) && !session.isValid())
            session = null;
        if (session != null)
            return (session.getSession());

        // Return the requested session if it exists and is valid
        Manager manager = null;
        if (context != null)
            manager = context.getManager();
        if (manager == null)
            return (null);      // Sessions are not supported
        if (requestedSessionId != null) {
            try {
                session = manager.findSession(requestedSessionId);
            } catch (IOException e) {
                session = null;
            }
            if ((session != null) && !session.isValid())
                session = null;
            if (session != null) {
                session.access();
                return (session.getSession());
            }
        }

        // Create a new session if requested and the response is not committed
        if (!create)
            return (null);
        if ((context != null) && (response != null) &&
            context.getCookies() &&
            response.getResponse().isCommitted()) {
            throw new IllegalStateException
              (sm.getString("coyoteRequest.sessionCreateCommitted"));
        }

        //*****************************
        //  mahh 就是此时在创建session
        //*****************************        
        session = manager.createSession();

        // Creating a new session cookie based on that session
        if ((session != null) && (getContext() != null)
               && getContext().getCookies()) {
            Cookie cookie = new Cookie(Globals.SESSION_COOKIE_NAME,
                                       session.getId());
            configureSessionCookie(cookie);
            ((HttpServletResponse) response).addCookie(cookie);
        }

        if (session != null) {
            session.access();
            return (session.getSession());
        } else {
            return (null);
        }

    }


    /**
     * Configures the given JSESSIONID cookie.
     *
     * @param cookie The JSESSIONID cookie to be configured
     */
    protected void configureSessionCookie(Cookie cookie) {
        cookie.setMaxAge(-1);
        String contextPath = null;
        if (getContext() != null) {
            contextPath = getContext().getPath();
        }
        if ((contextPath != null) && (contextPath.length() > 0)) {
            cookie.setPath(contextPath);
        } else {
            cookie.setPath("/");
        }
        if (isSecure()) {
            cookie.setSecure(true);
        }
    }
}

其中manager.createSession();创建了session对象,创建sessionId,并放入HashMap中缓存。创建sessionId的代码请参照http://blog.csdn.net/asiaasia666/article/details/45870229
/**
 * Minimal implementation of the <strong>Manager</strong> interface that supports
 * no session persistence or distributable capabilities.  This class may
 * be subclassed to create more sophisticated Manager implementations.
 *
 * @author Craig R. McClanahan
 * @version $Revision: 1.27 $ $Date: 2004/05/26 16:13:59 $
 */

public abstract class ManagerBase implements Manager, MBeanRegistration {

    /**
     * Construct and return a new session object, based on the default
     * settings specified by this Manager's properties.  The session
     * id will be assigned by this method, and available via the getId()
     * method of the returned session.  If a new session cannot be created
     * for any reason, return <code>null</code>.
     *
     * @exception IllegalStateException if a new session cannot be
     *  instantiated for any reason
     */
    public Session createSession() {

        // Recycle or create a Session instance
        Session session = createEmptySession();

        // Initialize the properties of the new session and return it
        session.setNew(true);
        session.setValid(true);
        session.setCreationTime(System.currentTimeMillis());
        session.setMaxInactiveInterval(this.maxInactiveInterval);
        String sessionId = generateSessionId();

        String jvmRoute = getJvmRoute();
        // @todo Move appending of jvmRoute generateSessionId()???
        if (jvmRoute != null) {
            sessionId += '.' + jvmRoute;
        }
        synchronized (sessions) {
            while (sessions.get(sessionId) != null){ // Guarantee uniqueness
                duplicates++;
                sessionId = generateSessionId();
                // @todo Move appending of jvmRoute generateSessionId()???
                if (jvmRoute != null) {
                    sessionId += '.' + jvmRoute;
                }
            }
        }

        session.setId(sessionId);
        sessionCounter++;

        return (session);

    }


    /**
     * Get a session from the recycled ones or create a new empty one.
     * The PersistentManager manager does not need to create session data
     * because it reads it from the Store.
     */
    public Session createEmptySession() {
        return (getNewSession());
    }
    /**
     * Get new session class to be used in the doLoad() method.
     */
    protected StandardSession getNewSession() {
        return new StandardSession(this);
    }

}

3.2,session如何存储

在org.apache.catalina.session.StandardManager extends ManagerBase的属性HashMap sessions中存储,key为sessionid,value为CoyoteRequest对象。 (通过工厂模式,保证整个应用ManagerBase只有一个对象的存在。)
public abstract class ManagerBase implements Manager, MBeanRegistration {
    /**
     * The set of currently active Sessions for this Manager, keyed by
     * session identifier.
     */
    protected HashMap sessions = new HashMap();
}

3.3,如何识别一个请求是否存在session

如果知道这次请求的sessionId,那么从HashMap sessions中是可以取到sesion对象的。问题转换为如何寻找sessionId? 一种是Cookie方式,即浏览器请求时会将cookie传递到Tomcat中,如果有name=JSESSIONID的Cookie,那么这个Cookie的值就是sessionId。 另一种是url方式,即通过请求url中增加;jsessionid=FEF549911390D7ADC6E85D06128405CF方式,Tomcat中间件解析url可以得到sessionId。 其中Cookie方式优先级更高。就是说如果一个请求即有name=JSESSIONID的Cookie,url中还有jsessionid=FEF549911390D7ADC6E85D06128405CF,那么sessionId将使用Cookie中的值,忽略url中的值。
/**
 * Implementation of a request processor which delegates the processing to a
 * Coyote processor.
 *
 * @author Craig R. McClanahan
 * @author Remy Maucherat
 * @version $Revision: 1.26 $ $Date: 2004/05/14 11:00:25 $
 */

public class CoyoteAdapter
    implements Adapter 
 {
    private static Log log = LogFactory.getLog(CoyoteAdapter.class);

    /**
     * The match string for identifying a session ID parameter.
     */
    private static final String match =
        ";" + Globals.SESSION_PARAMETER_NAME + "=";

    /**
     * Parse session id in URL.
     */
    protected void parseSessionId(Request req, CoyoteRequest request) {

        CharChunk uriCC = req.decodedURI().getCharChunk();
        int semicolon = uriCC.indexOf(match, 0, match.length(), 0);

        if (semicolon > 0) {

            // Parse session ID, and extract it from the decoded request URI
            int start = uriCC.getStart();
            int end = uriCC.getEnd();

            int sessionIdStart = start + semicolon + match.length();
            int semicolon2 = uriCC.indexOf(';', sessionIdStart);
            if (semicolon2 >= 0) {
                request.setRequestedSessionId
                    (new String(uriCC.getBuffer(), sessionIdStart, 
                                semicolon2 - semicolon - match.length()));
            } else {
                request.setRequestedSessionId
                    (new String(uriCC.getBuffer(), sessionIdStart, 
                                end - sessionIdStart));
            }
            request.setRequestedSessionURL(true);

            // Extract session ID from request URI
            ByteChunk uriBC = req.requestURI().getByteChunk();
            start = uriBC.getStart();
            end = uriBC.getEnd();
            semicolon = uriBC.indexOf(match, 0, match.length(), 0);

            if (semicolon > 0) {
                sessionIdStart = start + semicolon;
                semicolon2 = uriCC.indexOf
                    (';', start + semicolon + match.length());
                uriBC.setEnd(start + semicolon);
                byte[] buf = uriBC.getBuffer();
                if (semicolon2 >= 0) {
                    for (int i = 0; i < end - start - semicolon2; i++) {
                        buf[start + semicolon + i] 
                            = buf[start + i + semicolon2];
                    }
                    uriBC.setBytes(buf, start, semicolon 
                                   + (end - start - semicolon2));
                }
            }

        } else {
            request.setRequestedSessionId(null);
            request.setRequestedSessionURL(false);
        }

    }


    /**
     * Parse session id in URL.
     */
    protected void parseSessionCookiesId(Request req, CoyoteRequest request) {

        // Parse session id from cookies
        Cookies serverCookies = req.getCookies();
        int count = serverCookies.getCookieCount();
        if (count <= 0)
            return;

        for (int i = 0; i < count; i++) {
            ServerCookie scookie = serverCookies.getCookie(i);
            if (scookie.getName().equals(Globals.SESSION_COOKIE_NAME)) {
                // Override anything requested in the URL
                if (!request.isRequestedSessionIdFromCookie()) {
                    // Accept only the first session id cookie
                    request.setRequestedSessionId
                        (scookie.getValue().toString());
                    request.setRequestedSessionCookie(true);
                    request.setRequestedSessionURL(false);
                    if (log.isDebugEnabled())
                        log.debug(" Requested cookie session id is " +
                            ((HttpServletRequest) request.getRequest())
                            .getRequestedSessionId());
                } else {
                    if (!request.isRequestedSessionIdValid()) {
                        // Replace the session id until one is valid
                        request.setRequestedSessionId
                            (scookie.getValue().toString());
                    }
                }
            }
        }

    }
}

public final class Globals {
    /**
     * The name of the cookie used to pass the session identifier back
     * and forth with the client.
     */
    public static final String SESSION_COOKIE_NAME = "JSESSIONID";


    /**
     * The name of the path parameter used to pass the session identifier
     * back and forth with the client.
     */
    public static final String SESSION_PARAMETER_NAME = "jsessionid";

}

3.3,response.encodeURL做了什么

public class CoyoteResponse
    implements HttpResponse, HttpServletResponse {
	protected CoyoteRequest request = null; 
	/*******************在此隐藏N行******/
    /**
     * Encode the session identifier associated with this response
     * into the specified URL, if necessary.
     *
     * @param url URL to be encoded
     */
    public String encodeURL(String url) {
        
        String absolute = toAbsolute(url);
        if (isEncodeable(absolute)) {
            HttpServletRequest hreq =
                (HttpServletRequest) request.getRequest();
            
            // W3c spec clearly said 
            if (url.equalsIgnoreCase("")){
                url = absolute;
            }
            return (toEncoded(url, hreq.getSession().getId()));
        } else {
            return (url);
        }

    }

    /**
     * Return the specified URL with the specified session identifier
     * suitably encoded.
     *
     * @param url URL to be encoded with the session id
     * @param sessionId Session id to be included in the encoded URL
     */
    private String toEncoded(String url, String sessionId) {

        if ((url == null) || (sessionId == null))
            return (url);

        String path = url;
        String query = "";
        String anchor = "";
        int question = url.indexOf('?');
        if (question >= 0) {
            path = url.substring(0, question);
            query = url.substring(question);
        }
        int pound = path.indexOf('#');
        if (pound >= 0) {
            anchor = path.substring(pound);
            path = path.substring(0, pound);
        }
        StringBuffer sb = new StringBuffer(path);
        if( sb.length() > 0 ) { // jsessionid can't be first.
            sb.append(";jsessionid=");
            sb.append(sessionId);
        }
        sb.append(anchor);
        sb.append(query);
        return (sb.toString());

    }

}








www.bkjia.comtruehttp://www.bkjia.com/ASPjc/1003554.htmlTechArticleTomcat部署应用,客户端阻止cookie时,成功登录后,还是出现登录失败的问题解决,tomcatcookie 一、提出问题 如果用户浏览器设置的阻止cook...

相关文章

相关搜索: tomcat

帮客评论

视觉看点