详解JavaEE使用过滤器实现登录(用户自动登录 安全登录 取消自动登录黑用户禁止登录)

详解JavaEE使用过滤器实现登录

什么是过滤器

在网络开发中,过滤器是一种能够截取并处理请求和响应的功能组件。过滤器可以修改请求,修改响应内容并可以过滤/拦截请求和响应。使用过滤器可以在不影响原来的请求和响应方式的情况下增加一些自定义的操作,使得整个系统的设计更加灵活。

怎样使用过滤器实现登录

1. 过滤器的实现

过滤器需要实现Filter接口,接口中有三个方法:

  • init 方法:过滤器的初始化方法。
  • doFilter 方法:过滤器要执行的操作。
  • destroy 方法:过滤器销毁时执行的方法。

下面是过滤器的一个基本实现:

public class LoginFilter implements Filter{

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

    }

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

    }

    @Override
    public void destroy() {

    }
}

2. 登录账号认证

在登录操作中,我们需要对用户的账号和密码进行认证。下面是一个使用Filter实现用户登录的过滤器:

public class LoginFilter implements Filter{
    private String loginPage = "/login.jsp";
    private String encoding = "UTF-8";
    private String[] logonPages = new String[] { "/login.jsp", "/index.jsp" };

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // TODO Auto-generated method stub

        String loginPages = filterConfig.getInitParameter("loginPages");
        if (loginPages != null && !"".equals(loginPages)) {
            logonPages = loginPages.split(",");
        }
        String loginPage = filterConfig.getInitParameter("loginPage");
        if (loginPage != null && !"".equals(loginPage)) {
            this.loginPage = loginPage;
        }
        String encoding = filterConfig.getInitParameter("encoding");
        if (encoding != null && !"".equals(encoding)) {
            this.encoding = encoding;
        }
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
            throws IOException, ServletException {
        // TODO Auto-generated method stub

        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        String requestURI = req.getRequestURI();
        boolean loginPageFlag = false;
        for (String page : logonPages) {
            if (requestURI.indexOf(page) != -1) {
                loginPageFlag = true;
                break;
            }
        }

        if (!loginPageFlag) {
            // 进入这里表示登录失败或者还没有登录,需要进行登录认证
            HttpSession session = req.getSession();
            String userId = (String) session.getAttribute("userId");
            if (userId == null) {
                // 进行登录认证
                userId = req.getParameter("userId");
                String password = req.getParameter("password");
                if (userId != null && !"".equals(userId) 
                    && password != null && !"".equals(password) 
                    && validate(userId, password)) {
                    // 认证通过,设置session
                    session.setAttribute("userId", userId);

                    // 安全登录
                    if (req.getParameter("remember") != null) {
                        // 在Cookie中存储用户名密码
                        Cookie loginCookie = new Cookie("login", URLEncoder.encode(userId + ":" + password, encoding));
                        loginCookie.setMaxAge(60 * 60 * 24 * 7);
                        res.addCookie(loginCookie);
                    }

                    filterChain.doFilter(request, response);
                } else {
                    // 非法登录,直接返回登录页面
                    res.sendRedirect(req.getContextPath() + loginPage);
                }
            } else {
                // 用户已经登录,可以访问
                filterChain.doFilter(request, response);
            }
        } else {
            // 请求的是登录页面,可以直接访问
            filterChain.doFilter(request, response);
        }
    }

    private boolean validate(String userId, String password) {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }

}

3. 用户自动登录

在实现登录的过程中,为了方便用户下次访问的时候能够直接访问系统而无需再次登录,我们可以实现用户自动登录功能。下面是用户自动登录的实现过程:

3.1 在Cookie中存储用户信息

在用户登录后,我们在Cookie中存储用户的用户名和密码,方便用户下次访问时可直接登录。代码如下:

