You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在非Spring环境(含嵌入式Tomcat)中编程式使用Spring Security?

纯编程式配置Spring Security(无Spring注解 + 嵌入式Tomcat)

要在完全不依赖Spring注解、类路径扫描的前提下使用Spring Security,同时搭配纯编程式配置的嵌入式Tomcat,核心是手动构建Spring Security过滤器链并绑定到Tomcat的ServletContext,全程通过代码完成所有组件的初始化与注册。以下是完整的实现步骤和示例代码:

1. 依赖配置

确保项目引入必要的核心依赖(无需Spring Boot自动配置类):

<!-- 嵌入式Tomcat核心 -->
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-core</artifactId>
    <version>10.1.18</version>
</dependency>
<!-- Spring Security核心 -->
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-web</artifactId>
    <version>6.2.3</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-config</artifactId>
    <version>6.2.3</version>
</dependency>
<!-- Spring核心依赖 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>6.1.4</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>6.1.4</version>
</dependency>

2. 手动构建Spring Security过滤器链

不使用任何注解,直接通过HttpSecurity构建安全规则与过滤器链:

import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

public class SecurityConfig {
    public SecurityFilterChain buildSecurityFilterChain(HttpSecurity http) throws Exception {
        // 配置URL授权规则
        http.authorizeHttpRequests(auth -> auth
                .requestMatchers("/public/**").permitAll() // 公开路径无需认证
                .anyRequest().authenticated() // 其余路径需认证
        );
        
        // 添加自定义过滤器(示例)
        http.addFilterBefore(new CustomSecurityFilter(), UsernamePasswordAuthenticationFilter.class);
        
        // 演示用:禁用CSRF(生产环境按需开启)
        http.csrf(csrf -> csrf.disable());
        
        // 可按需添加认证方式,比如HTTP Basic:
        // http.httpBasic();
        
        return http.build();
    }
}

// 自定义过滤器示例
class CustomSecurityFilter implements javax.servlet.Filter {
    @Override
    public void doFilter(javax.servlet.ServletRequest req, javax.servlet.ServletResponse res, javax.servlet.FilterChain chain) throws java.io.IOException, javax.servlet.ServletException {
        System.out.println("[Custom Filter] 处理请求: " + ((javax.servlet.http.HttpServletRequest) req).getRequestURI());
        chain.doFilter(req, res);
    }
}

3. 嵌入式Tomcat的纯编程式配置与组件注册

手动启动Tomcat,初始化Spring上下文并注册Spring Security过滤器、自定义Servlet:

import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.startup.Tomcat;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
import org.springframework.web.context.support.GenericWebApplicationContext;

import javax.servlet.ServletRegistration;

public class TomcatSecurityLauncher {
    public static void main(String[] args) throws LifecycleException {
        // 初始化嵌入式Tomcat
        Tomcat tomcat = new Tomcat();
        tomcat.setPort(8080);
        Context tomcatContext = tomcat.addContext("", System.getProperty("java.io.tmpdir"));

        // 1. 初始化Spring Web上下文(无注解、无扫描)
        GenericWebApplicationContext springContext = new GenericWebApplicationContext();
        // 注册SecurityConfig到Spring上下文
        springContext.registerBean(SecurityConfig.class);
        springContext.refresh();

        // 2. 注册Spring Security过滤器到Tomcat
        AbstractSecurityWebApplicationInitializer securityInitializer = new AbstractSecurityWebApplicationInitializer() {
            @Override
            protected org.springframework.web.context.WebApplicationContext createServletApplicationContext() {
                return springContext;
            }
        };
        securityInitializer.onStartup(tomcatContext.getServletContext());

        // 3. 注册自定义Servlet(无@WebServlet注解)
        javax.servlet.Servlet protectedServlet = new javax.servlet.http.HttpServlet() {
            @Override
            protected void doGet(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp) throws javax.servlet.ServletException, java.io.IOException {
                resp.getWriter().write("已通过认证,访问受保护资源");
            }
        };
        ServletRegistration.Dynamic servletReg = tomcatContext.addServlet("ProtectedServlet", protectedServlet);
        servletReg.addMapping("/private/**");

        // 注册公开Servlet
        javax.servlet.Servlet publicServlet = new javax.servlet.http.HttpServlet() {
            @Override
            protected void doGet(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp) throws javax.servlet.ServletException, java.io.IOException {
                resp.getWriter().write("公开资源,无需认证");
            }
        };
        ServletRegistration.Dynamic publicServletReg = tomcatContext.addServlet("PublicServlet", publicServlet);
        publicServletReg.addMapping("/public/**");

        // 启动Tomcat
        tomcat.start();
        tomcat.getServer().await();
    }
}

关键细节说明

  • Spring上下文:使用GenericWebApplicationContext手动注册Bean,完全替代注解驱动的上下文,避免类路径扫描。
  • Security过滤器注册:通过AbstractSecurityWebApplicationInitializer将Spring Security的过滤器链注入Tomcat的ServletContext,无需依赖Spring的自动配置机制。
  • Servlet注册:直接创建Servlet实例并通过Tomcat的API完成注册,完全抛弃@WebServlet等注解。

验证运行

启动TomcatSecurityLauncher的main方法后:

  • 访问http://localhost:8080/public/test:直接返回公开内容,无拦截
  • 访问http://localhost:8080/private/test:若未配置认证方式(如HTTP Basic),会返回401未授权;若添加了http.httpBasic(),则会弹出认证窗口,输入正确凭证后可访问受保护内容

内容的提问来源于stack exchange,提问作者BBB

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 07:07:49