Programing

JAX-RS 웹 서비스에서 교차 도메인 요청을 사용하는 방법은 무엇입니까?

crosscheck 2020. 11. 20. 08:38
반응형

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.

참고URL : https://stackoverflow.com/questions/23450494/how-to-enable-cross-domain-requests-on-jax-rs-web-services

반응형