我正在按照旧的教程来实现 Spring Security。不幸的是,
antMatchers
在我的配置类中不被认为是一种方法,所以经过一些研究,我相信requestMatchers
方法是它的等价物。但是,未经身份验证,路径 (/
) 仍处于阻塞状态。我想允许这样做。
这是我的控制器:
package com.quadri.springsecurity.controllers;
import java.util.Arrays;
import java.util.List;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.quadri.springsecurity.models.Student;
@RestController
@RequestMapping("api/v1/students")
public class StudentController {
private static final List<Student> STUDENTS = Arrays.asList(
new Student(1, "James Bond"),
new Student(2, "Maria Jones"),
new Student(3, "Anna Smith")
);
@GetMapping(path = "{studentId}")
public Student getStudent(@PathVariable("studentId") Integer studentId) {
return STUDENTS.stream()
.filter(student -> studentId.equals(student.getStudentId()))
.findFirst()
.orElseThrow(() -> new IllegalStateException("Student " + studentId + " does not exist!"));
}
}
这是我的配置文件:
package com.quadri.springsecurity.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
@EnableWebSecurity
public class ApplicationSecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests()
.requestMatchers( "resources/**", "/").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic();
return http.build();
}
}
在我的 resources/static 文件夹中,我创建了一个简单的 html 页面 (
index.html
),显示 hello world。在教程中,RequestMapping
没有改变,但是他们在配置文件中使用了.antMatcher
,这在Spring Security中不是公认的方法,至少在我使用的版本中是这样。这是我的POM供参考:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.quadri</groupId>
<artifactId>spring-security</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-security</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
确保允许主页或“/”URL 的正确方法是什么?
您应该在
index.html
请求匹配器中允许 HttpSecurity
,因为 /
正在自动重定向到 index.html
,并且没有为 index.html
定义允许规则来给出身份验证提示。以下设置应该有效:
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests()
.requestMatchers( "/resources/**", "/", "/index.html").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic();
return http.build();
}
正如您所怀疑的,问题可能来自最新的 Spring Boot 你使用的版本,在 pom 中是 3.0.1。如你看到的 这里,3.0及之后的版本是基于Spring框架6.0的。 Spring 框架 6.0 还使用 Spring Security 6.0,, 其中,不推荐使用 antMatchers() (以及其他 Matcher 方法) 用于 Spring 安全配置。 [参见此处和此处]。
此外,我建议忽略您希望访问的任何 URL 路径,例如“/**”或“/resources/**”,并仅保护 api 的其他路径,在您的情况下应该是您的控制器“/api/v1/students/**”中定义的一个。您可以按照与下面的代码片段类似的方式来完成此操作:
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// http
// .securityMatchers( (matchers) -> matchers
// .requestMatchers("/resources/**", "/"))
// .authorizeHttpRequests((authorize) -> authorize
// .anyRequest().permitAll());
http
.securityMatchers( (matchers) -> matchers
.requestMatchers("/api/v1/students/**"))
.authorizeHttpRequests((authorize) -> authorize
.anyRequest().authenticated())
.httpBasic();
return http.build();
}
这可以帮助其他人,特别是那些刚接触 jhipster + spring-security 的人:
如果您使用 Web 过滤器(例如 OncePerRequestFilter 或任何其他过滤器),请确保它不会过滤掉您的 api/端点
这里有一个例子:
public class MyWebFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// Request URI includes the contextPath if any, removed it.
String path = request.getRequestURI().substring(request.getContextPath().length());
if (
!path.startsWith("/my_api") &&
!path.contains(".") &&
path.matches("/(.*)")
) {
request.getRequestDispatcher("/index.html").forward(request, response);
return;
}
filterChain.doFilter(request, response);
}
}