为什么 Spring Security 拒绝来自我前端的调用?

问题描述 投票:0回答:1

我正在为我的 TFC 制作一个完整的堆栈应用程序,使用 Java 和 Spring Boot 作为后端,并使用 Angular 和前端。但是,当发出

GET
请求时,Spring Boot 安全性拒绝了我的请求。

这些是我得到的 Spring Boot 安全日志:

2024-12-23T12:42:44.562+01:00  INFO 14252 --- [nio-8080-exec-2] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring DispatcherServlet 'dispatcherServlet'
2024-12-23T12:42:44.562+01:00  INFO 14252 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Initializing Servlet 'dispatcherServlet'
2024-12-23T12:42:44.565+01:00  INFO 14252 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet        : Completed initialization in 3 ms
2024-12-23T12:42:44.594+01:00 DEBUG 14252 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy        : Securing GET /park/emergencies
2024-12-23T12:42:44.594+01:00 DEBUG 14252 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy        : Securing GET /park/dinosaurs
2024-12-23T12:42:44.594+01:00 DEBUG 14252 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : Securing GET /park/enclosures
2024-12-23T12:42:44.595+01:00 DEBUG 14252 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Securing GET /park/status
2024-12-23T12:42:44.790+01:00 DEBUG 14252 --- [nio-8080-exec-2] o.s.s.w.a.Http403ForbiddenEntryPoint     : Pre-authenticated entry point called. Rejecting access
2024-12-23T12:42:44.790+01:00 DEBUG 14252 --- [nio-8080-exec-4] o.s.s.w.a.Http403ForbiddenEntryPoint     : Pre-authenticated entry point called. Rejecting access
2024-12-23T12:42:44.790+01:00 DEBUG 14252 --- [nio-8080-exec-1] o.s.s.w.a.Http403ForbiddenEntryPoint     : Pre-authenticated entry point called. Rejecting access
2024-12-23T12:42:44.790+01:00 DEBUG 14252 --- [nio-8080-exec-3] o.s.s.w.a.Http403ForbiddenEntryPoint     : Pre-authenticated entry point called. Rejecting access
2024-12-23T12:42:44.801+01:00 DEBUG 14252 --- [nio-8080-exec-1] o.s.security.web.FilterChainProxy        : Securing GET /error
2024-12-23T12:42:44.801+01:00 DEBUG 14252 --- [nio-8080-exec-4] o.s.security.web.FilterChainProxy        : Securing GET /error
2024-12-23T12:42:44.801+01:00 DEBUG 14252 --- [nio-8080-exec-2] o.s.security.web.FilterChainProxy        : Securing GET /error
2024-12-23T12:42:44.801+01:00 DEBUG 14252 --- [nio-8080-exec-3] o.s.security.web.FilterChainProxy        : Securing GET /error
2024-12-23T12:42:44.801+01:00 DEBUG 14252 --- [nio-8080-exec-1] o.s.s.w.a.Http403ForbiddenEntryPoint     : Pre-authenticated entry point called. Rejecting access
2024-12-23T12:42:44.801+01:00 DEBUG 14252 --- [nio-8080-exec-4] o.s.s.w.a.Http403ForbiddenEntryPoint     : Pre-authenticated entry point called. Rejecting access
2024-12-23T12:42:44.801+01:00 DEBUG 14252 --- [nio-8080-exec-2] o.s.s.w.a.Http403ForbiddenEntryPoint     : Pre-authenticated entry point called. Rejecting access
2024-12-23T12:42:44.801+01:00 DEBUG 14252 --- [nio-8080-exec-3] o.s.s.w.a.Http403ForbiddenEntryPoint     : Pre-authenticated entry point called. Rejecting access
2024-12-23T12:42:45.892+01:00 DEBUG 14252 --- [nio-8080-exec-5] o.s.security.web.FilterChainProxy        : Securing PUT /park/update
2024-12-23T12:42:45.897+01:00 DEBUG 14252 --- [nio-8080-exec-5] o.s.s.w.a.Http403ForbiddenEntryPoint     : Pre-authenticated entry point called. Rejecting access
2024-12-23T12:42:45.898+01:00 DEBUG 14252 --- [nio-8080-exec-5] o.s.security.web.FilterChainProxy        : Securing PUT /error
2024-12-23T12:42:45.900+01:00 DEBUG 14252 --- [nio-8080-exec-5] o.s.s.w.a.Http403ForbiddenEntryPoint     : Pre-authenticated entry point called. Rejecting access

我比较了前端和后端这两个令牌,它们是相同的,所以我不知道为什么他们拒绝我的请求。

这是我配置CORS的类:

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    private final JwtFilter jwtFilter;

    @Autowired
    public SecurityConfig(JwtFilter jwtFilter){
        this.jwtFilter=jwtFilter;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .cors(Customizer.withDefaults())
                .csrf(AbstractHttpConfigurer::disable)
                .authorizeHttpRequests(auth -> auth
                        .requestMatchers("/auth/register", "/auth/login").permitAll()
                        .anyRequest().authenticated()
                )
                .anonymous(AbstractHttpConfigurer::disable)
                .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
        return http.build();
    }

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(List.of("http://localhost:4200"));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
        configuration.setAllowedHeaders(List.of("Authorization", "Content-Type", "Accept"));
        configuration.setExposedHeaders(List.of("Authorization"));
        configuration.setMaxAge(3600L);
        configuration.setAllowCredentials(true);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

这是

JwtFilter
:

@Component
public class JwtFilter implements Filter {

    private final JwtUtil jwtUtil;



    @Autowired
    public JwtFilter(JwtUtil jwtUtil){
        this.jwtUtil=jwtUtil;
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String authHeader = httpRequest.getHeader("Authorization");
//        System.out.println(authHeader+" solicitud desde el fornted");

          String path = httpRequest.getRequestURI();

        if ( path.startsWith("/auth")) {
            chain.doFilter(request, response);
            return;
        }
        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            String token = authHeader.substring(7);
            try {
                String userId=jwtUtil.validateToken(token);
                httpRequest.setAttribute("userId",userId);
                System.out.println("Token válido. UserId extraído: " + userId+" token "+authHeader);
            } catch (Exception e) {
                HttpServletResponse httpResponse = (HttpServletResponse) response;
//                System.out.println("Error al validar el token de jwt filter " + e.getMessage()+ " "+token);
                httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Token inválido");
                return;
            }
        }

        chain.doFilter(request, response);
    }

这是我用来生成令牌的类

@Component
public class JwtUtil {

    @Value("${jwtKey}")
    private String secretKey;

    @Value("${jwtKeyExpiration}")
    private long keyExpiration;

    private Key key;

    @PostConstruct
    public void init() {
        key = Keys.hmacShaKeyFor(secretKey.getBytes());
    }
    //genero un token con enlazado con el id del usuario mi key, que durara una 1 hora(despues el usuario
    //Tendra que iniciar sesion de nuevo
    public String generateToken(String userId) {
        Map<String, Object> claims = new HashMap<>();
        return Jwts.builder()
                .claims(claims)
                .subject(userId)
                .issuedAt(new Date())
                .expiration(new Date(System.currentTimeMillis() + keyExpiration))
                .signWith(key, SignatureAlgorithm.HS256)
                .compact();
    }

    public String validateToken(String token) {
        Claims claims = Jwts.parser()
                .setSigningKey(key)
                .build()
                .parseSignedClaims(token)
                .getPayload();
        return claims.getSubject();
    }
}

如何修复 403 CORS 错误?

首先我比较了令牌,后端在登录时是否正确地将它们发送到前端,以及是否相同。 我还查看了该网站上有关安全错误的其他帖子,但它对我不起作用。

我得到的 CORS 错误是:

Request URL:
http://localhost:8080/park/update
Request Method:
PUT
Status Code:
403 Forbidden
Remote Address:
[::1]:8080
Referrer Policy:
strict-origin-when-cross-origin
access-control-allow-credentials:
true
access-control-allow-origin:
http://localhost:4200
access-control-expose-headers:
Authorization
cache-control:
no-cache, no-store, max-age=0, must-revalidate
connection:
keep-alive
content-length:
0
date:
Mon, 23 Dec 2024 11:47:17 GMT
expires:
0
keep-alive:
timeout=60
pragma:
no-cache
vary:
Origin
vary:
Access-Control-Request-Method
vary:
Access-Control-Request-Headers
x-content-type-options:
nosniff
x-frame-options:
DENY
x-xss-protection:
0
accept:
application/json, text/plain, */*
accept-encoding:
gzip, deflate, br, zstd
accept-language:
es-ES,es;q=0.9
authorization:
Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIiwiaWF0IjoxNzM0OTUzMTM0LCJleHAiOjE3MzQ5NTY3MzR9.x6VAuPFWyr2AaASPMO3Th7_6d7MDRyoEuwVdlxJf95U
connection:
keep-alive
content-length:
0
host:
localhost:8080
origin:
http://localhost:4200
referer:
http://localhost:4200/
sec-ch-ua:
"Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"
sec-ch-ua-mobile:
?0
sec-ch-ua-platform:
"Windows"
sec-fetch-dest:
empty
sec-fetch-mode:
cors
sec-fetch-site:
same-site
user-agent:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36

这是我在前端使用的拦截器:

    export const authInterceptor: HttpInterceptorFn = (req: HttpRequest<any>, next: HttpHandlerFn): Observable<HttpEvent<any>> => {
  const token = localStorage.getItem('token');
  console.log("El token es del fronted "+token)
  const clonedRequest = token
    ? req.clone({
        setHeaders: {
          Authorization: `Bearer ${token}`,
        },
        withCredentials: true
      })
    : req.clone({ withCredentials: true });

  return next(clonedRequest);
};
java spring-boot spring-security jwt cors
1个回答
0
投票

在设置允许的起点时尝试允许所有路径。
所以改变这个

configuration.setAllowedOrigins(List.of("http://localhost:4200"));

像这样:

configuration.setAllowedOrigins(List.of("http://localhost:4200/**"));

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.