身份验证筛选器未正确识别身份验证

时间:2015-03-03 06:46:00

标签: java session servlets servlet-filters

我正在尝试使用Filter,因此我可以在用户访问受保护的网页之前对其进行身份验证。以下是我的Filter

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并将其重定向到索引页面(如果他们已经注销)。这意味着,如果用户输入以下网址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

这意味着会话根本没有销毁,否则过滤器出现问题。我该如何解决这个问题?

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

1 个答案:

答案 0 :(得分:1)

您不能使用会话的简单存在来确定用户是否已登录。如果没有会话,很明显用户没有登录,但情况恰恰相反。

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

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