43、Spring Security 配置与资源保护详解

Spring Security 配置与资源保护详解

1. 启用 Spring Security

在对系统进行安全保护之前,需要先启用 Spring Security。其核心概念是捕获进入系统的每个请求,并决定是否允许该请求通过。这一机制始于标准的 JEE Servlet 过滤器。

Spring Security 使用 org.springframework.web.filter.DelegatingFilterProxy (它是标准 javax.servlet.Filter 的实现),该过滤器会被配置为拦截每个请求,并将捕获的请求委托给 Spring Security 处理。在 com.apress.prospringmvc.bookstore.web.BookstoreWebApplicationInitializer 中,可以使用 JEE 动态 Servlet API 来添加此过滤器,示例代码如下:

private void registerSpringSecurityFilterChain(ServletContext servletContext){ 
    FilterRegistration.Dynamic springSecurityFilterChain = 
      servletContext.addFilter(BeanIds.SPRING_SECURITY_FILTER_CHAIN, new 
      DelegatingFilterProxy()); 
    springSecurityFilte
public class SecurityConfig { private final JwtAuthenticationFilter jwtAuthFilter; private final AuthenticationProvider authenticationProvider; @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .csrf(csrf -> csrf.disable()) .authorizeHttpRequests(auth -> auth // 开放Swagger UI文档访问,但在超级管理员上才有访问权限 .requestMatchers("/swagger-ui.html").permitAll() .requestMatchers("/swagger-ui/**").permitAll() .requestMatchers("/v3/api-docs/**").permitAll() .requestMatchers("/swagger-resources/**").permitAll() .requestMatchers("/webjars/**").permitAll() // 公开接口 .requestMatchers("/api/auth/**").permitAll() .requestMatchers("/api/articles/index").permitAll() .requestMatchers("/api/articles/search").permitAll() .requestMatchers("/api/articles/{id}").permitAll() .requestMatchers("/api/articles/by-category/{id}").permitAll() .requestMatchers("/api/articles/by-tag/{id}").permitAll() .requestMatchers("/api/categories/all").permitAll() .requestMatchers("/api/tags/all").permitAll() .requestMatchers("/api/health/**").permitAll() // ADMIN权限接口 - 文章管理(增删改) .requestMatchers("/api/articles").hasRole("ADMIN") // POST, GET (后台管理列表) .requestMatchers(HttpMethod.POST, "/api/articles").hasRole("ADMIN") .requestMatchers(HttpMethod.PUT, "/api/articles/**").hasRole("ADMIN") .requestMatchers(HttpMethod.DELETE, "/api/articles/**").hasRole("ADMIN") // ADMIN权限接口 - 分类管理(增删改查) .requestMatchers("/api/categories").hasRole("ADMIN") // POST, GET (后台管理列表) .requestMatchers(HttpMethod.POST, "/api/categories").hasRole("ADMIN") .requestMatchers(HttpMethod.PUT, "/api/categories/**").hasRole("ADMIN") .requestMatchers(HttpMethod.DELETE, "/api/categories/**").hasRole("ADMIN") // ADMIN权限接口 - 标签管理(增删改查) .requestMatchers("/api/tags").hasRole("ADMIN") // POST, GET (后台管理列表) .requestMatchers(HttpMethod.POST, "/api/tags").hasRole("ADMIN") .requestMatchers(HttpMethod.PUT, "/api/tags/**").hasRole("ADMIN") .requestMatchers(HttpMethod.DELETE, "/api/tags/**").hasRole("ADMIN") // 需要认证的接口 .requestMatchers("/api/file/**").authenticated() .requestMatchers("/api/users/**").authenticated() // 其他请求都需要认证 .anyRequest().authenticated() ).headers(headers -> headers .frameOptions(frameOptions -> frameOptions.sameOrigin()) // 允许同域iframe ) .sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authenticationProvider(authenticationProvider) .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class); return http.build(); } } 但是现在这种参数的配置比如我想用/api/articles/index接口,后面是查询参数,会不会后面的配置 .requestMatchers("/api/articles").hasRole("ADMIN") // POST, GET (后台管理列表) 起到冲突,导致说对查询字符串敏感?
08-20
<think>我们正在讨论Spring Security的路径匹配问题。用户有两个具体问题: 1. Spring Security的requestMatchers路径匹配是否包含查询参数? 2. 配置中同时存在`/api/articles`和`/api/articles/index`是否存在冲突? 根据之前的回答,我们已经明确:Spring Security的路径匹配默认不包含查询参数。接下来,我们需要验证第二个问题:两个路径配置是否存在冲突。 首先,回顾一下Spring Security中路径匹配的规则: - Spring Security使用`AntPathMatcher`(默认)或`MvcPathMatcher`(如果启用)进行路径匹配。 - `AntPathMatcher`支持通配符匹配,例如`?`匹配一个字符,`*`匹配0个或多个字符,`**`匹配0个或多个目录。 现在,考虑两个路径: 1. `/api/articles` 2. `/api/articles/index` 这两个路径是不同的,因为: - `/api/articles` 会匹配: - `/api/articles` - `/api/articles/`(如果配置了`setTrailingSlashMatch`,默认为true,也会匹配) - 但不匹配`/api/articles/index`,因为`/api/articles`要求路径到此结束,而`/api/articles/index`有额外的子路径。 但是,注意`/api/articles`也可以匹配`/api/articles?xxx`(带查询参数),因为查询参数在匹配时被忽略。 另外,`/api/articles`和`/api/articles/index`是两个不同的路径,所以它们不会冲突。但是,如果配置了更宽泛的模式,比如`/api/articles/**`,那么它会匹配所有以`/api/articles/`开头的路径,包括`/api/articles/index`。 因此,如果配置如下: ```java http.authorizeRequests() .antMatchers("/api/articles").permitAll() .antMatchers("/api/articles/index").authenticated(); ``` 那么: - 访问`/api/articles`(无论有无查询参数)将被允许(permitAll)。 - 访问`/api/articles/index`需要认证(authenticated)。 但是,如果配置顺序颠倒,则需要注意:Spring Security的匹配规则是按照配置的顺序来的,第一个匹配的规则会被应用。 例如: ```java http.authorizeRequests() .antMatchers("/api/articles/**").permitAll() .antMatchers("/api/articles/index").authenticated(); ``` 在这种情况下,由于`/api/articles/**`会匹配`/api/articles/index`,所以第一个规则生效,即`/api/articles/index`也被允许了,第二个规则不会生效。 因此,为了避免冲突,应该将更具体的路径放在前面,更通用的放在后面。 所以,总结: 1. 查询参数不影响路径匹配。 2. 两个路径`/api/articles`和`/api/articles/index`本身不会冲突,但是配置时要注意顺序和通配符的使用。 现在,我们根据用户提供的引用,来验证一些配置方法: 引用[2]中提到,可以通过`WebSecurity`的`ignoring`方法来忽略某些路径: ```java @Override public void configure(WebSecurity web) { web.ignoring().antMatchers(permitUrls); } ``` 这里,同样遵循Ant风格的路径匹配,且忽略查询参数。 另外,引用[3]提到,Spring Security默认使用`/login`作为登录处理URL,这同样不受查询参数影响。 因此,针对用户的问题: 问题1:Spring Security的requestMatchers路径匹配不包含查询参数。 问题2:配置中`/api/articles`和`/api/articles/index`不会冲突,因为它们是两个不同的路径。但是,如果配置了通配符(如`/api/articles/**`)则可能覆盖更具体的路径,因此要注意配置顺序。 最后,我们给出建议:在配置时,将更具体的路径放在前面,更通用的放在后面,以避免被通用规则覆盖。 下面,我们按照要求生成相关问题。</think>在Spring Security中,路径匹配机制对查询参数**不敏感**,同时配置`/api/articles``api/articles/index`**可能存在冲突**,具体分析如下: ### 一、查询参数处理机制 1. **默认忽略查询参数** Spring Security的路径匹配(如`antMatchers()`)仅关注URI路径部分,**不包含查询参数**。例如: - 配置规则:`.antMatchers("/admin")` - 匹配路径:`/admin?user=test` ✅ - 匹配路径:`/admin?id=123` ✅ 底层通过`AntPathMatcher`实现,该匹配器会主动忽略`?`后的所有内容[^1]。 2. **需特殊处理查询参数的场景** 若需基于查询参数控制权限,需通过其他方式实现: ```java // 方法级安全控制(需启用@EnableMethodSecurity) @PreAuthorize("request.getParameter('token') == authentication.credentials") @GetMapping("/secure-data") public String secureData() { ... } ``` 或自定义`AccessDecisionVoter`动态解析请求参数[^3]。 --- ### 二、路径冲突分析 配置`/api/articles`和`/api/articles/index`时需警惕两种冲突: 1. **路径覆盖风险** 若配置顺序不当,通用路径可能覆盖具体路径: ```java http.authorizeRequests() .antMatchers("/api/articles/**").permitAll() // 覆盖下方规则 .antMatchers("/api/articles/index").authenticated(); // 此规则失效 ``` 2. **精确匹配优先级** **正确做法**是将具体路径前置: ```java http.authorizeRequests() .antMatchers("/api/articles/index").authenticated() // 优先匹配 .antMatchers("/api/articles/**").permitAll(); ``` --- ### 三、配置建议 1. **调试工具** 启用调试模式观察匹配过程: ```java @EnableWebSecurity(debug = true) // 控制台输出详细匹配日志 public class SecurityConfig extends WebSecurityConfigurerAdapter { ... } ``` 2. **路径冲突解决方案** ```java http.authorizeRequests() // 精确路径优先 .antMatchers(HttpMethod.GET, "/api/articles/index").authenticated() // 通用路径在后 .antMatchers("/api/articles/**").permitAll() // 完全匹配/api/articles(不含子路径) .antMatchers("/api/articles").hasRole("EDITOR"); ``` > **关键结论**: > - 查询参数**永不参**路径匹配 > - `/api/articles`会匹配所有以其开头的路径(如`/api/articles/123`), > 若需严格匹配**无后缀**的路径,应使用`.antMatchers("/api/articles").exactPath()`(需自定义配置) --- ### 附:路径匹配对照表 | 配置规则 | 匹配路径示例 | 是否包含子路径 | |-------------------------|----------------------------------|----------------| | `/api/articles` | `/api/articles` ✅ | 是(默认) | | `/api/articles` | `/api/articles?sort=date` ✅ | 是 | | `/api/articles` | `/api/articles/index` ✅ | 是 | | `/api/articles/index` | `/api/articles` ❌ | 否 | | `/api/articles/index` | `/api/articles/index?page=2` ✅ | 是(忽略参数) | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值