Reputation: 429
I am following an older tutorial to implement Spring Security. Unfortunately, antMatchers
is not recogzied as a method in my configuration class, so after doing some research, I believe requestMatchers
method is its equivalent. However, the path (/
) remains blocked without authentication. I would like to permit this.
Here is my controller:
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!"));
}
}
Here is my config file:
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();
}
}
In my resources/static folder I have created a simple html page (index.html
) displaying hello world. In the tutorial the RequestMapping
wasn't changed, however they used .antMatcher
in the config file which is not a recognized method in Spring Security at least the version I am using. Here is my POM for reference:
<?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>
What is the proper way to make sure the home or "/" URL is permitted?
Upvotes: 2
Views: 11658
Reputation: 116
This could help someone else specially those new to jhipster + spring-security:
In case you using a webfilter like for example OncePerRequestFilter or any other, ensure that is not filtering out your api/endpoints
Here an example:
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);
}
}
by excluding our api from the filter we keeping it accessible
Upvotes: 0
Reputation: 158
As you suspected, issues can come out from the Spring Boot newest version you use, which as it is in the pom is 3.0.1. As you can see here,versions 3.0 and afterward, are based on the Spring framework 6.0. The Spring framework 6.0 also uses the Spring Security 6.0,, where, antMatchers() (as well as other Matcher methods) are deprecated for Spring security configurations. [See here and here].
Moreover, I suggest leaving out any URL path you wish to be accessible, such as "/** " or "/resources/** " and protect just the other path(s) of your api, which in your case should be the one defined in your controller "/api/v1/students/** ". You can do that in a similar way as the snippet below:
@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();
}
Upvotes: 1
Reputation: 316
You should allow index.html
in the HttpSecurity
request matchers as going to /
is doing an auto-redirect to index.html
and there is no permit rule defined for index.html
giving an auth prompt. Below setting should work:
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests()
.requestMatchers( "/resources/**", "/", "/index.html").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic();
return http.build();
}
Upvotes: 6