java - 身份验证过滤器无法正确识别身份验证

标签 java session servlets servlet-filters

我正在尝试使用过滤器,以便我可以在用户访问 protected 页面之前对其进行身份验证。下面是我的过滤器

package Filter;

import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 *
 * @author Yohan
 */
public class LoginFilter_Level1 implements Filter {

    private static final boolean debug = true;

    // The filter configuration object we are associated with.  If
    // this value is null, this filter instance is not currently
    // configured. 
    private FilterConfig filterConfig = null;

    public LoginFilter_Level1() {
    }    

    public void init(FilterConfig arg0) throws ServletException {}  

public void doFilter(ServletRequest req, ServletResponse resp,FilterChain chain) throws IOException, ServletException
{  

    PrintWriter out=resp.getWriter();  

    HttpServletRequest request = (HttpServletRequest)req;
    HttpServletResponse response = (HttpServletResponse)resp;

    HttpSession session = request.getSession(false);

    if(session==null)
    {
        RequestDispatcher dispatch = request.getRequestDispatcher("index.jsp");
        dispatch.forward(req, resp);
        System.out.println("Executed 1");
    }
    else
    {
        System.out.println("Executed 2");
        chain.doFilter(request,response);
    }

}  
    public void destroy() {}  ;

}

下面是我的 Web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <filter>
        <filter-name>LoginFilter_Level1</filter-name>
        <filter-class>Filter.LoginFilter_Level1</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>LoginFilter_Level1</filter-name>
        <url-pattern>/Populate_subUsers</url-pattern>
    </filter-mapping>
    <servlet>
        <servlet-name>DipslyHeaderDataHstrySrvlt</servlet-name>
        <servlet-class>Controller.DipslyHeaderDataHstrySrvlt</servlet-class>
    </servlet>
    <servlet>
        <servlet-name>SubUserSrvlt</servlet-name>
        <servlet-class>Controller.subuser.SubUserSrvlt</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>DipslyHeaderDataHstrySrvlt</servlet-name>
        <url-pattern>/DipslyHeaderDataHstrySrvlt</url-pattern>
    </servlet-mapping>
<servlet-mapping>
        <servlet-name>SubUserSrvlt</servlet-name>
        <url-pattern>/SubUserSrvlt</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
</web-app>

以下是用户如何从系统注销。

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package Controller.login;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

/**
 *
 * @author user
 */
@WebServlet(name = "LogoutSrvlt", urlPatterns =
{
    "/LogoutSrvlt"
})
public class LogoutSrvlt extends HttpServlet
{

    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException
    {
        response.setContentType("text/html;charset=UTF-8");
        try
        {
            HttpSession session=request.getSession();  
            session.invalidate();      



        } finally
        {
            response.sendRedirect("index.jsp");
            return;
        }
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /**
     * Handles the HTTP <code>GET</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException
    {
        processRequest(request, response);
    }

    /**
     * Handles the HTTP <code>POST</code> method.
     *
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException
    {
        processRequest(request, response);
    }

    /**
     * Returns a short description of the servlet.
     *
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo()
    {
        return "Short description";
    }// </editor-fold>

}

我的期望是阻止用户直接访问 URL,并将他们重定向到索引页面(如果他们已经注销)。这意味着,如果用户输入以下 URL,http://localhost:8080/App/Populate_subUsers ,那么他应该被重定向到索引页面。

但是,我没有得到重定向,而是收到以下错误。

Mar 03, 2015 12:09:50 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [Populate_subUsers] in context with path [/PatientApp] threw exception
java.lang.NullPointerException
    at Controller.subuser.Populate_subUsers.processRequest(Populate_subUsers.java:47)
    at Controller.subuser.Populate_subUsers.doGet(Populate_subUsers.java:91)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at Filter.LoginFilter_Level1.doFilter(LoginFilter_Level1.java:60)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

除此之外,Filter 中的 System.out.println() 打印以下内容。

Executed 2

这意味着 session 根本没有被破坏,否则过滤器就会出现问题。我该如何解决这个问题?

注意:我使用 /Populate_subUsers 通过将进程限制为一个 servlet 来进行测试。实际上,我希望相同的过滤器在所有 servlet 之前工作。

最佳答案

您不能仅使用 session 的存在来确定用户是否已登录。如果不存在 session ,则显然用户尚未登录,但反之则不然。

当用户成功通过身份验证时,您应该在 session 中放置一个有效的用户 ID,并测试该 ID 是否存在(当然,如果不存在 session ,则使用未经过身份验证...)

事实上,当您注销时,当前 session 就会失效。这意味着先前存储在 session 中的所有属性(如果有)都会丢失,并且 servlet 容器将在内部创建一个具有新 session ID 的新 session 。但这也意味着......您仍然有一个 session ,空的但有效。这就是为什么您应该将用户 ID 放入 session 中以了解用户是否已通过身份验证的原因。

关于java - 身份验证过滤器无法正确识别身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28825676/

相关文章:

java - 如何检查 session 在java中是否已过期?

java - 在 Java 中使用多线程初始化您的应用程序

java - 编译后 Java 对象引用变量类型会发生什么变化?

php - 如何限制使用 session 下载的文件数量

java - 谁(网络服务器或开发人员)负责为每个浏览器维护一个 http session ?

java - 将变量从 Servlet 发送到 JSP

java - 泛型可以消除困惑

java - Spring JPA存储库-jsonObject上的运算符SIMPLE_PROPERTY需要标量参数

php - session_start() 挂起服务器

java - 仅存储 24 小时变量值