Java 会话管理的最佳选择
Posted
技术标签:
【中文标题】Java 会话管理的最佳选择【英文标题】:Best option for Session management in Java 【发布时间】:2010-12-14 14:19:57 【问题描述】:Java 中管理会话的最佳方式。我听说 cookie 不是可靠的选择,因为它们存储在浏览器中,以后可以访问?它是否正确?如果可能,请通过编码示例给出答案。
哪个是最好的:
URL 重写:服务器会在 URL 链接的末尾添加一个额外的参数 表单中的隐藏参数:服务器将在 html 中的每个表单中添加一个附加参数 cookie:服务器会要求浏览器维护一个cookie。【问题讨论】:
对这个问题投反对票的任何评论 一篇很好的会话管理博文journaldev.com/1907/… 【参考方案1】:会话管理(客户端识别、cookie 处理、保存会话范围数据等)基本上已经由应用服务器本身完成。你根本不需要担心它。您可以通过HttpSession#setAttribute()
和#getAttribute()
在会话中设置/获取Java 对象。只有在客户端不支持 cookie 的情况下,您真正需要注意的是 URL 重写。然后它将在 URL 上附加一个 jsessionid
标识符。在 JSP 中,您可以为此使用 JSTL 的 c:url
。在 Servlet 中,您可以为此使用 HttpServletResponse#encodeURL()
。这样服务器就可以通过读取新的请求 URL 来识别客户端。
您的新问题可能是“但是 cookie 与此有什么关系?服务器是如何完成这一切的?”。好吧,答案是这样的:如果服务器收到来自客户端的请求并且服务器端代码(您的代码)试图通过HttpServletRequest#getSession()
获取HttpSession
,而还没有创建任何人(新会话中的第一个请求),服务器将自己创建一个新的。服务器将生成一个长的、唯一的且难以猜测的 ID(您可以通过 HttpSession#getId()
获得的 ID)并将此 ID 设置为名称为 jsessionid
的 cookie 的值。在后台,服务器为此使用HttpServletResponse#addCookie()
。最后,服务器会将所有会话存储在某种Map
中,会话 ID 为键,HttpSession
为值。
根据HTTP cookie spec,客户端需要在后续请求的标头中发回相同的cookie。在后台,服务器将通过HttpServletRequest#getCookies()
搜索jsessionid
cookie 并确定其值。这样,服务器就能够获取关联的HttpSession
,并在每次调用HttpServletRequest#getSession()
时将其返回。
直截了当:唯一存储在客户端的是会话 ID(类似于 cookie)和 HttpSession
对象(包括它的所有属性)存储在服务器端(在 Java 中记忆)。您自己无需担心会话管理,也无需担心安全性。
另见:
Authenticating the username, password by using filters in Java (contacting with database) How to redirect to Login page when Session is expired in Java web application? How to implement "Stay Logged In" when user login in to the web application【讨论】:
更新:当前的 HTTP 状态管理机制 规范是 RFC 6265,它废弃了之前的规范 RFC 2965。您可以更新答案中指向 RFC 2965 的链接(在“HTTP cookie 规范”中)。 @BalusC 根据上面的答案,如果我使用 url 重写,那么存储值和获取 session.setAttribute() 和 session.getAttribute() 等值的方法是什么。 @BalusC 请参阅我正在使用 mozilla,并且我已手动阻止接受 cookie(未选中允许 cookie)。然后我尝试存储到使用 session.setAttribute("x",x);现在在另一个页面中我正在使用 session.getAttribute(x);并且在页面上显示为空。看了你的回答后,我尝试了这种方式,然后我发表了评论。这不是使用会话属性的方式吗? @javaprogrammer: 显然你没有做正确的 URL 重写。【参考方案2】:所有 Java Web 框架都支持 cookie 或 URL 编码的会话 ID。他们会自动选择正确的方法,因此您无需做任何事情。只需从您的容器中请求会话对象,它就会处理详细信息。
[编辑] 有两个选项:Cookie 和特殊 URL。两种方法都存在问题。例如,如果您在 URL 中编码会话,人们可以尝试传递会话(例如,通过将 URL 放入邮件中)。如果您想了解这一点,请阅读几篇有关安全性和构建应用服务器的文章。否则:您的 Java 应用程序服务器将为您做正确的事情。别想了。
【讨论】:
没有其他选择,所以这个问题没有意义。 @Aaron,你的意思是说 cookie 是唯一可用的选项吗?【参考方案3】:cookie 只是存储会话 ID,会话过期后这个 ID 就没有用了。
【讨论】:
【参考方案4】:Servlet specification 定义了用于在标准 J2EE 应用程序中访问/设置会话数据的 API。它还定义了会话数据存储在服务器端,除了会话标识符之外没有任何内容传输到客户端。会话 id 的传输有两种机制:
1) 请求 URL 例如jessionid=.... 2) 饼干
机制是根据客户端功能自动确定的。
编辑。没有最好的选择,有定义方式的 servlet 规范。
【讨论】:
您的 servlet 规范链接似乎已损坏,如果可能,您应该更新您的问题。【参考方案5】:Http 是一种无状态的、仅客户端拉取的协议。
为了实现有状态的对话,Java EE Web Server 需要在客户端隐藏一些信息(即 sessionid),它可以使用的机制应该遵循 HTTP 和 HTML 规范。
有三种方法可以实现这一目标:
-
URL 重写:服务器会在 URL 链接的末尾添加一个额外的参数。
表单中的隐藏参数:服务器将在 HTML 中的每个表单中添加一个附加参数。
cookie:服务器会要求浏览器维护一个cookie。
基本上,现代网络服务器将有一个“过滤器”来选择自动使用的方式。 所以如果Server检测到浏览器已经关闭了cookie支持,就会切换到其他方式。
【讨论】:
【参考方案6】:2 个重要问题:
您使用的是哪种网络技术? JSF、Struts、SpringMVC 或只是普通的 servlet/JSP。
Servlet/JSP 已经为您提供了所需的会话支持。 JSP 示例:Hello, <%= session.getAttribute( "theName" ) %>
我真的认为您不必担心 cookie,因为数据安全地存储在服务器中,并且处理 cookie 是自动完成的。
您的应用程序是否安装在单个服务器上?
如果 YES 比您没有问题,请使用 servlet 会话选项。
如果否,那么您必须找到另一种方法来执行此操作。就像使用粘性会话一样,或者可能将请求/响应中的整个会话对象解析为一个字段。此选项确实需要您采取安全措施。
【讨论】:
JSF、Struts、SpringMVC 都建立在 servlet 规范之上。 您可以从任何可以访问请求对象的地方调用 request.getSession().getAttribute(),而不仅仅是 JSP。 这个问题与servlets/JSP有关。以上是关于Java 会话管理的最佳选择的主要内容,如果未能解决你的问题,请参考以下文章
ASP.NET 中的 FluentNHibernate 会话管理