У меня есть проект Spring Boot, использующий взаимный TLS. Все отлично работает для любых конечных точек GET, но мои конечные точки POST возвращают следующее:
{
"timestamp": "2020-03-26T11:28:38.778+0000",
"status": 403,
"error": "Forbidden",
"message": "Forbidden",
"path": "/audit/joe"
}
Я предполагаю, что делаю что-то не так, но не вижу этого.
Вот моя конфигурация:
@SpringBootApplication
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
public class X509AuthenticationServer extends WebSecurityConfigurerAdapter
{
public static void main(final String[] args)
{
SpringApplication.run(X509AuthenticationServer.class, args);
}
@Override
protected void configure(final HttpSecurity http) throws Exception
{
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.x509()
.subjectPrincipalRegex("CN=(.*?)(?:,|$)")
.userDetailsService(userDetailsService());
}
@Bean
public UserDetailsService userDetailsService()
{
return new UserDetailsService()
{
@Override
public UserDetails loadUserByUsername(final String username) throws UsernameNotFoundException
{
System.out.println("userDetailsService::loadUserByUsername() :: Username: " + username);
if (username.equalsIgnoreCase("allowed-user"))
{
return new User(username, "", AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER"));
} else
{
throw new UsernameNotFoundException(String.format("User %s not found", username));
}
}
};
}
}
И мой контроллер следующий:
@RestController
public class AuditController
{
@PreAuthorize("hasAuthority('ROLE_USER')")
@RequestMapping(value = "/audit/{username}", method = RequestMethod.POST), consumes = "application/json")
public void audit(@PathVariable("username") final String username,
@RequestBody final AuditRequest auditRequest,
final HttpServletResponse response) throws JsonProcessingException
{
// Business logic
response.setStatus(201);
}
}
Метод GET этого контроллера работает, как и ожидалось:
@Controller
public class UserController
{
@PreAuthorize("hasAuthority('ROLE_USER')")
@RequestMapping(value = "/user", method = RequestMethod.GET)
public String user(final Model model, final Principal principal)
{
final UserDetails currentUser = (UserDetails) ((Authentication) principal).getPrincipal();
model.addAttribute("username", currentUser.getUsername());
return "user";
}
}
И вот мои зависимости:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
</dependencies>