기사 디렉토리
실제 프로젝트에서 프런트엔드와 백엔드는 두 개의 다른 프로젝트로 나뉘고 각각 다른 도메인 이름으로 배포되므로 도메인 간 문제도 발생합니다.
이제 문제가 발생했으니 근본적으로 문제를 해결해야 하는데, 솔루션에 대해 이야기하기 전에 크로스 도메인이 무엇인지부터 이해해야 합니다.
교차 도메인이란 무엇입니까?
교차 도메인은 브라우저가 다른 웹사이트의 스크립트를 실행할 수 없음을 의미합니다. 이는 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.html
Callhttp://127.0.0.1:8080/user.jsp
localhost는 127.0.0.1과 동일하지만 동일한 기원이 아닙니다.
동일 출처 정책에 의해 제한되는 상황:
-
쿠키, LocalStorage 및 IndexDB를 읽을 수 없습니다.
-
DOM 및 Js 개체를 가져올 수 없습니다.
-
AJAX 요청을 보낼 수 없습니다.
참고: img, iframe 및 script와 같은 태그의 src 속성은 특수한 경우이며 동일 출처가 아닌 웹사이트의 리소스에 액세스할 수 있습니다.
교차 도메인 프로세스
교차 도메인 액세스의 예
두 개의 웹사이트가 있고 웹사이트 A는 http://localhost:8080
로컬 IP 포트 8080에 배포되고 웹사이트 B는 로컬 IP 포트 8081에 배포된다고 가정합니다 http://localhost:8081
.
이제 웹사이트 B의 페이지가 웹사이트 A의 정보를 방문하려고 하면 다음과 같이 페이지가 표시됩니다.
위의 도메인 간 문제가 발생했다는 오류 메시지에서 알 수 있습니다!
도메인 간 문제를 해결하는 방법은 무엇입니까?
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) {
}
}
요약하다
프런트엔드 솔루션
- JSONP를 사용하여 도메인 간 호출을 구현합니다.
- NodeJS 서버를 서비스 프록시로 사용하고 프런트 엔드는 NodeJS 서버에 대한 요청을 시작하고 NodeJS 서버 프록시는 요청을 백엔드 서버로 전달합니다.
백엔드 솔루션
- Nginx 리버스 프록시는 도메인 간 문제를 해결합니다.
- 서버 설정
Response Header
(응답 헤더)Access-Control-Allow-Origin
. - 도메인 간 액세스가 필요한 클래스 및 메서드에서 도메인 간 액세스를 허용합니다(예:
@CrossOrigin
Spring에서 주석 사용). - Spring Web의 CorsFilter(Spring MVC, Spring Boot에 적용 가능)를 상속받아 사용한다.
- WebMvcConfigurer 인터페이스(Spring Boot용)를 구현합니다.