我在第一个 JwtSecurity 应用程序中遇到身份验证问题。用户注册工作正常,并且使用令牌访问安全端点也成功。但是,“身份验证”(登录)操作始终会导致 403 Forbidden 错误。我不确定如何继续。我正在使用 Spring Boot 版本 3.0.10。这是我的代码片段
@RestController
@RequestMapping("/api/v1/auth")
@RequiredArgsConstructor
public class AuthenticationController {
@PostMapping("/authenticate")
public ResponseEntity<AuthenticationResponse> authenticate(
@RequestBody AuthenticationRequest request
) {
return ResponseEntity.ok(service.authenticate(request));
}
private final AuthenticationManager authenticationManager;
public AuthenticationResponse authenticate(AuthenticationRequest request) {
authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(
request.getEmail(),
request.getPassword()
)
);
var user = userRepository.findByEmail(request.getEmail())
.orElseThrow(() -> new RuntimeException("User not found"));
var jwtToken = jwtService.generateToken(user);
return AuthenticationResponse.builder()
.token(jwtToken)
.build();
}
@Configuration
@RequiredArgsConstructor
public class ApplicationConfig {
private final UserRepository userRepository;
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
return config.getAuthenticationManager();
}
@Bean
public AuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService());
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
@Component
@RequiredArgsConstructor
public class JwtAuthenticationFilter extends OncePerRequestFilter{
private final JwtService jwtService;
private final UserDetailsService userDetailsService;
@Override
protected void doFilterInternal(
@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull FilterChain filterChain)
throws ServletException, IOException {
final String authHeader = request.getHeader("Authorization");
final String jwt;
final String userEmail;
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
filterChain.doFilter(request, response);
return;
}
jwt = authHeader.substring(7);
userEmail= jwtService.extractUsername(jwt);
if(userEmail!=null && SecurityContextHolder.getContext().getAuthentication()==null){
UserDetails userDetails = this.userDetailsService.loadUserByUsername(userEmail);
if(jwtService.isTokenValid(jwt,userDetails)){
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
userDetails,
null,
userDetails.getAuthorities()
);
authToken.setDetails(
new WebAuthenticationDetailsSource().buildDetails(request)
);
SecurityContextHolder.getContext().setAuthentication(authToken);
}
}
filterChain.doFilter(request, response);
}
}
private final JwtAuthenticationFilter jwtAuthenticationFilter;
private final AuthenticationProvider authenticationProvider;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.authorizeHttpRequests()
.requestMatchers("api/v1/auth/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authenticationProvider(authenticationProvider)
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
我遵循了 Amigoscode JWT 授权教程,并且仔细检查了我的实现,但我仍然面临问题。尽管与教程进行比较并在网上搜索,但我找不到问题所在。你能帮我吗,拜托了
您忘记启用 CORS(跨域资源共享)。通过将其添加到您的过滤链方法中来完成此操作
http.cors().and().csrf().disable()