Cookie实现免密登录

追求适度,才能走向成功;人在顶峰,迈步就是下坡;身在低谷,抬足既是登高;弦,绷得太紧会断;人,思虑过度会疯;水至清无鱼,人至真无友,山至高无树;适度,不是中庸,而是一种明智的生活态度。

导读:本篇文章讲解 Cookie实现免密登录,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

Cookie+Session实现免密登录

先大致说一下流程,看图:
在这里插入图片描述

拦截器执行的逻辑大致如下:

  • 不受限资源:直接放行请求,请求原来访问哪就让他访问哪
  • 受限资源:
    • 首先判断当前会话中是否存在登录用户,也就是用户已经登录了,直接放行
    • 如果session中没有存登录用户,那就获取请求头中获取cookie,看下cookie中是否有登录信息,如果有则说明用户希望免密登录,取出数据并且存入session,然后放行资源
    • 以上两种情况都不符合说明用户没有登录,其次又没有做免密登录,只能拦截下来重定向到登录页面了

项目工程:
在这里插入图片描述
pom.xml:

<dependencies>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <version>2.5</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat</groupId>
        <artifactId>tomcat-api</artifactId>
        <version>8.5.41</version>
    </dependency>

    <!--对象转json-->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.8</version>
    </dependency>
</dependencies>

登录请求处理

  • 校验用户名密码是否正确,将用户信息存入session中,如果勾选了”记住我”那么需要给前端响应cookie
package com.horizon.temp.servlet;


import com.fasterxml.jackson.databind.ObjectMapper;
import com.horizon.temp.entity.User;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;

@WebServlet("/login")
public class LoginServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //模拟数据库的用户
        User dbUser=new User("root","admin");
        /**
         * 接收前端参数
         */
        String username = request.getParameter("username");
        String password= request.getParameter("password");
        String remember = request.getParameter("remember");


        System.out.println(remember);

        if(username.equals(dbUser.getUsername()) && password.equals(dbUser.getPassword())){
            // 用户名密码正确
            HttpSession session = request.getSession();

            //存入session
            session.setAttribute("loginUser",dbUser);

            //如果勾选了提交过来的应该是1(如果没有勾选则不会提交,remember的值为null)
            if("1".equals(remember)){

                //说明用户勾选了"记住我"

                ObjectMapper om=new ObjectMapper();

                //转换为json:{"username":"root","password":"admin"}
                //这里你也可以加密,我就不加密了
                String userJson = om.writeValueAsString(dbUser);

                Cookie cookie=new Cookie("loginUser",userJson);
                //设置cookie携带路径为整个项目都携带
                cookie.setPath(request.getContextPath());

                //设置cookie有效期(7天),cookie的过期时间是基于秒设置的(session也是)
                cookie.setMaxAge(60*60*24*7);

                response.addCookie(cookie);

            }

            response.sendRedirect(request.getContextPath()+"/home.jsp");
            return;
        }
        request.setAttribute("error","用户名或密码错误");
        request.getRequestDispatcher("/login.jsp").forward(request,response);

    }
}

登录页

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>


<form action="${pageContext.request.contextPath}/login">

    用户名:<input type="text" name="username">
    <hr>
    密码:<input type="password" name="password">
    <hr>
    <label for="remember">记住我</label>
    <input type="checkbox" name="remember" id="remember" value="1">
    <hr>
    <p style="color:red">${error}</p>
    <input type="submit">
</form>
</body>
</html>

核心拦截器

  • 主要是针对受限资源以及不受限资源分别进行处理,详细逻辑请看文章上面的流程图以及解释
package com.horizon.temp.filter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.horizon.temp.entity.User;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

@WebFilter(urlPatterns = "/*")           //拦截所有的请求
public class LoginFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

        //转换为Http(功能方法更丰富)
        HttpServletRequest request=(HttpServletRequest)servletRequest;
        HttpServletResponse response=(HttpServletResponse)servletResponse;

        /**
         * 浏览器请求:http://localhost:8080/Temp/home.jsp
         * request.getRequestURI():/Temp/home.jsp
         * request.getRequestURL():http://localhost:8080/Temp/home.jsp
         */
        String uri = request.getRequestURI();

        //只要/Temp/home.jsp 请求"/"后面的字符串(home.jsp)
        uri=uri.substring(uri.lastIndexOf("/")+1);

        /**
         * 放行 index.jsp、login.jsp、logout请求、login请求等
         *
         * 不受限内容
         */
        if(
                uri.equals("index.jsp")
                || uri.equals("login.jsp")
                || uri.equals("logout")
                || uri.equals("login")
        ){

            //放行资源
            filterChain.doFilter(request, response);

            //记住这里要加return,要不然请求放行了代码还是会往下执行
            return;
        }


        /**
         * 受限内容
         */
        HttpSession session = request.getSession();
        if(session.getAttribute("loginUser")!=null){


            //虽然是受限内容,但是仍然处于一次会话中,即:用户已经登录过了
            filterChain.doFilter(request,response);

            return;
        }

        Cookie[] cookies = request.getCookies();
        Cookie loginCookie=null;
        if(cookies!=null){
            for (Cookie cookie : cookies) {
                //看下请求头中的所有cookie是否有包含"loginCookie"
                if(cookie.getName().equals("loginUser")){
                    loginCookie=cookie;
                }
            }
        }

        if(loginCookie!=null){
            //说明请求头上的cookie是有携带登录信息的
            //准备读取cookie中的value转回user存入session
            ObjectMapper mapper=new ObjectMapper();

            User user = mapper.readValue(loginCookie.getValue(), User.class);

            session.setAttribute("loginUser",user);
            filterChain.doFilter(request,response);

            return;
        }


        //重定向到登录页面
        response.sendRedirect(request.getContextPath()+"/login.jsp");

    }

    @Override
    public void destroy() {

    }
}

退出登录

  • 在session中销毁登录标识符,销毁cookie标识符,重定向到登录页
package com.horizon.temp.servlet;

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 java.io.IOException;

@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // 清除当前登录用户
        request.getSession().removeAttribute("loginUser");

        // 清除cookie
        Cookie cookie=new Cookie("loginUser","");
        cookie.setMaxAge(0);

        response.addCookie(cookie);

        response.sendRedirect(request.getContextPath()+"/login.jsp");
    }
}


测试

勾选记住我

  • 发现响应头中有响应”loginUser”
    在这里插入图片描述
  • 查看浏览器中的cookie信息
    在这里插入图片描述
    其他情况大家自行断点测试,我就带大家测试到这里了

总结

整体来说还是比较简单的,流程的话大家可以看文章最上面写的步骤

项目中需要注意的一个点:

  • 登录的时候Cookie的携带路径设置是cookie.setPath(request.getContextPath());或者设置为cookie.setPath("/");,代表整个项目下的所有路径都携带此Cookie,但是肯定很多人有疑问,原来使用Cookie从来没有设置过这个东西啊,也一样能成功啊?如果没有设置默认的访问路径为当前的路径的上一级路径,就会有问题了

如果没听懂的话可以看我的另外一篇文章:Cookie携带路径详解

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/131866.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!