admin管理员组文章数量:1352863
I am hosting a Next.js front-end and a Spring Boot back-end in Docker on the same server. The front-end runs on port 3001, and the back-end runs on port 8080.
Server IP (external address): 192.168.100.116
Front-end URL (inside the network): http://192.168.100.116:3001
Back-end API URL: http://192.168.100.116:8080/api/v1/auth/authenticate
When accessing the front-end from my PC (same WiFi network), I get this CORS error when trying to call the back-end API:
Access to XMLHttpRequest at 'http://192.168.100.116:8080/api/v1/auth/authenticate' from origin 'http://192.168.100.116:3001' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
✅ Calling API from localhost:3001 works.
❌ Calling API from 192.168.100.116:3001 fails with CORS error.
What additional steps should I take to properly configure CORS in Spring Boot and Docker networking to allow external front-end requests from 192.168.100.116:3001 to 192.168.100.116:8080?
Docker-compose file
version: "3.9"
services:
postgres_db:
restart: always
image: postgres:16.4
container_name: project_xxx_postgres_db
environment:
POSTGRES_USER: xxx
POSTGRES_PASSWORD: xxx
POSTGRES_DB: project-ai-reception-db
ports:
- "5431:5432"
volumes:
- project_xxx_container_data:/var/lib/postgresql/data
networks:
- project-ai-rec-network
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
backend:
restart: always
image: xxx/project-ai-reception-backend:0.0.122
container_name: project_xxx_backend
ports:
- "8080:8080"
networks:
- project-ai-rec-network
depends_on:
postgres_db:
condition: service_healthy
volumes:
- uploads:/app/uploads
- backend_logs:/app/logs
extra_hosts:
- "host.docker.internal:host-gateway"
environment:
- SPRING_APPLICATION_JSON={"server.address":"0.0.0.0"}
cms-frontend:
restart: always
image: xxx/project-ai-reception-cms:0.0.5
container_name: cms-frontend
ports:
- "3001:3001"
environment:
- NEXT_PUBLIC_BACKEND_URL=http://192.168.100.116:8080 # Use service name instead of IP
- NEXT_PUBLIC_XXX_VOLUME_MANAGER_URL=http://192.168.100.116:5000
depends_on:
- backend
- XXX-volume-manager
networks:
- project-ai-rec-network
volumes:
project_xxx_container_data:
uploads:
album:
backend_logs:
networks:
project-ai-rec-network:
Spring Boot project
package com.xxx.ai_reception_backend.config;
import lombok.RequiredArgsConstructor;
import .springframework.beans.factory.annotation.Value;
import .springframework.context.annotation.Bean;
import .springframework.context.annotation.Configuration;
import .springframework.http.HttpStatus;
import .springframework.security.authentication.AuthenticationProvider;
import .springframework.security.config.annotation.web.builders.HttpSecurity;
import .springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import .springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import .springframework.security.config.http.SessionCreationPolicy;
import .springframework.security.core.AuthenticationException;
import .springframework.security.web.AuthenticationEntryPoint;
import .springframework.security.web.SecurityFilterChain;
import .springframework.security.web.access.AccessDeniedHandler;
import .springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import .springframework.web.cors.CorsConfiguration;
import .springframework.web.cors.CorsConfigurationSource;
import .springframework.web.cors.UrlBasedCorsConfigurationSource;
import java.time.LocalDateTime;
import java.util.Arrays;
import static .springframework.security.config.Customizer.withDefaults;
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
// @Value("${spring.web.cors.allowed-origin-patterns-cms}")
// private String cms_frontend_url;
//
// @Value("${spring.web.cors.allowed-origin-patterns-frontdoor}")
// private String frontdoor_frontend_url;
private final JwtAuthenticationFilter jwtAuthFilter;
private final AuthenticationProvider authenicationProvider;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(AbstractHttpConfigurer::disable) // Updated way to disable CSRF
.cors(cors -> cors.configurationSource(corsConfigurationSource())) // Apply CORS config
//.cors(withDefaults()) // Ensure CORS is enabled
.headers(headers -> headers
.addHeaderWriter((request, response) -> {
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
response.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type");
response.setHeader("Access-Control-Allow-Credentials", "true");
})
)
.authorizeHttpRequests(auth -> auth
// Permit Swagger and API docs access without authentication
.requestMatchers(
"/v3/api-docs/**",
"/swagger-ui/**",
"/swagger-ui.html",
"/images/**",
"/album/image/**",
"/api/v1/attendance/create",
"/api/v1/workpass/broadcast/admin",
"/api/v1/mqtt/**",
"/api/v1/demo"
).permitAll()
// Define other public endpoints
.requestMatchers("/api/v1/auth/**").permitAll()
// Secure all other endpoints
.anyRequest().authenticated()
)
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS) // Set session management policy to stateless
)
.authenticationProvider(authenicationProvider) // Set the custom authentication provider
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class) // Add JWT filter before UsernamePasswordAuthenticationFilter
.exceptionHandling(exceptions -> {
exceptions
.accessDeniedHandler(accessDeniedHandler()) // Handle 403 Forbidden
.authenticationEntryPoint(authenticationEntryPoint()); // Handle 401 Unauthorized
});
return http.build();
}
// Custom Access Denied Handler for 403 Forbidden
@Bean
public AccessDeniedHandler accessDeniedHandler() {
return (HttpServletRequest request, HttpServletResponse response, .springframework.security.access.AccessDeniedException ex) -> {
response.setStatus(HttpServletResponse.SC_FORBIDDEN); // 403 FORBIDDEN
response.setContentType("application/json");
String jsonResponse = String.format(
"{\"message\": \"%s\", \"details\": %s, \"statusCode\": \"%d\", \"time\": \"%s\"}",
"You don't have permission to access this resource. "+ex.getMessage(),
"Access Denied",
HttpStatus.FORBIDDEN.value(),
LocalDateTime.now()
);
response.getWriter().write(jsonResponse);
};
}
@Bean
public AuthenticationEntryPoint authenticationEntryPoint() {
return (HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) -> {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // 401 UNAUTHORIZED
response.setContentType("application/json");
String jsonResponse = String.format(
"{\"message\": \"%s\", \"details\": %s, \"statusCode\": \"%d\", \"time\": \"%s\"}",
"Please login to access this resource. "+authException.getMessage(),
"Unauthorized",
HttpStatus.UNAUTHORIZED.value(),
LocalDateTime.now()
);
response.getWriter().write(jsonResponse);
};
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
// configuration.setAllowedOriginPatterns(Arrays.asList("*")); // Allow all origins
configuration.setAllowedOrigins(Arrays.asList(
"http://192.168.100.116:3001",
"http://192.168.100.116:3000",
"http://192.168.1.86:3000",
"http://192.168.1.86:3001"
));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
configuration.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type"));
configuration.setAllowCredentials(true); // Allow credentials like cookies
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
本文标签: javaCORS error when accessing backend from external addressStack Overflow
版权声明:本文标题:java - CORS error when accessing back-end from external address - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1743918630a2561671.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论