Hoe om Cross-domein aanvragen op JAX-RS web services?

Ik ontwikkelde een set van restful web services. Ik kon het niet noemen van een van deze methoden van externe cliënten als gevolg van de fout
No 'Access-Control-Allow-Origin' header is present on the requested resource.

De diensten die perfect werken op localhost. Is er wijzigingen of configs te doen op de server side het probleem op te lossen. d.w.z. om cross-domein aanvragen.

Ik ben met behulp van WildFly 8, JavaEE 7

  • U kunt meer te weten komen over CORS hier: html5rocks.com/en/tutorials/cors kunt U meer informatie over het toevoegen CORS steun aan JAX-RS hier: cxf.apache.org/docs/jax-rs-cors.html
  • Dat is handig, maar ik was op zoek naar een oplossing zonder wijziging van de cliënten code.
  • Je vraag voor wijzigingen aan de server-kant. De meeste van de wijzigingen voor CORS worden gedaan aan de server-kant. Er zijn slechts minimale eventuele veranderingen die nodig zijn in de client.
InformationsquelleAutor Naili | 2014-05-03

 

8 Replies
  1. 103

    Ik was benieuwd hetzelfde, dus na een beetje onderzoek kwam ik erachter dat de eenvoudigste manier is simpelweg gebruik te maken van een JAX-RS ContainerResponseFilter toevoegen van de relevante CORS headers. Op deze manier hoeft u niet te vervangen, het hele web services stack met CXF (Wildfly gebruikt CXF is een vorm, maar het ziet er niet als het wordt gebruikt voor JAX-RS misschien alleen JAX-WS).

    Ongeacht als u dit filter voegt de koppen naar elk REST webservice.

    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");
       }
    
    }

    Toen ik getest met een krul van de interventie had de CORS headers:

    $ 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

    Mijn opvatting is dat het de @Provider aantekening dat vertelt de JAX-RS runtime om de filter te gebruiken, zonder aantekening gebeurt er niets.

    Ik heb het idee over het gebruik van de ContainerResponseFilter van een Jersey voorbeeld.

    • ja ik gebruikte dezelfde oplossing die u hier geplaatst. Maar ik geloof dat we opnieuw te maken van een security probleem doordat elke cross-domein-verbinding.
    • Ja dat klopt als je de REST web services maken gebruik van cookies voor het beveiligen ervan. Maar als je gewoon proberen om een aantal publieke REST web services, dan is er geen veiligheidsprobleem.Je hebt niet vermeld in uw vraag als je gewoon nodig 1 domein te werken, dat wil zeggen diensten.uwdomein bijvoorbeeld, of in elk domein.
    • Als u van plan bent om alleen een specifieke host in plaats van *, vergeet niet om toe te voegen de poort
    • Kunt u vertellen hoe u dit filter ? Moet ik dat doen in web.xml ?
    • het maakt gebruik van de @ Provider annotatie, dus zolang je CDI ingeschakeld voor uw oor/oorlog geen extra configuratie nodig
    • +1 voor @Provider annotatie. Ook ik was op zoek naar voorbeelden online, maar op een of andere manier gemist essentieel onderdeel!
    • Ik ben het uitvoeren van de diensten op een steiger server met jersey servlet container. In dit geval, alleen het hebben van de @Provider is niet voldoende. De CORSFilter klasse moest worden geregistreerd als een jersey servlet met init parameter zo: jerseyServlet.setInitParameter( "jersey.config.server.provider.classnames", MyService.class.getCanonicalName() + ", org.glassfish.jersey.media.multipart.MultiPartFeature, " + CORSFilter.class.getCanonicalName())
    • deze vraag werd over Wildfly 8 en JEE 7, en niet steiger/jersey, dus als u nog andere vragen moet u een andere vraag, als deze oplossing niet relevant voor u is.
    • Pearson Is Overeengekomen. Ik kwam deze vraag door middel van een google-zoekopdracht voor “enable CORS in jax-rs”. Net dacht dat het misschien nuttig voor anderen die op deze pagina terecht ook. Niettemin, de geaccepteerde antwoord niet lijkt te suggereren iets specifiek voor wildfly of jee7. Kan ik mis de link? Dit was de oplossing die werkte voor mij op de steiger+jersey en bedankt voor het posten.
    • waar is het waarschijnlijk niet JEE 7, lijkt de Aanbieder annotatie is beschikbaar in JEE 6: docs.oracle.com/javaee/6/api/index.html?javax/ws/rs/ext/… Het ding dat maakt het Wildfly is het feit dat je moet CDI voor het aan het werk zoals het is. Maar het is mogelijk dat het zou werken in een JEE 6 container, omdat het niet te verwijzen naar Wildfly Api ‘ s rechtstreeks. Het is interessant dat u kunt nog steeds dat het werken in JAX-RS buiten JEE al. Interessante informatie, bedankt.
    • Access-Control-Allow-Credentials: true deze lijn is eigenlijk tegenstrijdig met "Access-Control-Allow-Origin", "*" zoals het zou een beveiliging probleem, of (ten minste in Chrome) is gewoon ontkend. Als u wilt toestaan referenties, moet u opgeven van een bepaalde oorsprong, niet een wildcard.
    • Eerst krijgen de aanvraag oorsprong: String origin = requestContext.getHeaderString("origin");, vervolgens (toen origin !== null) gebruik ik oorsprong.s.o een wildcard: cres.getHeaders().add("Access-Control-Allow-Origin", origin);. Als je API gebruik van cookies om authenticatie (bijvoorbeeld bij het gebruik van de container managed authentication), controleren van de oorsprong tegen een witte lijst van toegestane oorsprong voor het instellen van de CORS headers.
    • Bedankt mannen, voor degenen die zich afvragen wanneer om deze code, moet u gewoon deze code op uw org.uwdomein.rest pakket, als je gebruik wildfly 10.
    • Hadden We het Probleem, dat de aanbieder niet geregistreerd standaard en de volgende vraag geholpen: stackoverflow.com/questions/32328012/…
    • er is alleen een security probleem als de toepassing beperkt de toegang op basis van IP-nummer (dit is een zeer slechte gewoonte), alleen in dit geval een kwaadaardige site toegang tot gegevens is het niet anders kon ophalen. in alle andere omstandigheden, als referenties zijn niet toegestaan (zoals opgemerkt door Stijn de Witt) er is geen beveiligingsprobleem.

  2. 17

    Ik werd geconfronteerd met een soortgelijk probleem, en had geprobeerd het gebruik van @Alex Petty ‘ s oplossing, maar afgezien van dat u de CORS kolomkoppen op elke JAX-RS-eindpunt in mijn klas, zoals:

    @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();
    }

    Ik had verder definiëren van een catch-all OPTIONS eindpunt dat zou de terugkeer van de CORS kop voor een andere OPTIONS verzoek in de klas, en dus ook de vangst van alle eindpunt van de soort:

    @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();
    }

    Alleen nadat u dit heeft gedaan, kon ik goed gebruiken voor mijn JAX-RS API eindpunten van Jquery Ajax-clients op andere domeinen of hosts.

    • Ik heb een vreemd probleem. De reactie van de header.header(“SOME_HEADER”,”SOME_HEADER”), vastgesteld door mij niet weergegeven in attitude UI in Google chrome, Mozilla, maar in IE 11. Ik heb gecontroleerd dat deze reactie kop is afkomstig van de browser (in de console response header van de developer tool), maar het is niet steeds weergegeven in Attitude UI.
    • Dat is niet juist. U moet gebruik maken van filters. Gebruik een Filter als u wilt filteren en/of wijzigen van aanvragen op basis van de specifieke omstandigheden. Gebruik een Servlet wanneer u wilt bedienen, preprocess en/of na te bewerken aanvragen. docs.oracle.com/javaee/6/tutorial/doc/bnagb.html
    • Ik voegde deze .header(“Access-Control-Allow-Origin”, “*”) en het werkte
  3. 11

    Ik heb veel geluk gehad met het configureren Cross-origin resource sharing (CORS) voor mijn API (op Wildfly) door het gebruik van deze lib:

    <dependency>
    <groupId>com.thetransactioncompany</groupId>
    <artifactId>cors-filter</artifactId>
    <version>2.1</version>
    </dependency>

    Het is zeer gemakkelijk te installeren. Voeg aan de bovenstaande afhankelijkheid aan uw pom en voeg de volgende config naar de webapp gedeelte van uw web.xml -bestand.

    <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>

    U kunt ook configureren met een properties-bestand in plaats indien u de voorkeur geeft. Dit lib werkt als een charme en geeft u een groot deel van de instellingen flexibiliteit!

    • Dank je wel mach
    • Ik wilde dit proberen, maar ik heb deze fout op mijn log-console : The 'Access-Control-Allow-Origin' header contains multiple values 'http://127.0.0.1, *', but only one is allowed. Een idee wat te veranderen aan de web.xml om het goed te maken ?
    • Ik heb dit geprobeerd, maar niet kunnen zien, dit toegevoegd aan de koptekst.
  4. 11

    Vond ik een nog eenvoudiger (RestEasy-specifieke) manier in staat te stellen CORS op Wildfly zonder het gebruik van een filter en waar u kunt uw Api ‘ s response header-configuratie op de resource-niveau.

    Bijvoorbeeld:

    @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();
    }
    • Dank u. Ik was niet in staat om ‘javax.ws.rs.container’ klassen (waarom? een andere JAX-RS-versie?), en je oplossing werkte prima.
    • Deze manier werkt alleen voor KRIJGEN, wanneer het proberen met POST (van de klant) dezelfde fout, ik ben nog steeds bezig om uit te zoeken hoe dit probleem op te lossen, omdat mijn “oorsprong” zal variëren met de tijd.
    • Dit zal nooit werken, zijn verkeerd. CORS eerste gesprek de HTTP-methode “OPTIES” voordat u belt “GET”, “POST” of wat dan ook. De kop inzendingen zullen worden vastgesteld in een “OPTIES” – methode. Als ze niet zijn, de browser gewoon accepteren. HTTP filteren op verzoek is de beste manier om dat te doen. Een ander ding, als u een ernstige HTTP-server, zoals Apache, de vermelding “Access-Control-Allow-Origin”, “*” is schaars, en de browser zal niet toestaan. Je moet specifiek voeg de machtiging van DNS, bijvoorbeeld “Access-Control-Allow-Origin: my.domain.com“.
    • Maar als je 100s van methoden… een betere aanpak zou zijn om een filter te gebruiken
  5. 7

    Geen van de andere antwoorden werkte voor mij, maar dit deed:

    import javax.ws.rs.core.Response;

    Wijzig de return type van de methode service te Response, en verander de return instructie:

    return Response.ok(resp).header("Access-Control-Allow-Origin", "*").build();

    Waar resp is het originele response-object.

    • Dit werkt alleen als het een eenvoudige vraag. Dat is als het verzoek KRIJGEN of via de POST request headers zijn eenvoudige(De enige eenvoudige kopteksten te Accepteren, Accepteren-Taal, Content-Taal, Content-Type= application/x-www-form-urlencoded, multipart/form-data, text/plain). Anders browser stuurt een verzoek van de OPTIES voorafgaand aan de feitelijke aanvraag.
  6. 3

    U kunt ook implementeren javax.ws.rs.core.Feature zoals hieronder te voeren 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;
     }
    
    }
  7. 0

    Net iets toe te voegen naar andere reacties.
    Zodat * is een beetje gevaarlijk.
    Wat kan worden gedaan is het configureren van een database van de toegestane oorsprong (het kan een bestand)

    Dan wanneer de aanvraag komt, kun je doen:

    //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");
    }

    Op die manier zal je niet toestaan iedereen.

  8. 0

    @Joel Pearson antwoord geholpen, maar voor iemand die nieuw is aan JAX-RS als ik en is het uitvoeren van de service op tomcat configureren web.xml moet voorzichtig zijn tijdens het maken van de klasse en zet het ergens in het project. Zie het pakket dat u hebt opgegeven in het kader voor jersey en maakt dit filter klasse. Op die manier werkte voor mij.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *