过滤器过滤特定的url
默认情况下,过滤器不支持排除特定的URL模式,每当您为过滤器定义URL模式时,任何与该模式匹配的请求都将由过滤器无例外处理。
从过滤器中排除URL的最简单方法是将过滤器映射到非常特定的模式。 在早期开发阶段完成此操作是可行的,但是如果您在生产环境中修改现有过滤器的URL模式,则可能是一个繁琐的过程,因为您必须重新映射所有现有servlet URL以实现您的目的。
在本教程中,我们将展示如何以编程方式向现有过滤器添加排除功能。
1-自定义过滤器
自定义过滤器是您可以控制的过滤器。 即您拥有修改其源代码的所有权利。
假设我们有一个现有的Web应用程序,该应用程序通过LDAP验证用户请求。 所有servlet请求都通过LDAPAuthenticationFilter传递,该映射映射到/ * ,如下所示:
<filter>
<filter-name>LDAPAuthenticationFilter</filter-name>
<filter-class>com.programmer.gate.filters.LDAPAuthenticationFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LDAPAuthenticationFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
我们的过滤器仅对请求进行身份验证,然后调用chain.doFilter() :
LDAPAuthenticationFilter.java
package com.programmer.gate.filters;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
public class LDAPAuthenticationFilter implements Filter{
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
// Authenticate the request through LDAP
System.out.println("Authenticating the request through LDAP");
// Forward the request to the next filter or servlet in the chain.
chain.doFilter(req, resp);
}
public void init(FilterConfig filterConfig) throws ServletException {
}
public void destroy() {
// TODO Auto-generated method stub
}
}
现在,假设我们要创建一个servlet,它需要简单的数据库身份验证并且不需要通过LDAP。 我们首先想到的是创建一个新的过滤器,并将其映射到新servlet的特定URL模式。
因此,我们创建了一个名为DatabaseAuthenticationFilter的新过滤器,该过滤器仅通过数据库对请求进行身份验证并随后调用chain.doFilter() :
package com.programmer.gate.filters;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class DatabaseAuthenticationFilter implements Filter{
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
// Authenticate the request through database then forward the request to the next filter or servlet in the chain
System.out.println("Authenticating the request through database");
chain.doFilter(req, resp);
}
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub
}
public void destroy() {
// TODO Auto-generated method stub
}
}
我们在web.xml下定义过滤器,以仅处理以/ DatabaseAuthenticatedServlet开头的特定URL:
<filter>
<filter-name>DatabaseAuthenticationFilter</filter-name>
<filter-class>com.programmer.gate.filters.DatabaseAuthenticationFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>DatabaseAuthenticationFilter</filter-name>
<url-pattern>/DatabaseAuthenticatedServlet/*</url-pattern>
</filter-mapping>
这里的问题是,像/ DatabaseAuthenticatedServlet之类的请求也将匹配根URL模式“ / *”,即我们的请求将通过两个身份验证过程: LDAP和Database,其排序取决于首先在web.xml下定义哪个过滤器。
为了解决此问题,我们需要修改LDAPAuthenticationFilter ,以排除以/ DatabaseAuthenticatedServlet开头的URL 。 人们通常要做的是在doFilter()方法中静态检查请求的servlet URL,并在找到时简单地绕过身份验证过程。
在这里,我们进一步走了一步,实现了一个更加动态的解决方案,该解决方案使我们能够通过web.xml管理排除的URL。
以下是将排除功能添加到LDAPAuthenticationFilter的步骤:
- 添加名为List <String>类型的名为excludeUrls的新字段:
private List excludedUrls;
- 里面的init()方法,读取配置属性使用一个FilterConfig称为excludedUrls,属性应该是逗号分隔,使我们排除尽可能多的网址,因为我们需要。
public void init(FilterConfig filterConfig) throws ServletException { String excludePattern = filterConfig.getInitParameter("excludedUrls"); excludedUrls = Arrays.asList(excludePattern.split(",")); }
- 修改doFilter()以便检查请求的URL是否属于预定义的排除URL列表,如果是,则只需将请求转发到链中的下一个过滤器或Servlet,否则执行身份验证逻辑。
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { String path = ((HttpServletRequest) req).getServletPath(); if(!excludedUrls.contains(path)) { // Authenticate the request through LDAP System.out.println("Authenticating the request through LDAP"); } // Forward the request to the next filter or servlet in the chain. chain.doFilter(req, resp); }
- 现在在web.xml内部,您可以控制从LDAP身份验证中排除的URL,而无需任何代码更改:
<filter> <filter-name>LDAPAuthenticationFilter</filter-name> <filter-class>com.programmer.gate.filters.LDAPAuthenticationFilter</filter-class> <init-param> <param-name>excludedUrls</param-name> <!-- Comma separated list of excluded servlets --> <param-value>/DatabaseAuthenticatedServlet,/UnAuthenticatedServlet</param-value> </init-param> </filter>
添加排除功能后, LDAPAuthenticationFilter如下所示:
package com.programmer.gate.filters;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
public class LDAPAuthenticationFilter implements Filter{
private List excludedUrls;
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
throws IOException, ServletException {
String path = ((HttpServletRequest) req).getServletPath();
if(!excludedUrls.contains(path))
{
// Authenticate the request through LDAP
System.out.println("Authenticating the request through LDAP");
}
// Forward the request to the next filter or servlet in the chain.
chain.doFilter(req, resp);
}
public void init(FilterConfig filterConfig) throws ServletException {
String excludePattern = filterConfig.getInitParameter("excludedUrls");
excludedUrls = Arrays.asList(excludePattern.split(","));
}
public void destroy() {
// TODO Auto-generated method stub
}
}
2-第三方过滤器
第三方过滤器是您无法控制的过滤器。 即您不能修改其源代码。
在本节中,我们将对示例进行一些更改,并使用CAS身份验证而不是LDAP。 这就是我们在web.xml中定义CAS身份验证过滤器的方式:
<filter>
<filter-name>CAS Authentication Filter</filter-name>
<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
<init-param>
<param-name>casServerLoginUrl</param-name>
<param-value>https://localhost:8443/cas/login</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>localhost</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CAS Authentication Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
CAS身份验证是通过第三方库完成的,现在为了支持数据库身份验证,我们无法像在上一个LDAP示例中那样修改CAS的源代码。
从第三方过滤器中排除URL的解决方案是用一个新的自定义过滤器对其进行包装,该过滤器仅添加了exclude功能并将过滤器逻辑委托给包装的类。
以下是将排除功能添加到CAS身份验证的步骤:
- 创建一个名为CASCustomAuthenticationFilter的新过滤器,如下所示:
public class CASCustomAuthenticationFilter implements Filter{ private AuthenticationFilter casAuthenticationFilter = new AuthenticationFilter(); private List excludedUrls; public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { String path = ((HttpServletRequest) req).getServletPath(); if(!excludedUrls.contains(path)) { // Authenticate the request through CAS casAuthenticationFilter.doFilter(req,resp,chain); } // Forward the request to the next filter or servlet in the chain. chain.doFilter(req, resp); } public void init(FilterConfig arg0) throws ServletException { String excludePattern = filterConfig.getInitParameter("excludedUrls"); excludedUrls = Arrays.asList(excludePattern.split(",")); casAuthenticationFilter.init(); } public void destroy() { casAuthenticationFilter.destroy(); } }
我们的自定义过滤器通过构成将CAS验证过滤器包装起来,它的主要目的是仅管理要通过CAS验证的URL,而我们没有涉及CAS验证过程。
- 在web.xml中 ,我们将过滤器定义更改为使用CASCustomAuthenticationFilter而不是默认的CAS实现:
<filter> <filter-name>CAS Authentication Filter</filter-name> <filter-class>com.programmer.gate.filters.CASCustomAuthenticationFilter</filter-class> <init-param> <param-name>casServerLoginUrl</param-name> <param-value>https:localhost:8443/cas/login</param-value> </init-param> <init-param> <param-name>serverName</param-name> <param-value>localhost</param-value> </init-param> <init-param> <param-name>excludeUrls</param-name> <param-value>/DatabaseAuthenticatedServlet</param-value> </init-param> </filter> <filter-mapping> <filter-name>CAS Authentication Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
就是这样,请在下面的评论部分中留下您的想法。
翻译自: https://www.javacodegeeks.com/2018/04/how-to-exclude-a-url-from-a-filter.html
过滤器过滤特定的url