iOS全浏览器Java Session失效问题求助
我的网站在Windows和Android设备的所有浏览器中运行正常,但在iOS设备的所有浏览器里,JSP页面获取Java Session时返回null值。
相关代码文件
testinput.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Insert title here</title> </head> <body> <form action="testing" method="post"> <input type="text" name="pdf1"> <input type="text" name="pdf2"> <button type="submit">click me</button> </form> </body> </html>
testing.java (Servlet)
import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; /** * Servlet implementation class testing */ @WebServlet("/testing") public class testing extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public testing() { super(); // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub response.getWriter().append("Served at: ").append(request.getContextPath()); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String abc = request.getParameter("pdf1").toString(); String def = request.getParameter("pdf2").toString(); HttpSession sess = request.getSession(); sess.setAttribute("pdf1", abc); sess.setAttribute("pdf2", def); if(sess.getAttribute("pdf1")!=null){ Cookie cook = new Cookie("login", sess.getAttribute("pdf1").toString()); response.addCookie(cook); } response.sendRedirect("test.jsp"); return; } }
test.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Insert title here</title> </head> <body> <%try{ %> <% Cookie cook[] = request.getCookies(); for(Cookie c :cook){ if(c.getName().equals("pdf1")){ String str = c.getValue();%> <p><%=str%></p> <%} }%> <p><%=session.getAttribute("pdf1").toString() %></p> <p><%=session.getAttribute("pdf2").toString() %></p> <%}catch (Exception e){ e.printStackTrace(); log("erroristhis"+e); }%> </body> </html>
Apache配置(Linux VPS服务器)
为访问Session变量,我在https.conf及virtualHost*:80文件中添加了以下配置:
<VirtualHost *:80> ServerName example.com ServerAlias mail.example.com www.example.com # DocumentRoot /home/example1/public_html RewriteEngine on RewriteCond %{HTTP_HOST} ^example\.com [NC] RewriteCond %{SERVER_PORT} 80 RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L] JkMount /* example <Proxy *> Order deny,allow Allow from all </Proxy> ProxyRequests Off ProxyPreserveHost On ProxyPass / http://localhost:8080/example/ ProxyPassReverse / http://localhost:8080/example/ ProxyPassReverseCookiePath / domine/ </VirtualHost>
这种iOS全浏览器都出现Session获取null的情况,十有八九是Session Cookie的路径或跨域配置出了问题——毕竟iOS的WebKit内核(包括Safari和其他iOS浏览器)对Cookie的策略比其他平台严格得多。咱们一步步来排查和解决:
1. 先修正Apache里的Cookie路径配置错误
你看你的VirtualHost配置里有这么一行:
ProxyPassReverseCookiePath / domine/
这明显写错了!这行的作用是把后端Tomcat返回的Cookie路径从/example/(因为你的ProxyPass指向http://localhost:8080/example/)转换成前端的/,所以正确的写法应该是:
ProxyPassReverseCookiePath /example/ /
错误的路径配置会导致iOS浏览器识别不到Cookie的作用范围,自然不会在请求时携带Session Cookie,服务器就拿不到Session了。
2. 给Session Cookie加上正确的SameSite和Secure属性
iOS的WebKit对SameSite属性的校验很严格,默认的Cookie如果没设置SameSite,可能会被归类为Lax模式,而你是POST提交后重定向到test.jsp,这种场景下Lax模式可能会阻止Cookie被携带。咱们在Servlet里手动配置Session Cookie的属性:
// 获取Session后添加这段代码 HttpSession sess = request.getSession(); // 获取或创建JSESSIONID Cookie Cookie sessionCookie = new Cookie("JSESSIONID", sess.getId()); sessionCookie.setPath("/"); // 确保整个域名下都能访问 sessionCookie.setHttpOnly(true); // 提升安全性,防止XSS sessionCookie.setSecure(true); // 必须设置,因为你用了HTTPS重定向 sessionCookie.setAttribute("SameSite", "None"); // 允许跨站/重定向时携带Cookie response.addCookie(sessionCookie);
划重点:设置SameSite=None必须同时开启Secure,不然iOS浏览器会直接拒绝这个Cookie。
3. 确保Cookie的Domain属性适配重定向的域名
你的配置里把example.com重定向到https://www.example.com,如果Session Cookie的Domain只设置成www.example.com,那主域名下的请求就带不上Cookie,反之亦然。所以咱们把Domain设置为.example.com(带前缀点),这样所有子域名都能共享Cookie:
sessionCookie.setDomain(".example.com");
4. 顺便修复test.jsp里的小bug
看你的test.jsp里循环Cookie时判断的是c.getName().equals("pdf1"),但Servlet里设置的Cookie名字是login(new Cookie("login", ...)),这完全不匹配啊!这段代码根本读不到你设置的Cookie,虽然这不是Session null的原因,但也是个明显的问题,改成:
if(c.getName().equals("login")){
5. 测试前先清一下iOS浏览器的缓存
iOS浏览器有时候会缓存旧的Cookie规则,测试前记得清除浏览器的历史记录和Cookie,确保新的配置能生效。
按照上面的步骤调整后,应该就能解决iOS浏览器里Session返回null的问题了!
内容的提问来源于stack exchange,提问作者Ravi varma

