身份验证过滤器未正确识别身份验证
Authentication Filter is not properly identifying the authentication
我正在尝试使用 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>
}
我的期望是阻止用户直接访问 URLs 并将他们重定向到索引页面(如果他们已经注销)。这意味着,如果用户输入下面的 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)
除此之外,过滤器中的 System.out.println()
会打印以下内容。
Executed 2
这意味着会话根本没有被破坏,否则过滤器有问题。我该如何解决这个问题?
注意:我使用 /Populate_subUsers
通过将进程限制为一个 servlet 来进行测试。实际上我希望同一个过滤器在所有 servlet 之前工作。
您不能使用会话的简单存在来确定用户是否登录。如果没有会话存在,很明显用户没有登录,反之则不然。
当用户成功通过身份验证时,您应该在会话中放置一个有效的用户 ID 并测试此 ID 的存在(当然,如果不存在会话则使用未通过身份验证...)
事实上,当您注销时,您使当前会话无效。这意味着之前存储在会话中的所有属性(如果有的话)都将丢失,并且在内部 servlet 容器将创建一个具有新会话 ID 的新会话。但这也意味着......你仍然有一个会话,空但有效。这就是为什么您应该在会话中放置用户 ID 以了解用户是否已通过身份验证的原因。
我正在尝试使用 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>
}
我的期望是阻止用户直接访问 URLs 并将他们重定向到索引页面(如果他们已经注销)。这意味着,如果用户输入下面的 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)
除此之外,过滤器中的 System.out.println()
会打印以下内容。
Executed 2
这意味着会话根本没有被破坏,否则过滤器有问题。我该如何解决这个问题?
注意:我使用 /Populate_subUsers
通过将进程限制为一个 servlet 来进行测试。实际上我希望同一个过滤器在所有 servlet 之前工作。
您不能使用会话的简单存在来确定用户是否登录。如果没有会话存在,很明显用户没有登录,反之则不然。
当用户成功通过身份验证时,您应该在会话中放置一个有效的用户 ID 并测试此 ID 的存在(当然,如果不存在会话则使用未通过身份验证...)
事实上,当您注销时,您使当前会话无效。这意味着之前存储在会话中的所有属性(如果有的话)都将丢失,并且在内部 servlet 容器将创建一个具有新会话 ID 的新会话。但这也意味着......你仍然有一个会话,空但有效。这就是为什么您应该在会话中放置用户 ID 以了解用户是否已通过身份验证的原因。