用于登录的身份验证过滤器和servlet

pao*_*988 22 authentication servlets login-control servlet-filters

我有一个用于登录的过滤器.它在"用户名"和"密码"字段上执行文本检查.当且仅当文本检查正确完成时,请求才会进入Servlet.后者执行必须与数据库交互的控件.这个链条是否正确?

Bal*_*usC 51

前言:我收集您使用本地登录而不是容器管理登录.有关所有方法,请参阅如何处理数据库中用户的身份验证/授权?


过滤器(拦截器)不应检查用户名/密码组合的有效性.这是servlet(控制器)的责任.

过滤器应仅检查用户是否已登录(通常仅通过检查会话属性的存在),然后继续请求或通过重定向回登录页面来阻止它.

@WebFilter("/*")
public class LoginFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {    
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;
        HttpSession session = request.getSession(false);
        String loginURI = request.getContextPath() + "/login";

        boolean loggedIn = session != null && session.getAttribute("user") != null;
        boolean loginRequest = request.getRequestURI().equals(loginURI);

        if (loggedIn || loginRequest) {
            chain.doFilter(request, response);
        } else {
            response.sendRedirect(loginURI);
        }
    }

    // ...
}
Run Code Online (Sandbox Code Playgroud)

servlet应收集提交的数据,找到User数据库中的关联数据,如果找到则将其存储为会话属性,然后重定向到主页,否则重新显示带有验证错误的表单.

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

    @EJB
    private UserService userService;

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        Map<String, String> messages = new HashMap<String, String>();

        if (username == null || username.isEmpty()) {
            messages.put("username", "Please enter username");
        }

        if (password == null || password.isEmpty()) {
            messages.put("password", "Please enter password");
        }

        if (messages.isEmpty()) {
            User user = userService.find(username, password);

            if (user != null) {
                request.getSession().setAttribute("user", user);
                response.sendRedirect(request.getContextPath() + "/home");
                return;
            } else {
                messages.put("login", "Unknown login, please try again");
            }  
        }

        request.setAttribute("messages", messages);
        request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response);
    }

}
Run Code Online (Sandbox Code Playgroud)

也可以看看:

  • 别客气.确保在登录页面本身不调用过滤器!否则它可能会以无限循环结束.您需要将受限制的页面放在一个单独的文件夹中(以便可以使用`/ somefolder/*`的URL模式代替),或者如果最终用户当前不是,则在请求URL上添加额外的检查请求登录页面. (4认同)
  • +1.为了获得更好的用户体验,如果截获的请求是GET,请将其缓存(或将其添加为登录页面中的隐藏字段),并在登录成功后重定向到此页面. (2认同)