本以为没几个人会遇到这种问题,结果后台数据显示挺多的,那我就把内容精简一下,之前的主要为了个人笔记
(我是使用HttpSession传入用户信息来验证是否登录,通过Cookie记录登录的用户名和密码实现下次登录时省去输入密码的操作直接进入首页。
退出不了的原因是因为Cookie没有删除成功;
虽然定义了退出请求的logout-student(清除Session删除Cookie),但现实却是用户在主页发起退出请求时跳转到了logout-student,但它没有进行登录信息的清除,之后直接重定向到登录页面,再通过Cookie实现免登录进入主页。这就导致用户点击了退出却无法退出。
【logout-student】定义的学生退出servlet
【login】登录服务的sevlet
【student-self】学生主页的加载servlet
F12打开开发者模式
根源是全局过滤器那里将退出请求的服务直接重定向到登录页面,请求自始至终没有在logout-student进行登录相关信息的清除
另外,有的人遇到的情况可能是因为Cookie没有设置path,只需要为Cookie添加path就可以解决问题
自定义的cookie名.setPath("/");
/代表全局路径可用,一般加上这段就ok)
以下是罗里吧嗦的解释,建议不要浪费时间看
登陆时添加的Cookie
String isStudent = req.getParameter("is-student");
//判断是学生还是管理员,如果为null就是管理员
String username = req.getParameter("username");
String password = req.getParameter("password");
String remember = req.getParameter("remember");
if(isStudent!=null){
//如果登录的是学生
Student student=new Student(username,password);
httpSession.setAttribute("student", student);
//传入Student对象用以验证是否已经登录,下同
}else{
User user =new User(username,password);
httpSession.setAttribute("user", user);
}
if (remember != null) {
//传入Cookie
Cookie cookie_username = new Cookie("username", username);
Cookie cookie_password = new Cookie("password", password);
Cookie cookie_isStudent = new Cookie("is-student", isStudent);
cookie_username.setMaxAge(60 * 60 * 24 * 30);
cookie_password.setMaxAge(60 * 60 * 24 * 30);
cookie_isStudent.setMaxAge(60 * 60 * 24 * 30);//设置最大存在时间
resp.addCookie(cookie_username);
resp.addCookie(cookie_password);
resp.addCookie(cookie_isStudent);
}
实现按钮,点击跳转到logout-student服务,调用doGet方法
<a href="logout-student">
<i class="fas fa-sign-out-alt"></i> 退出登录
</a>
注册退出的LogoutStudentServlet(通过addCookie覆盖原来的Cookie实现Cookie的删除)
@WebServlet("/logout-student")
public class LogoutStudentServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Cookie cookie_isStudent = new Cookie("is-student", null);
Cookie cookie_username = new Cookie("username", null);
Cookie cookie_password = new Cookie("password", null);
//这里可以添加一些输出或者log,用来检测程序是否调用了此方法
//比如System.out.println("调用logout-student的doGet方法")
//将Cookie设置失效
cookie_username.setMaxAge(0);
cookie_password.setMaxAge(0);
cookie_isStudent.setMaxAge(0);
//覆盖Cookie的代码段
resp.addCookie(cookie_username);
resp.addCookie(cookie_password);
resp.addCookie(cookie_isStudent);
resp.sendRedirect("login");//重定向到登录界面
}
}
我开始以为问题根源在于Cookie路径的设置上,因为搜索到的无法删除Cookie的情况基本都是因为Cookie路径没有设置,域名没有设置之类的,于是我给Cookie添加了路径
cookie_username.setPath("/");
cookie_password.setPath("/");
cookie_isStudent.setPath("/");
以防意外,在添加Cookie和覆盖Cookie的代码处我都加上了这段,理想是丰满的,结果却不是
点击退出按钮后,程序会跳转到注册的LogoutStudentServlet,但是,它没有调用doGet方法,Cookie也没有被覆盖,而是直接重定向到登录界面,这就意味着这个Servlet中无论我写不写东西,程序都能正常运行,它只是需要一个注册名为“logout-student”的Servlet
如图:
它首先跳转到logout-student,也就是定义的退出servlet程序,之后重定向到登录界面login,但是之后又通过Cookie自动登录到用户界面,也就是说,用户点击退出后,程序跳了2个界面又回到了用户界面,点击了退出却无法退出
但一切都是有根源的,我锁定了重定向到login这个操作,在将LogoutStudentServlet中所有重定向到login的代码注释后,发现这个bug依然存在,说明问题不在servlet中,我的项目中与servlet相关联的只有全局过滤器,于是成功在全局过滤器中发现了问题
@Override
protected void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {
res.setContentType("text/html;charset=utf-8");
String url = req.getRequestURL().toString();
if (!url.endsWith("/login") && !url.contains("/static/")) {
HttpSession session = req.getSession();
User user = (User) session.getAttribute("user");
//从session中获取user对象,用以验证管理员是否登录,下同
// 应添加Student student = (Student) session.getAttribute("student");
if (user == null ) {//条件应添加&& student == null
//判断条件本来是实现没有登录的用户会全部重定向到登录界面,但我新增了学生用户后没有添加学生的判断条件,导致退出之后不覆盖Cookie直接重定向到登录界面
res.sendRedirect("login");
return;
}
}
chain.doFilter(req, res);
}
问题根源在于添加了新的登录用户student类型后,我没有在全局过滤器中加入它的验证代码,而原来的过滤器只有user类型用户的验证,这就导致student无法退出