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

Authentication 用于登录的身份验证过滤器和servlet,authentication,servlets,servlet-filters,login-control,Authentication,Servlets,Servlet Filters,Login Control,我有一个用于登录的筛选器。它对“用户名”和“密码”字段执行文本检查。如果且仅当文本检查正确完成时,请求才会转到Servlet。后者执行必须与数据库交互的控制。这个链正确吗?前言:我猜想您使用的是自制登录,而不是容器管理登录。有关所有方面的信息,请参见 筛选器(拦截器)不应检查用户名/密码组合的有效性。这是servlet(控制器)的职责 过滤器应该只检查用户是否登录(通常只检查会话属性的存在),然后通过重定向回登录页面继续请求或阻止请求 @WebFilter("/*") public class

我有一个用于登录的筛选器。它对“用户名”和“密码”字段执行文本检查。如果且仅当文本检查正确完成时,请求才会转到Servlet。后者执行必须与数据库交互的控制。这个链正确吗?

前言:我猜想您使用的是自制登录,而不是容器管理登录。有关所有方面的信息,请参见


筛选器(拦截器)不应检查用户名/密码组合的有效性。这是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);
        }
    }

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

@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);
    }

}
@WebServlet(“/login”)
公共类LoginServlet扩展了HttpServlet{
@EJB
私人用户服务;
@凌驾
受保护的void doGet(HttpServletRequest请求,HttpServletResponse响应)抛出ServletException,IOException{
request.getRequestDispatcher(“/WEB-INF/login.jsp”).forward(请求,响应);
}
@凌驾
受保护的void doPost(HttpServletRequest请求、HttpServletResponse响应)引发ServletException、IOException{
字符串username=request.getParameter(“用户名”);
字符串密码=request.getParameter(“密码”);
映射消息=新的HashMap();
if(username==null | | username.isEmpty()){
消息。放置(“用户名”,“请输入用户名”);
}
if(password==null | | password.isEmpty()){
信息。输入(“密码”,“请输入密码”);
}
if(messages.isEmpty()){
User=userService.find(用户名、密码);
如果(用户!=null){
request.getSession().setAttribute(“用户”,用户);
sendRedirect(request.getContextPath()+“/home”);
返回;
}否则{
messages.put(“登录”,“未知登录,请重试”);
}  
}
setAttribute(“消息”,消息);
request.getRequestDispatcher(“/WEB-INF/login.jsp”).forward(请求,响应);
}
}
另见:

+1。为了获得更好的用户体验,如果截获的请求是GET,则将其缓存(或将其作为登录页面中的隐藏字段添加),并在登录成功后重定向到此页面。这里可以找到一个具体的示例:欢迎使用。确保未在登录页面本身上调用筛选器!否则,它可能会以无限循环结束。您需要将受限制的页面放在一个单独的文件夹中(这样可以使用URL模式
/somefolder/*
),或者如果终端用户当前没有请求登录页面,则需要在请求URL上添加额外的检查。您能解释一下登录页面的额外检查吗,或者排除js或css页面?我尝试了这个方法,但一直失败,原因是:java.lang.RuntimeException:不可编译的源代码-LoginFilter不是抽象的,并且不会覆盖LoginFilter上javax.servlet.Filter中的抽象方法destroy()。(LoginFilter.java:15)