spring MVC cors 크로스 필드 에서 소스 코드 분석 실현
쉽게 말 하면 프로 토 콜,IP,http 방법 이 임의로 다 르 면 크로스 필드 입 니 다.
spring MVC 는 4.2 부터 도 메 인 간 지원 을 추가 합 니 다.
크로스 필드 의 구체 적 인 정 의 는 이동 하 십시오mozilla보 세 요.
사용 사례
spring mvc 에서 도 메 인 을 넘 어 사용 하 는 방법 은 세 가지 가 있 습 니 다.
웹.xml 에 CorsFilter 설정
<filter>
<filter-name>cors</filter-name>
<filter-class>org.springframework.web.filter.CorsFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>cors</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
xml 에 설정
// , ,
<mvc:cors>
<mvc:mapping path="/**" />
</mvc:cors>
//
<mvc:cors>
<mvc:mapping path="/api/**"
allowed-origins="http://domain1.com, http://domain2.com"
allowed-methods="GET, PUT"
allowed-headers="header1, header2, header3"
exposed-headers="header1, header2" allow-credentials="false"
max-age="123" />
<mvc:mapping path="/resources/**"
allowed-origins="http://domain1.com" />
</mvc:cors>
주 해 를 사용 하 다
@CrossOrigin(maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {
@CrossOrigin("http://domain2.com")
@RequestMapping("/{id}")
public Account retrieve(@PathVariable Long id) {
// ...
}
}
개념 에 관련되다봉 인 된 메시지 의 pojo
CorsConfiguration
request 와 크로스 필드 설정 정 보 를 저장 하 는 용기
CorsConfigurationSource、UrlBasedCorsConfigurationSource
구체 적 처리 류
CorsProcessor、DefaultCorsProcessor
CorsUtils
OncePerRequestFilter 인 터 페 이 스 를 실현 하 는 Adapter
CorsFilter
request 가 cors 인지 확인 하고 대응 하 는 Adapter 를 패키지 합 니 다.
AbstractHandler Mapping,내부 클래스 PreFlightHandler,CorsInterceptor 포함
CrossOrigin 주석 정보 읽 기
AbstractHandlerMethodMapping、RequestMappingHandlerMapping
xml 파일 에서 크로스 필드 설정 정 보 를 읽 습 니 다.
CorsBeanDefinitionParser
크로스 도 메 인 등록 보조 클래스
MvcNamespaceUtils
debug 분석
코드 를 알 아 보 려 면 도 메 인 정 보 를 봉인 하 는 pojo--CorsConfiguration 을 알 아야 합 니 다.
여 기 는 매우 간단 한 pojo 입 니 다.도 메 인 에 대응 하 는 몇 가지 속성 을 제외 하고 combine,checkOrigin,checkHttpMethod,checkHeaders 만 있 습 니 다.
속성 은 모두 다수 치 조합 에서 사용 합 니 다.
// CorsConfiguration
public static final String ALL = "*";
//
private List<String> allowedOrigins;
// http
private List<String> allowedMethods;
//
private List<String> allowedHeaders;
//
private List<String> exposedHeaders;
// cookies
private Boolean allowCredentials;
//
private Long maxAge;
combine 은 도 메 인 정 보 를 통합 하 는 것 입 니 다.3 개의 check 방법 은 각각 request 의 정보 가 허용 범위 내 에 포함 되 어 있 는 지 확인 하 는 것 이다.
설정 초기 화
시스템 이 시 작 될 때 CorsBeanDefinitionParser 를 통 해 설정 파일 을 분석 합 니 다.
RequestMappingHandlerMapping 을 불 러 올 때 InitialingBean 의 after Properties 갈 고 리 를 통 해 initCorsConfiguration 을 호출 하여 주석 정 보 를 초기 화 합 니 다.
프로필 초기 화
CorsBean Definition Parser 류 의 parse 방법 에서 정지점 을 찍 습 니 다.
CorsBean Definition Parser 호출 스 택
코드 를 통 해 이쪽 해석 을 볼 수 있 습 니 다.
크로스 필드 정보의 설정 은 path 단위 로 여러 맵 관 계 를 정의 할 수 있 습 니 다.
분석 할 때 정의 가 없 으 면 기본 설정 을 사용 합 니 다.
// CorsBeanDefinitionParser
if (mappings.isEmpty()) {
//
CorsConfiguration config = new CorsConfiguration();
config.setAllowedOrigins(DEFAULT_ALLOWED_ORIGINS);
config.setAllowedMethods(DEFAULT_ALLOWED_METHODS);
config.setAllowedHeaders(DEFAULT_ALLOWED_HEADERS);
config.setAllowCredentials(DEFAULT_ALLOW_CREDENTIALS);
config.setMaxAge(DEFAULT_MAX_AGE);
corsConfigurations.put("/**", config);
}else {
// mapping
for (Element mapping : mappings) {
CorsConfiguration config = new CorsConfiguration();
if (mapping.hasAttribute("allowed-origins")) {
String[] allowedOrigins = StringUtils.tokenizeToStringArray(mapping.getAttribute("allowed-origins"), ",");
config.setAllowedOrigins(Arrays.asList(allowedOrigins));
}
// ...
}
분석 완료 후 MvcNamespaceUtils.registerCorsConfigurations 를 통 해 등록이쪽 은 spring bean 용기 관리의 통 일 된 절 차 를 밟 고 있 으 며,지금 은 Bean Definition 으로 바 뀌 어 예화 되 었 습 니 다.
// MvcNamespaceUtils
public static RuntimeBeanReference registerCorsConfigurations(Map<String, CorsConfiguration> corsConfigurations, ParserContext parserContext, Object source) {
if (!parserContext.getRegistry().containsBeanDefinition(CORS_CONFIGURATION_BEAN_NAME)) {
RootBeanDefinition corsConfigurationsDef = new RootBeanDefinition(LinkedHashMap.class);
corsConfigurationsDef.setSource(source);
corsConfigurationsDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
if (corsConfigurations != null) {
corsConfigurationsDef.getConstructorArgumentValues().addIndexedArgumentValue(0, corsConfigurations);
}
parserContext.getReaderContext().getRegistry().registerBeanDefinition(CORS_CONFIGURATION_BEAN_NAME, corsConfigurationsDef);
parserContext.registerComponent(new BeanComponentDefinition(corsConfigurationsDef, CORS_CONFIGURATION_BEAN_NAME));
}
else if (corsConfigurations != null) {
BeanDefinition corsConfigurationsDef = parserContext.getRegistry().getBeanDefinition(CORS_CONFIGURATION_BEAN_NAME); corsConfigurationsDef.getConstructorArgumentValues().addIndexedArgumentValue(0, corsConfigurations);
}
return new RuntimeBeanReference(CORS_CONFIGURATION_BEAN_NAME);
}
주석 초기 화Request Mapping Handler Mapping 의 initCorsConfiguration 에서 CrossOrigin 주 해 를 사용 하 는 방법 을 스 캔 하고 정 보 를 추출 합 니 다.
RequestMappingHandlerMapping_initCorsConfiguration
// RequestMappingHandlerMapping
@Override
protected CorsConfiguration initCorsConfiguration(Object handler, Method method, RequestMappingInfo mappingInfo) {
HandlerMethod handlerMethod = createHandlerMethod(handler, method);
CrossOrigin typeAnnotation = AnnotatedElementUtils.findMergedAnnotation(handlerMethod.getBeanType(), CrossOrigin.class);
CrossOrigin methodAnnotation = AnnotatedElementUtils.findMergedAnnotation(method, CrossOrigin.class);
if (typeAnnotation == null && methodAnnotation == null) {
return null;
}
CorsConfiguration config = new CorsConfiguration();
updateCorsConfig(config, typeAnnotation);
updateCorsConfig(config, methodAnnotation);
// ...
return config;
}
크로스 필드 요청 처리Handler Mapping 은 검색 프로 세 서 를 정상적으로 처리 한 후 Abstract Handler Mapping.getHandler 에서 크로스 도 메 인 요청 인지 확인 하고 두 가지 로 나 누 어 처리 합 니 다.
UrlBasedCorsConfigurationSource 는 CorsConfigurationSource 의 실현 으로 클래스 이름 에서 이 request 와 CorsConfiguration 의 매 핑 은 url 에 기반 한 것 으로 추측 할 수 있 습 니 다.getCorsConfiguration 에서 request 의 url 을 추출 한 후 url 과 일치 하 는 지 확인 합 니 다.
// UrlBasedCorsConfigurationSource
public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
String lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
for(Map.Entry<String, CorsConfiguration> entry : this.corsConfigurations.entrySet()) {
if (this.pathMatcher.match(entry.getKey(), lookupPath)) {
return entry.getValue();
}
}
return null;
}
// AbstractHandlerMapping
public final HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
Object handler = getHandlerInternal(request);
// ...
HandlerExecutionChain executionChain = getHandlerExecutionChain(handler, request);
if (CorsUtils.isCorsRequest(request)) {
CorsConfiguration globalConfig = this.corsConfigSource.getCorsConfiguration(request);
CorsConfiguration handlerConfig = getCorsConfiguration(handler, request);
CorsConfiguration config = (globalConfig != null ? globalConfig.combine(handlerConfig) : handlerConfig);
executionChain = getCorsHandlerExecutionChain(request, executionChain, config);
}
return executionChain;
}
// HttpHeaders
public static final String ORIGIN = "Origin";
// CorsUtils
public static boolean isCorsRequest(HttpServletRequest request) {
return (request.getHeader(HttpHeaders.ORIGIN) != null);
}
요청 헤더 의 http 방법 을 통 해 options 가 사전 요청 여 부 를 판단 할 지 여부 입 니 다.PreFlightRequest 를 사용 하여 프로 세 서 를 교체 하 는 경우;일반적인 요청 이 라면 차단 기 를 추가 합 니 다.PreFlightRequest 는 CorsProcessor 가 HttpRequestHandler 에 대한 어댑터 입 니 다.이렇게 HandlerAdapter 는 HttpRequestHandlerAdapter 를 직접 사용 하여 처리 합 니 다.
CorsInterceptor 는 CorsProcessor 가 Hnalder Interceptor Adapter 에 대한 어댑터 입 니 다.
// AbstractHandlerMapping
protected HandlerExecutionChain getCorsHandlerExecutionChain(HttpServletRequest request,
HandlerExecutionChain chain, CorsConfiguration config) {
if (CorsUtils.isPreFlightRequest(request)) {
HandlerInterceptor[] interceptors = chain.getInterceptors();
chain = new HandlerExecutionChain(new PreFlightHandler(config), interceptors);
}
else {
chain.addInterceptor(new CorsInterceptor(config));
}
return chain;
}
private class PreFlightHandler implements HttpRequestHandler {
private final CorsConfiguration config;
public PreFlightHandler(CorsConfiguration config) {
this.config = config;
}
@Override
public void handleRequest(HttpServletRequest request, HttpServletResponse response)
throws IOException {
corsProcessor.processRequest(this.config, request, response);
}
}
private class CorsInterceptor extends HandlerInterceptorAdapter {
private final CorsConfiguration config;
public CorsInterceptor(CorsConfiguration config) {
this.config = config;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
return corsProcessor.processRequest(this.config, request, response);
}
}
// CorsUtils
public static boolean isPreFlightRequest(HttpServletRequest request) {
return (isCorsRequest(request) && request.getMethod().equals(HttpMethod.OPTIONS.name()) &&
request.getHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD) != null);
}
github 에 가서 볼 수 있 습 니 다https://github.com/haplone/spring_doc/blob/master/mvc/cors.md이상 은 본 고의 모든 내용 입 니 다.본 고의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 도움 이 되 기 를 바 랍 니 다.또한 저 희 를 많이 지지 해 주시 기 바 랍 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
실행 전 요청에 대한 응답이 액세스 제어 검사를 통과하지 못함: 'Access-Control-Allow-Origin'안녕하십니까 내 문제 메인 파일에 cors 패키지를 추가했습니다. index.js front=end 파일 게시 요청 내 백엔드 파일 실행 포트 = 3001 때문에 포트에서 실행되는 프런트 엔드 파일 = 3000 **...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.