if (req.getParameter("remember") != null) {
    // 在Cookie中存储用户名密码
    Cookie loginCookie = new Cookie("login", URLEncoder.encode(userId + ":" + password, encoding));
    loginCookie.setMaxAge(60 * 60 * 24 * 7);
    res.addCookie(loginCookie);
}

3.2 在Filter中判断Cookie中是否有用户信息

在每次请求时,我们都需要从Cookie中获取用户的信息,如果Cookie中有用户信息,则自动登录。代码如下:

// 判断是否需要自动登录
Cookie[] cookies = req.getCookies();
if (cookies != null && cookies.length > 0) {
    for (Cookie cookie : cookies) {
        if ("login".equals(cookie.getName())) {
            String userInfo = URLDecoder.decode(cookie.getValue(), encoding);
            String[] loginInfo = userInfo.split(":");
            String username = loginInfo[0];
            String password = loginInfo[1];
            if (validate(username, password)) {
                HttpSession session = req.getSession();
                session.setAttribute("userId", username);
            }
        }
    }
}

4. 安全登录

在实现自动登录功能后,为了保证用户密码安全,我们需要对密码进行加密。代码如下:

4.1 密码加密

在用户登录时,使用Base64对用户的密码进行加密:

if (userId != null && !"".equals(userId) 
    && password != null && !"".equals(password) 
    && validate(userId, password)) {
    // 认证通过,设置session
    session.setAttribute("userId", userId);

    // 安全登录
    if (req.getParameter("remember") != null) {
        // 对密码进行加密
        String encryptPassword = Base64.getEncoder().encodeToString(password.getBytes(encoding));
        // 在Cookie中存储用户名密码
        Cookie loginCookie = new Cookie("login", URLEncoder.encode(userId + ":" + encryptPassword, encoding));
        loginCookie.setMaxAge(60 * 60 * 24 * 7);
        res.addCookie(loginCookie);
    }

    filterChain.doFilter(request, response);
} else {
    // 非法登录,直接返回登录页面
    res.sendRedirect(req.getContextPath() + loginPage);
}

4.2 密码解密

在自动登录时,我们需要对Base64加密后的密码进行解密:

// 判断是否需要自动登录
Cookie[] cookies = req.getCookies();
if (cookies != null && cookies.length > 0) {
    for (Cookie cookie : cookies) {
        if ("login".equals(cookie.getName())) {
            String userInfo = URLDecoder.decode(cookie.getValue(), encoding);
            String[] loginInfo = userInfo.split(":");
            String username = loginInfo[0];
            String password = loginInfo[1];

            // 对密码进行解密
            String decryptPassword = new String(Base64.getDecoder().decode(password), encoding);

            if (validate(username, decryptPassword)) {
                HttpSession session = req.getSession();
                session.setAttribute("userId", username);
            }
        }
    }
}

5. 取消自动登录

如果用户选择了自动登录选项,但是在下次访问时不想继续启用自动登录,我们需要提供给用户一个取消自动登录的按钮。代码如下:

登录页面中的取消自动登录按钮:

<div class="checkbox">
    <label for="remember-me">
        <input type="checkbox" name="remember" id="remember-me"> 自动登录
    </label>
    <br>
    <a href="${pageContext.request.contextPath}/CancelAutoLoginServlet">取消自动登录</a>
</div>

实现取消自动登录功能的Servlet:

public class CancelAutoLoginServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public CancelAutoLoginServlet() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 删除Cookie中的登录信息
        Cookie loginCookie = new Cookie("login", "");
        loginCookie.setMaxAge(0);
        response.addCookie(loginCookie);

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

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }
}

小结

通过使用过滤器实现登录相关功能,可以很容易地实现用户的安全登录、自动登录等功能。可以增强系统的安全性,提升用户的使用体验,但是需要注意保护用户的隐私信息。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解JavaEE使用过滤器实现登录(用户自动登录 安全登录 取消自动登录黑用户禁止登录) - Python技术站

