安らかなWebサービスのセットを開発しました。エラーNo 'Access-Control-Allow-Origin' header is present on the requested resource.
が原因で、これらのメソッドをリモートクライアントから呼び出すことができませんでした
サービスはローカルホストで完全に機能します。問題を解決するためにサーバー側で行う変更や設定はありますか?つまり、クロスドメインリクエストを有効にします。
WildFly 8、JavaEE 7を使用しています
私は同じことを疑問に思っていたので、少し調査した後、最も簡単な方法は、JAX-RS ContainerResponseFilter
を使用して関連するCORSヘッダーを追加することであることがわかりました。この方法では、Webサービススタック全体をCXFに置き換える必要はありません(WildflyはCXFを使用していますが、JAX-RSに使用するようには見えないかもしれません)。
このフィルターを使用するかどうかに関係なく、すべてのREST Webサービスにヘッダーが追加されます。
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の solution を使用しようとしましたが、クラスの各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
リクエストに対してCORSヘッダーを返すcatch-all OPTIONS
エンドポイントをさらに定義する必要があったため、並べ替えのすべてのエンドポイントをキャッチしました。
@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エンドポイントを適切に使用できます。
フィルターを使用せずに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();
}
このライブラリを使用して、(Wildflyで)APIのCross-Originリソース共有(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>
必要に応じて、代わりにプロパティファイルを使用して構成することもできます。このライブラリは魅力のように機能し、設定の柔軟性が大幅に向上します!
他の答えはどれもうまくいきませんでしたが、これはうまくいきました:
import javax.ws.rs.core.Response;
次に、サービスメソッドの戻り値の型をResponse
に変更し、return
ステートメントを次のように変更します。
return Response.ok(resp).header("Access-Control-Allow-Origin", "*").build();
ここで、resp
は元の応答オブジェクトです。
以下のようにjavax.ws.rs.core.Feature
を実装して、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;
}
}
他の応答に何かを追加するだけです。 *を許可することは少し危険です。できることは、許可されたオリジンのデータベースを構成することです(ファイルにすることもできます)
その後、リクエストが到着すると次のことができます。
// 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");
}
その方法では、すべての人を許可しません。
@Joel Pearsonの回答は役に立ちましたが、私のようなJAX-RSを初めて使用し、web.xmlを構成してTomcatでサービスを実行している人は、クラスを作成してプロジェクトのどこにでも配置する際に注意する必要があります。 jerseyで指定したパッケージを参照して、このフィルタークラスを作成します。そのようにそれは私のために働いた。