JAX-RS 웹 서비스에서 교차 도메인 요청을 사용하는 방법은 무엇입니까?
나는 편안한 웹 서비스 세트를 개발했습니다. 오류로 인해 원격 클라이언트에서 이러한 메서드를 호출 할 수 없습니다.No 'Access-Control-Allow-Origin' header is present on the requested resource.
이 서비스는 localhost에서 완벽하게 작동합니다. 문제를 해결하기 위해 서버 측 에서 수행 할 변경 또는 구성이 있습니까? 즉, 교차 도메인 요청을 활성화합니다.
WildFly 8, JavaEE 7을 사용하고 있습니다.
나는 똑같은 것을 궁금해하고 있었기 때문에 약간의 조사 끝에 가장 쉬운 방법은 JAX-RS ContainerResponseFilter
를 사용 하여 관련 CORS 헤더를 추가하는 것임을 발견했습니다 . 이렇게하면 전체 웹 서비스 스택을 CXF로 교체 할 필요가 없습니다 (Wildfly는 CXF를 사용하는 형식이 있지만 JAX-RS 용으로 사용하는 것 같지는 않지만 JAX-WS 만 사용할 수 있음).
이 필터를 사용하더라도 모든 REST 웹 서비스에 헤더를 추가합니다.
package com.yourdomain.package;
import java.io.IOException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.ext.Provider;
@Provider
public class CORSFilter implements ContainerResponseFilter {
@Override
public void filter(final ContainerRequestContext requestContext,
final ContainerResponseContext cres) throws IOException {
cres.getHeaders().add("Access-Control-Allow-Origin", "*");
cres.getHeaders().add("Access-Control-Allow-Headers", "origin, content-type, accept, authorization");
cres.getHeaders().add("Access-Control-Allow-Credentials", "true");
cres.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD");
cres.getHeaders().add("Access-Control-Max-Age", "1209600");
}
}
그런 다음 curl로 테스트했을 때 응답에 CORS 헤더가 있습니다.
$ curl -D - "http://localhost:8080/rest/test"
HTTP/1.1 200 OK
X-Powered-By: Undertow 1
Access-Control-Allow-Headers: origin, content-type, accept, authorization
Server: Wildfly 8
Date: Tue, 13 May 2014 12:30:00 GMT
Connection: keep-alive
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Transfer-Encoding: chunked
Content-Type: application/json
Access-Control-Max-Age: 1209600
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS, HEAD
내 이해는 @Provider
주석이 아무 일도 일어나지 않고 JAX-RS 런타임이 필터를 사용하도록 지시 하는 주석이라는 것입니다.
Jersey 예제ContainerResponseFilter
에서 를 사용하는 것에 대한 아이디어를 얻었습니다 .
비슷한 문제에 직면했고 @Alex Petty의 솔루션 을 사용하려고 시도했지만 내 클래스의 각 JAX-RS 끝점에 CORS 헤더를 설정해야하는 것 외에는 다음과 같습니다.
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getMemberList() {
List<Member> memberList = memberDao.listMembers();
members.addAll(memberList);
return Response
.status(200)
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Headers", "origin, content-type, accept, authorization")
.header("Access-Control-Allow-Credentials", "true")
.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD")
.header("Access-Control-Max-Age", "1209600")
.entity(memberList)
.build();
}
클래스의 OPTIONS
다른 OPTIONS
요청에 대해 CORS 헤더를 반환 하는 포괄적 인 끝점 을 추가로 정의하여 모든 끝점을 잡아야했습니다.
@OPTIONS
@Path("{path : .*}")
public Response options() {
return Response.ok("")
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Headers", "origin, content-type, accept, authorization")
.header("Access-Control-Allow-Credentials", "true")
.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD")
.header("Access-Control-Max-Age", "1209600")
.build();
}
이렇게 한 후에야 다른 도메인이나 호스트의 Jquery Ajax 클라이언트에서 내 JAX-RS API 끝점을 제대로 사용할 수있었습니다.
이 lib를 사용하여 내 API (Wildfly에서)에 대해 CORS (교차 출처 리소스 공유)를 구성하는 데 행운이있었습니다.
<dependency>
<groupId>com.thetransactioncompany</groupId>
<artifactId>cors-filter</artifactId>
<version>2.1</version>
</dependency>
설정이 매우 쉽습니다. 위의 종속성을 pom에 추가 한 다음 web.xml 파일의 webapp 섹션에 다음 구성을 추가하십시오.
<filter>
<filter-name>CORS</filter-name>
<filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
<init-param>
<param-name>cors.allowGenericHttpRequests</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>cors.allowOrigin</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>cors.allowSubdomains</param-name>
<param-value>false</param-value>
</init-param>
<init-param>
<param-name>cors.supportedMethods</param-name>
<param-value>GET, HEAD, POST, DELETE, OPTIONS</param-value>
</init-param>
<init-param>
<param-name>cors.supportedHeaders</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>cors.supportsCredentials</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>cors.maxAge</param-name>
<param-value>3600</param-value>
</init-param>
</filter>
<filter-mapping>
<!-- CORS Filter mapping -->
<filter-name>CORS</filter-name>
<url-pattern>*</url-pattern>
</filter-mapping>
원하는 경우 속성 파일을 사용하여 구성 할 수도 있습니다. 이 라이브러리는 매력처럼 작동하며 많은 구성 유연성을 제공합니다!
필터를 사용하지 않고 Wildfly에서 CORS를 활성화하고 리소스 수준에서 API 응답 헤더 구성을 제어 할 수있는 훨씬 더 쉬운 (RestEasy 관련) 방법을 찾았습니다.
예를 들면 :
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getMemberList() {
List<Member> memberList = memberDao.listMembers();
members.addAll(memberList);
return Response
.status(200)
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Headers", "origin, content-type, accept, authorization")
.header("Access-Control-Allow-Credentials", "true")
.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD")
.header("Access-Control-Max-Age", "1209600")
.entity(memberList)
.build();
}
다른 답변 중 어느 것도 나를 위해 일하지 않았지만 이것은 효과가 있습니다.
import javax.ws.rs.core.Response;
그런 다음 서비스 메서드의 반환 유형을로 Response
변경하고 return
문을 다음 과 같이 변경합니다 .
return Response.ok(resp).header("Access-Control-Allow-Origin", "*").build();
resp
원래 응답 객체는 어디에 있습니까 ?
You can also implement javax.ws.rs.core.Feature
as below to implement CORS.
import javax.ws.rs.core.Feature;
import javax.ws.rs.core.FeatureContext;
import javax.ws.rs.ext.Provider;
import org.jboss.resteasy.plugins.interceptors.CorsFilter;
@Provider
public class CorsFeature implements Feature {
@Override
public boolean configure(FeatureContext context) {
CorsFilter corsFilter = new CorsFilter();
corsFilter.getAllowedOrigins().add("*");
context.register(corsFilter);
return true;
}
}
Just to add something to other responses. Allowing * is a little bit dangerous. What can be done is configuring a database of the allowed origin (it can be a file)
Then when the request arrive you can do:
// this will return you the origin
String referers[] = requestContext.getHeaders().get("referer")
// then search in your DB if the origin is allowed
if(referers != null && referers.lenght == 1 && isAllowedOriging(referers[0])){
containerResponseContext.getHeaders().add("Access-Control-Allow-Origin", referers[0]);
containerResponseContext.getHeaders().add("Access-Control-Allow-Headers", "origin, content-type, accept, authorization, <HERE PUT YOUR DEDICATED HEADERS>);
containerResponseContext.getHeaders().add("Access-Control-Allow-Credentials", "true");
containerResponseContext.getHeaders().add("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD");
containerResponseContext.getHeaders().add("Access-Control-Max-Age", "1209600");
}
In that way you won't allow everyone.
@Joel Pearson answer helped but for someone who is new to JAX-RS like me and is running the service on tomcat by configuring web.xml should be careful while creating the class and putting it anywhere in the project. See the package you specified in under for jersey and create this filter class there. That way it worked for me.
'Programing' 카테고리의 다른 글
문자열이 문자열로 시작하는지 테스트 하시겠습니까? (0) | 2020.11.20 |
---|---|
STL 컨테이너를 필터링하는 현대적인 방법? (0) | 2020.11.20 |
Jupyter 내 Tensorflow 세트 CUDA_VISIBLE_DEVICES (0) | 2020.11.20 |
Query if Android database exists! (0) | 2020.11.19 |
하단을 제외하고 선형 레이아웃 주위에 테두리를 추가하는 방법은 무엇입니까? (0) | 2020.11.19 |