(0)
上一篇 2023年6月15日
下一篇 2023年6月15日

相关文章

  • Javaweb使用getPart接收表单文件过程解析

    下面我将详细讲解Javaweb使用getPart接收表单文件的过程。 获取上传文件的表单 首先,在jsp页面中需要创建一个表单,用于上传文件。 <form action="upload" method="post" enctype="multipart/form-data"> <i…

    Java 2023年6月15日
    00
  • java内部类的最详细详解

    Java内部类的最详细详解 什么是Java内部类 在Java中,内部类是一个定义在其他类中的类,这个类可以访问其外部类的所有成员和方法。Java中内部类的分类有四种:成员内部类、局部内部类、匿名内部类和静态内部类。 成员内部类 成员内部类是定义在类的内部,且与类的成员变量和方法处于同一等级的类。成员内部类可以访问外部类的所有成员变量和方法,包括私有成员。成员…

    Java 2023年5月26日
    00
  • Maven build 命令介绍的使用详解

    Maven build 命令介绍的使用详解 Maven是一个Java项目的自动化构建工具,用于搭建、构建、测试和部署Java应用程序。它是Java世界中非常流行的构建工具,由于其依赖关系管理,传递依赖的下载,插件机制等功能,使得Java项目的构建变得更加简单和自动化。 在Maven中,mvn命令是我们最常用的命令之一,该命令被用于在项目中执行诸如编译、测试、…

    Java 2023年5月20日
    00
  • SpringBoot启动过程的实现

    下面是关于SpringBoot启动过程的实现的完整攻略。 SpringBoot启动过程的实现 SpringBoot使用Spring框架中的ApplicationContext来启动应用程序。 在所有bean都被创建和注册之后,SpringBoot的核心功能将启用自动化配置,例如管理静态资产,设置HTTP端口,连接数据库等。 SpringBoot的启动过程主要…

    Java 2023年5月15日
    00
  • 详解Java数据库连接池

    详解Java数据库连接池 什么是数据库连接池? 数据库连接池是一种用于管理数据库连接的技术。通俗地说,它就像一个存放数据库连接的池子,程序从池子里取连接,用完之后再放回池子里,这样可以减少连接的创建和关闭的时间,在提高程序性能的同时也降低了数据库服务器的压力。 为什么要使用数据库连接池? 在使用数据库操作时,每次打开连接、关闭连接都需要一定的时间。长时间使用…

    Java 2023年5月19日
    00
  • 使用Tomcat Native提升Tomcat IO效率的方法详解

    使用Tomcat Native提升Tomcat IO效率的方法详解 什么是Tomcat Native Tomcat Native是一个可选组件,它提供了使用操作系统本地库来优化Tomcat的I/O性能的功能。通过使用Tomcat Native,Tomcat服务器能够基于操作系统优化的IO处理提高性能。 安装Tomcat Native 要使用Tomcat Na…

    Java 2023年5月19日
    00
  • Java JTable 实现日历的示例

    这里提供一个Java JTable 实现日历的示例的完整攻略: 1. 实现一个基本的日历 步骤一:创建一个 JFrame,并添加一个 JTable,用来显示日历 public class Calendar extends JFrame { private final int WIDTH = 600; private final int HEIGHT = 40…

    Java 2023年5月20日
    00
  • java实现数字炸弹

    Java实现数字炸弹是一种常见的编程练习,主要是为了训练学生对于递归算法的理解和运用能力,以下是数字炸弹的完整攻略: 什么是数字炸弹? 数字炸弹指的是在一个数字序列中寻找出现次数最高的数字,并将出现次数最高的数字从序列中删除,接着重复以上步骤,直到序列为空。 怎样实现数字炸弹? 1. 将数字序列分解为数字数组 在Java中,我们可以将数字序列转化为数字数组,…

    Java 2023年5月23日
    00
合作推广
合作推广
分享本页
返回顶部