我正在使用 Spring Security 学习 Spring Boot,并且我的 AuthController 中的 @PostMapping 端点遇到问题。 @GetMapping 端点工作正常,但 @PostMapping 端点永远不会被命中。我已经使用 Postman 验证了该请求,一切似乎都是正确的。详情如下:
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {
@Bean
public UserDetailsService userDetailsService() {
// Define your custom UserDetailsService implementation
return new CustomUserDetailsService();
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(req ->
req.requestMatchers(
"/auth/**",
"/css/**.css",
"/js/**"
).permitAll()
.anyRequest().authenticated()
)
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
return http.build();
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
}
@RestController
@RequestMapping("/auth")
public class AuthController {
@GetMapping("/test")
public String test() {
return "Testing GET in Auth Ctrl.";
}
@PostMapping("/login")
public String login(@RequestBody AuthRequest authRequest) {
try {
if(authRequest.getUsername() == null || authRequest.getPassword() == null)
throw new AuthenticationException("AuthRequest is empty");
// Assuming successful authentication, you would normally return a JWT token here
return "Login successful!";
} catch (AuthenticationException e) {
return "Login failed!";
}
}
}
@Data
@NoArgsConstructor
class AuthRequest {
private String username;
private String password;
}
@Service
public class CustomUserDetailsService implements UserDetailsService {
private final Map<String, String> usersMap = new HashMap<>();
@Autowired
public CustomUserDetailsService() {
// Initialize the usersMap with encoded passwords
usersMap.put("ricky", "$2a$10$Dow1SE9N1XzFxXh3YDJIoO/b0Zi4DlCg8Up7X5DpIS9b/T/xkaHOO"); // password: 123
usersMap.put("martin", "$2a$10$Dow1SE9N1XzFxXh3YDJIoO/b0Zi4DlCg8Up7X5DpIS9b/T/xkaHOO"); // password: 456
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if (usersMap.containsKey(username)) {
return new User(username, usersMap.get(username), new ArrayList<>()); // Empty authorities list
}
// If this is thrown, then we won't generate a JWT token.
throw new UsernameNotFoundException(username + " not found.");
}
}
用邮递员测试:
网址:http://localhost:8080/auth/login 方法:邮寄 标头:内容类型:application/json 正文:原始 JSON 示例正文:
{
"username": "ricky",
"password": "123"
}
我尝试过的:
问题: 尽管执行了上述步骤,@PostMapping 端点永远不会被命中,并且不会记录任何错误消息。 @GetMapping 端点工作正常。
附加信息: pom.xml
任何关于为什么 @PostMapping 端点没有被命中的见解或建议将不胜感激!
当然,如果 Spring Security Filter 返回禁止,它就不会到达你的方法:)
您还应该检查为什么会出现
403
,将日志记录级别设置为使用 logging.level.org.springframework.security=DEBUG
进行调试,以便您看到错误。
我愿意打赌,CSRF 正确地不允许您在没有 CSRF 令牌的情况下发送“危险”请求(基本上是任何其他请求,除了 GET)。
您应该首先发送某种请求(任何请求)以获得 CSRF cookie(自动添加到尚未拥有它的调用的响应中),然后将该 cookie 的值添加为 X-您的 POST 调用的 XSRF-TOKEN 标头。请参阅文档
如果您不依赖 cookie 进行身份验证并且不使用会话,您还可以考虑使用
关闭 CSRF http
.csrf(AbstractHttpConfigurer::disable)
// ...