杰瑞科技汇

Java Filter如何拦截或处理特定URL?

Of course! In Java, filtering URLs is a common task, especially in web applications. The approach you take depends heavily on where you need to filter the URL.

Java Filter如何拦截或处理特定URL?-图1
(图片来源网络,侵删)

Here are the most common scenarios and how to handle them:

  1. In a Servlet Filter: Intercepting requests to your web application.
  2. Using Java's java.net Package: For standalone applications or simple URL validation.
  3. Using Regular Expressions: The most powerful and flexible method for pattern matching.

Let's break down each approach with code examples.


Scenario 1: Filtering URLs in a Servlet Filter (Web Applications)

This is the standard way to filter incoming requests in a Java web application (e.g., using Jakarta EE or Spring MVC). You can block access to certain URLs, log requests, or modify them.

A javax.servlet.Filter allows you to examine and manipulate HttpServletRequest and HttpServletResponse objects.

Java Filter如何拦截或处理特定URL?-图2
(图片来源网络,侵删)

Example: Blocking Admin URLs

Let's create a filter that blocks any user who tries to access a URL starting with /admin/ unless they are already logged in.

Create the Filter Class

import jakarta.servlet.*;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import java.io.IOException;
// This filter will apply to all URLs ("/*")
@WebFilter("/*")
public class AdminAccessFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // This method is called once when the filter is initialized.
        System.out.println("AdminAccessFilter initialized.");
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // Cast to HttpServletRequest to get session information
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        // Get the requested URL
        String requestURI = httpRequest.getRequestURI();
        // Define the protected path
        String adminPath = "/admin/";
        // Check if the request is for an admin page
        if (requestURI.startsWith(adminPath)) {
            // Check if the user is logged in (e.g., by checking a session attribute)
            HttpSession session = httpRequest.getSession(false); // false to not create a new session
            if (session == null || session.getAttribute("user") == null) {
                // User is not logged in, redirect to the login page
                System.out.println("Access to " + requestURI + " denied. Redirecting to login.");
                httpResponse.sendRedirect(httpRequest.getContextPath() + "/login.jsp");
                return; // Stop the filter chain
            }
        }
        // If the URL is not blocked or the user is authorized, continue to the next filter/servlet
        System.out.println("Allowing access to: " + requestURI);
        chain.doFilter(request, response);
    }
    @Override
    public void destroy() {
        // This method is called once when the filter is destroyed.
        System.out.println("AdminAccessFilter destroyed.");
    }
}

web.xml Configuration (Alternative to @WebFilter)

If you prefer XML configuration over annotations, you can define the filter in WEB-INF/web.xml:

Java Filter如何拦截或处理特定URL?-图3
(图片来源网络,侵删)
<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
         version="5.0">
    <filter>
        <filter-name>AdminAccessFilter</filter-name>
        <filter-class>com.yourpackage.AdminAccessFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>AdminAccessFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

Scenario 2: Filtering URLs in a Standalone Java Application

If you're not in a web container, you can use the java.net package to parse and validate URLs.

Example: Validating a URL's Protocol and Host

This example checks if a URL is valid and points to a specific domain.

import java.net.MalformedURLException;
import java.net.URL;
public class UrlValidator {
    public static boolean isValidAndAllowed(String urlString) {
        // A list of allowed domains
        String[] allowedDomains = {"example.com", "api.example.org"};
        try {
            URL url = new URL(urlString);
            // 1. Check if the protocol is HTTPS (secure)
            if (!"https".equalsIgnoreCase(url.getProtocol())) {
                System.out.println("URL rejected: Protocol must be HTTPS.");
                return false;
            }
            // 2. Check if the host is in the allowed list
            String host = url.getHost();
            boolean isAllowed = false;
            for (String domain : allowedDomains) {
                if (host.equals(domain) || host.endsWith("." + domain)) {
                    isAllowed = true;
                    break;
                }
            }
            if (!isAllowed) {
                System.out.println("URL rejected: Host '" + host + "' is not in the allowed list.");
                return false;
            }
            // 3. Check if the port is standard for HTTPS
            int port = url.getPort();
            if (port != -1 && port != 443) { // -1 means use the default port (443 for https)
                System.out.println("URL rejected: Non-standard port " + port + " used.");
                return false;
            }
            System.out.println("URL '" + urlString + "' is valid and allowed.");
            return true;
        } catch (MalformedURLException e) {
            System.out.println("URL rejected: Malformed URL - " + e.getMessage());
            return false;
        }
    }
    public static void main(String[] args) {
        String testUrl1 = "https://example.com/page";
        String testUrl2 = "http://malicious-site.com/data";
        String testUrl3 = "https://api.example.org/v1/users";
        String testUrl4 = "https://example.com:8443/secure"; // Non-standard port
        String testUrl5 = "not-a-valid-url";
        isValidAndAllowed(testUrl1); // Valid and allowed
        isValidAndAllowed(testUrl2); // Rejected: wrong protocol
        isValidAndAllowed(testUrl3); // Valid and allowed
        isValidAndAllowed(testUrl4); // Rejected: non-standard port
        isValidAndAllowed(testUrl5); // Rejected: malformed
    }
}

Scenario 3: Using Regular Expressions for Pattern Matching

Regular expressions are extremely powerful for matching complex URL patterns. This can be used within a Servlet Filter or a standalone application.

Example: Matching Specific URL Patterns

Let's say you want to:

  1. Allow URLs that start with /public/.
  2. Allow URLs that match /api/v[1-3]/products/.* (e.g., /api/v1/products/123, /api/v2/products/list).
  3. Block everything else.
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class UrlPatternMatcher {
    // Pre-compile the regex for better performance if used frequently
    private static final Pattern PUBLIC_PATTERN = Pattern.compile("^/public/.*");
    private static final Pattern API_PATTERN = Pattern.compile("^/api/v[1-3]/products/.*");
    public static boolean isAllowed(String urlPath) {
        // 1. Check for public access
        if (PUBLIC_PATTERN.matcher(urlPath).matches()) {
            System.out.println("Allowing (Public): " + urlPath);
            return true;
        }
        // 2. Check for API version constraint
        if (API_PATTERN.matcher(urlPath).matches()) {
            System.out.println("Allowing (API): " + urlPath);
            return true;
        }
        // 3. If neither pattern matches, block it
        System.out.println("Blocking: " + urlPath);
        return false;
    }
    public static void main(String[] args) {
        String path1 = "/public/home.html";
        String path2 = "/api/v1/products/99";
        String path3 = "/api/v4/products/new"; // v4 is not allowed
        String path4 = "/admin/dashboard";
        String path5 = "/public/images/logo.png";
        isAllowed(path1); // Allowing (Public)
        isAllowed(path2); // Allowing (API)
        isAllowed(path3); // Blocking
        isAllowed(path4); // Blocking
        isAllowed(path5); // Allowing (Public)
    }
}

Summary: Which Method to Choose?

Scenario Best Method Why?
Web Application Security Servlet Filter It's the standard, declarative way to intercept and control access to resources in a web container. It's integrated with the request/response lifecycle.
URL Validation / Parsing java.net.URL Provides built-in parsing, validation (throws MalformedURLException), and easy access to URL components (protocol, host, port, path, etc.).
Complex Pattern Matching Regular Expressions Offers unparalleled flexibility for defining complex rules (e.g., version numbers, specific path segments, query parameters). Can be used anywhere in your Java code.

For most web development tasks, the Servlet Filter is the correct tool for the job. For non-web applications or when you need to inspect the URL string itself, using java.net.URL with Regular Expressions is the most robust approach.

分享:
扫描分享到社交APP
上一篇
下一篇