직장에서 도메인 간 문제를 해결하는 방법은 무엇입니까?


실제 프로젝트에서 프런트엔드와 백엔드는 두 개의 다른 프로젝트로 나뉘고 각각 다른 도메인 이름으로 배포되므로 도메인 간 문제도 발생합니다.

이제 문제가 발생했으니 근본적으로 문제를 해결해야 하는데, 솔루션에 대해 이야기하기 전에 크로스 도메인이 무엇인지부터 이해해야 합니다.

교차 도메인이란 무엇입니까?

교차 도메인은 브라우저가 다른 웹사이트의 스크립트를 실행할 수 없음을 의미합니다. 이는 JavaScript에서 브라우저가 부과하는 보안 제한인 브라우저의 동일 출처 정책으로 인해 발생합니다.

동일 출처 정책이란 무엇입니까?

소위 상동성은 프로토콜, 도메인 이름 및 포트 번호가 모두 동일하며 그 중 하나가 다른 한 모두 동일하지 않은 출처를 나타냅니다.

동일 출처 정책은 넷스케이프에서 제안한 보안 정책으로 브라우저의 핵심이자 가장 기본적인 보안 기능으로, 동일 출처 정책이 누락될 경우 브라우저의 정상적인 기능에 영향을 미칠 수 있습니다. 이제 지원하는 모든 브라우저는 자바스크립트는 이 전략을 사용할 것입니다.

브라우저는 스크립트를 실행할 때 해당 스크립트가 속한 페이지, 즉 동일한 출처의 스크립트인지 확인하여 동일한 출처의 스크립트만 실행합니다. 데이터가 없으면 브라우저는 예외를 보고하고 액세스 거부 메시지를 표시합니다.

  • http://www.a.com/index.html호출 http://www.a.com/user.jsp프로토콜, 도메인 이름 및 포트 번호는 소스가 동일하며 모두 동일합니다.

  • https://www.a.com/index.html호출 http://www.a.com/user.jsp프로토콜은 다르며 동일한 출처가 아닙니다.

  • http://www.a.com:8080/index.html호출 http://www.a.com:8081/user.jsp포트는 다르며 동일한 출처가 아닙니다.

  • http://www.a.com/index.html호출 http://www.b.com/user.jsp도메인 이름은 다르며 출처가 동일하지 않습니다.

  • http://localhost:8080/index.htmlCall http://127.0.0.1:8080/user.jsplocalhost는 127.0.0.1과 동일하지만 동일한 기원이 아닙니다.

동일 출처 정책에 의해 제한되는 상황:

  1. 쿠키, LocalStorage 및 IndexDB를 읽을 수 없습니다.

  2. DOM 및 Js 개체를 가져올 수 없습니다.

  3. AJAX 요청을 보낼 수 없습니다.

참고: img, iframe 및 script와 같은 태그의 src 속성은 특수한 경우이며 동일 출처가 아닌 웹사이트의 리소스에 액세스할 수 있습니다.

교차 도메인 프로세스

d962ac838197193520f073411ac9393.png

교차 도메인 액세스의 예

두 개의 웹사이트가 있고 웹사이트 A는 http://localhost:8080로컬 IP 포트 8080에 배포되고 웹사이트 B는 로컬 IP 포트 8081에 배포된다고 가정합니다 http://localhost:8081.

이제 웹사이트 B의 페이지가 웹사이트 A의 정보를 방문하려고 하면 다음과 같이 페이지가 표시됩니다.

이미지.png

위의 도메인 간 문제가 발생했다는 오류 메시지에서 알 수 있습니다!

도메인 간 문제를 해결하는 방법은 무엇입니까?

1. 필터

Filter 필터를 사용하여 서비스 요청을 필터링하고 Response Header(응답 헤더)의 Access-Control-Allow-Origin 속성을 요청자에게 설정하여 도메인 간 액세스가 허용됨을 선언합니다.

@WebFilter
public class CorsFilter implements Filter {
    
      

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
    
      
        HttpServletResponse response = (HttpServletResponse) res;  
        response.setHeader("Access-Control-Allow-Origin", "*");  
        response.setHeader("Access-Control-Allow-Methods", "*");  
        response.setHeader("Access-Control-Max-Age", "3600");  
        response.setHeader("Access-Control-Allow-Headers", "*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        chain.doFilter(req, res);  
    }  
}

2. HandlerInterceptorAdapter 상속

@Component
public class CrossInterceptor extends HandlerInterceptorAdapter {
    
    

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    
    
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        return true;
    }
}

3. WebMvcConfigurer 구현

@Configuration
@SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection")
public class AppConfig implements WebMvcConfigurer {
    
    

    @Override
    public void addCorsMappings(CorsRegistry registry) {
    
    
        registry.addMapping("/**")  // 拦截所有的请求
                .allowedOrigins("http://www.abc.com")  // 可跨域的域名,可以为 *
                .allowCredentials(true)
                .allowedMethods("*")   // 允许跨域的方法,可以单独配置
                .allowedHeaders("*");  // 允许跨域的请求头,可以单独配置
    }
}

4. Nginx 구성 사용

location / {

   add_header Access-Control-Allow-Origin *;
   add_header Access-Control-Allow-Headers X-Requested-With;
   add_header Access-Control-Allow-Methods GET,POST,PUT,DELETE,OPTIONS;

   if ($request_method = 'OPTIONS') {
     return 204;
   }
}

5. @CrossOrgin주석 사용

도메인 간 일부 인터페이스만 원하고 구성을 사용하여 관리하지 않으려는 경우 이 방법을 사용할 수 있습니다.

컨트롤러에서 사용

@CrossOrigin
@RestController
@RequestMapping("/user")
public class UserController {
    
    

	@GetMapping("/{id}")
	public User get(@PathVariable Long id) {
    
    
		
	}

	@DeleteMapping("/{id}")
	public void remove(@PathVariable Long id) {
    
    

	}
}

특정 인터페이스에서 사용

@RestController
@RequestMapping("/user")
public class UserController {
    
    

	@CrossOrigin
	@GetMapping("/{id}")
	public User get(@PathVariable Long id) {
    
    
		
	}

	@DeleteMapping("/{id}")
	public void remove(@PathVariable Long id) {
    
    

	}
}

요약하다

프런트엔드 솔루션

  1. JSONP를 사용하여 도메인 간 호출을 구현합니다.
  2. NodeJS 서버를 서비스 프록시로 사용하고 프런트 엔드는 NodeJS 서버에 대한 요청을 시작하고 NodeJS 서버 프록시는 요청을 백엔드 서버로 전달합니다.

백엔드 솔루션

  • Nginx 리버스 프록시는 도메인 간 문제를 해결합니다.
  • 서버 설정 Response Header(응답 헤더) Access-Control-Allow-Origin.
  • 도메인 간 액세스가 필요한 클래스 및 메서드에서 도메인 간 액세스를 허용합니다(예: @CrossOriginSpring에서 주석 사용).
  • Spring Web의 CorsFilter(Spring MVC, Spring Boot에 적용 가능)를 상속받아 사용한다.
  • WebMvcConfigurer 인터페이스(Spring Boot용)를 구현합니다.

추천

출처blog.csdn.net/jiang_wang01/article/details/131366267