Java Web登录验证与自动登录实现指南
在Java Web开发中,保障用户数据安全需要校验登录状态,提升用户体验则需要支持自动登录。本文将详细演示如何利用Servlet过滤器(Filter)进行会话拦截,以及结合HTTP Cookie实现“记住我”功能的完整代码路径与配置流程。
验证用户登录状态
在Web应用中,我们需要保护某些页面或操作不被未授权用户访问。最简单有效的方式是在请求到达目标资源之前,检查当前会话(Session)中是否存在特定的用户标识属性。如果不存在,则视为未登录,并重定向至首页或登录页。
第1步:创建过滤类
目的:实现一个统一的入口拦截器,专门用于检查登录权限。
操作:新建一个类实现 javax.servlet.Filter 接口。核心逻辑在 doFilter 方法中执行。
- 将传入的请求对象强转为
HttpServletRequest,以便调用getSession()获取当前会话。 - 通过
getSession().getAttribute("user")检查是否存在已记录的用户名。这里假设登录成功后会在Session中存储名为 "user" 的属性。 - 若属性为空(null),说明未登录:
- 向Request作用域设置提示信息。
- 使用Response对象的
sendRedirect重定向到登录入口(如/index.jsp)。
- 若属性存在,说明已登录,调用
chain.doFilter(request, response)放行请求继续处理。
package cn.hongxin.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
public class LoginFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
// 初始化逻辑
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
HttpSession ss = req.getSession();
// 从 session 中获取 user
if (ss.getAttribute("user") == null) {
System.err.println("你还没有登录");
req.getSession().setAttribute("msg", "请你先登录");
// 重定向到登录页面
String contextPath = req.getContextPath();
resp.sendRedirect(contextPath + "/index.jsp");
} else {
// 放行
chain.doFilter(request, response);
}
}
public void destroy() {
// 销毁逻辑
}
}
第2步:配置 web.xml
目的:告诉服务器哪些页面受该过滤器管辖。
操作:在 WEB-INF/web.xml 中注册Filter并设置匹配模式。
<filter>
<filter-name>login</filter-name>
<filter-class>cn.itcast.filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>login</filter-name>
<!-- 仅拦截jsp目录下的资源 -->
<url-pattern>/jsps/*</url-pattern>
<url-pattern>/views/*</url-pattern>
</filter-mapping>
实现自动登录功能
自动登录机制通常被称为“记住我”(Remember Me)。其原理是:用户首次登录时,服务端将包含用户标识的Cookie发送并保存到客户端浏览器;下次用户访问时,过滤器读取该Cookie,自动补全Session信息,从而实现无感登录。
第1步:开发登录前端界面
目的:提供用户输入账号及选择是否自动登录的交互入口。
操作:在JSP中使用EL表达式判断当前是否已登录。未登录时展示表单,提供单选框选项(不自动、1天、1周)。
<c:choose>
<c:when test="${empty sessionScope.name}">
<form name="x" method="post" action="<c:url value='/LoginServlet'/>">
Name: <input type="text" name="name"/><br/>
auto:
<input type="radio" name="auto" value="-1">不自动登录<br/>
<input type="radio" name="auto" value="1">1天<br/>
<input type="radio" name="auto" value="7">1周<br/>
<input type="submit" value="提交"/>
</form>
</c:when>
<c:otherwise>
你已经登录了: ${name}<br/>
<a href="<c:url value='/LoginServlet'/>">退出</a>
</c:otherwise>
</c:choose>
第2步:服务端处理登录并保存Cookie
目的:接收用户的登录请求,并在Session建立后,根据用户的选择决定是否下发Cookie。
操作:在 LoginServlet 的 doPost 方法中:
- 获取用户名和自动登录时长参数。
- 将用户名存入
session.setAttribute("name", name)。 - 解析自动登录参数:若非 "-1"(即选择了自动登录),则将天数转换为秒数(1天=86400秒)。
- 实例化
Cookie,设置MaxAge(存活时间)和Path(有效路径)。 - 务必注意:Cookie的Path必须设置为
request.getContextPath(),确保同项目下任何Servlet都能读取该Cookie。
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 接收用户姓名
String name = request.getParameter("name");
String auto = request.getParameter("auto");
// 将用户信息放到 session
request.getSession().setAttribute("name", name);
// 判断是否需要设置自动登录
if (!auto.equals("-1")) {
int day = Integer.parseInt(auto); // 1 | 7
int seconds = 60 * 60 * 24 * day;
// 声明 cookie
Cookie c = new Cookie("autoLogin", name);
c.setMaxAge(seconds); // 设置存活时间
c.setPath(request.getContextPath()); // 设置路径为项目根目录
// 保存cookie到客户端
response.addCookie(c);
}
}
第3步:开发自动登录过滤器
目的:在所有页面加载前检查本地是否有有效的“记住我”凭证。
操作:创建一个 AutoFilter,同样实现Filter接口。由于要让所有页面都经历此检查,它需要挂载到 /* 上,但需要注意避免死循环和性能浪费(下文有优化建议)。
- 在
doFilter中读取所有Cookie数组req.getCookies()。 - 遍历数组,寻找名称为
autoLogin的Cookie。 - 若找到且值不为空,将值写入Session
req.getSession().setAttribute("name", value)。 - 最后无论是否完成自动登录,都必须调用
chain.doFilter放行请求。
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
// 获取所有的 cookies
Cookie[] cs = req.getCookies();
if (cs != null) {
for (Cookie c : cs) {
// 如果存在自动登录的 cookie
if (c.getName().equals("autoLogin")) {
String value = c.getValue();
// 登录成功是指:手动将身份信息注入 Session
req.getSession().setAttribute("name", value);
break;
}
}
}
// 不管是否自动登录成功,都要放行
chain.doFilter(request, response);
}
第4步:配置自动登录过滤器
目的:确保所有URL请求都会经过自动登录的逻辑判断。
操作:在 web.xml 中追加以下配置:
<filter>
<filter-name>auto</filter-name>
<filter-class>cn.itcast.filter.AutoFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>auto</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
安全退出与代码优化
简单的实现往往忽略细节,导致退出失效或性能冗余。我们需要优化退出逻辑以及过滤器的执行顺序。
第1步:开发退出逻辑
目的:清除服务端Session并作废客户端Cookie。
操作:在退出处理的Servlet中:
- 调用
request.getSession().invalidate()使当前Session失效。 - 构造一个同名的
Cookie(key为autoLogin),但将其setMaxAge(0),这会指示浏览器立即删除该Cookie。 - 设置路径时必须与原保存Cookie的路径一致,否则无法正确覆盖或删除。
// 模拟退出处理
System.out.println("用户退出");
// 删除整个session
request.getSession().invalidate();
// 清空Cookie
Cookie c = new Cookie("autoLogin", "ddd"); // 值随意
c.setMaxAge(0); // 立即过期
c.setPath(request.getContextPath()); // 保持原路径一致
response.addCookie(c);
// 跳转回首页
response.sendRedirect(request.getContextPath() + "/index.jsp");
第2步:代码性能优化
在上述逻辑中,当用户进行正常的账号密码登录时(调用LoginServlet),也会触发 AutoFilter 的执行。虽然这不会报错,但增加了不必要的Cookie遍历开销。此外,直接拦截Logout也会导致异常。因此,建议在 AutoFilter 中进行如下改进:
- 排除登录接口:在
doFilter头部检查请求URI,如果是指向LoginServlet的请求,直接break或continue,不进行Cookie读取。 - 排除退出接口:同理,如果是Logout请求,也跳过自动登录逻辑。
以上就是Java实现验证用户登录状态与Cookie自动登录的详细内容,更多关于Java Filter与Cookie应用的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













