web-dev-qa-db-fra.com

L'origine n'est pas autorisée par Access-Control-Allow-Origin - comment activer CORS à l'aide d'une pile Web très simple et de guice

Je ne sais pas si le problème concerne les technologies impliquées ou ma compréhension des technologies.

J'ai une application html5 écrite en javascript et html hébergée sur un serveur Apache 2.2.

J'ai une application Java écrite en Java utilisant jetty, guice, jackson, jersey qui héberge un simple service REST.

Les deux applications s'exécutent sur la même boîte, l'une sur le port 80 (application html5 pure hébergée sur Apache), l'autre sur 8080 (pure Java hébergée sur jetty/guice)

Je crois que la réponse est dans les en-têtes im renvoyant. Les en-têtes CORS indiquent à un navigateur que vous autorisez des applications externes à atteindre votre API. Je n'arrive pas à comprendre comment configurer mon serveur Jetty, Guice pour renvoyer les en-têtes CORS corrects.

J'utilise un serveur Jetty imbriqué donc je n'ai pas de fichier web.xml avec lequel ajouter les en-têtes.

Cela peut également être lié à la façon dont le serveur d'applications HTML5 (dans ce cas, Apache 2.2) sert l'application.

Le fichier Apache httpd.conf contient l'entrée:

LoadModule headers_module modules/mod_headers.so

<IFModule mod_headers>
    Header add Access-Control-Allow-Origin "*"
    Header add Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE, HEAD
    Header add Access-Control-Allow-Headers: X-PINGOTHER
    Header add Access-Control-Max-Age: 1728000  
</IfModule>

dans ma configuration de servlet guice j'ai les éléments suivants:

public class RestModule extends ServletModule{

    @Override
    protected void configureServlets() {
        bind(QuestbookService.class);

        // hook Jersey into Guice Servlet
        bind(GuiceContainer.class);

        // hook Jackson into Jersey as the POJO <-> JSON mapper
        bind(JacksonJsonProvider.class).in(Scopes.SINGLETON);

        Map<String, String> guiceContainerConfig = new HashMap<String, String>();
        guiceContainerConfig.put(ResourceConfig.PROPERTY_RESOURCE_FILTER_FACTORIES,
            HttpStatusCodeMetricResourceFilterFactory.class.getCanonicalName());
        serve("/*").with(GuiceContainer.class, guiceContainerConfig);
    }
}

Je pense que le problème est dans ma configuration de guice car je n'ai pas de place pour définir les en-têtes de réponse.

J'utilise un serveur de jetée intégré et j'ai donc pensé que le mode dev contournerait tout le contrôle, mais je peux me tromper.

Merci pour tout conseil.

11
AnthonyJClink

Faites aux exigences spécifiques de ma demande. Le serveur doit être complètement séparé du client. Le client doit pouvoir se connecter au serveur de communication par n'importe quelle méthode.

Puisque la première implémentation de cette application va être pilotée par REST, je dois pouvoir accepter le repos de n'importe où.

De plus, je veux une configuration complètement sans XML, donc j'utilise Guice avec un serveur Jetty intégré. Étant donné que je n'ai pas de fichier web.xml, je n'ai pas pu déterminer comment définir les en-têtes pour autoriser CORS.

Après beaucoup d'essais et d'erreurs et après avoir lu la documentation de Guice, j'ai trouvé comment ajouter les en-têtes CORS à la réponse quittant le serveur.

La classe Guice ServletModule vous permet d'ajouter des filtres à votre contexte de servlet. Cela me permet de faire passer toutes les demandes via un servlet donné.

Puisque j'essaye de construire une application de repos qui répond aux demandes CORS, j'avais besoin d'un filtre qui a ajouté les en-têtes cors à la réponse de toute demande.

Donc, pour activer les cors dans mon serveur intégré à l'aide de guice, j'ai construit un filtre qui ressemble à ceci:

@Singleton
public class CorsFilter implements Filter{

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
    FilterChain filterChain) throws IOException, ServletException {

        if(response instanceof HttpServletResponse){
        HttpServletResponse alteredResponse = ((HttpServletResponse)response);
        addCorsHeader(alteredResponse);
    }

    filterChain.doFilter(request, response);
    }

    private void addCorsHeader(HttpServletResponse response){
        //TODO: externalize the Allow-Origin
        response.addHeader("Access-Control-Allow-Origin", "*");
        response.addHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, HEAD");
        response.addHeader("Access-Control-Allow-Headers", "X-PINGOTHER, Origin, X-Requested-With, Content-Type, Accept");
        response.addHeader("Access-Control-Max-Age", "1728000");
    }

    @Override
    public void destroy() {}

    @Override
    public void init(FilterConfig filterConfig)throws ServletException{}
}

Guice fournit une classe abstraite qui vous permet de configurer le servlet Guice.

Le module de configuration ressemble à ceci:

public class RestModule extends ServletModule{

    @Override
    protected void configureServlets() {
        bind(MyServiceClass.class);

        // hook Jersey into Guice Servlet
        bind(GuiceContainer.class);

        // hook Jackson into Jersey as the POJO <-> JSON mapper
        bind(JacksonJsonProvider.class).in(Scopes.SINGLETON);

        Map<String, String> guiceContainerConfig = new HashMap<String, String>();

        serve("/*").with(GuiceContainer.class, guiceContainerConfig);

        filter("/*").through(CorsFilter.class);
    }
}

Désormais, guice ajoutera des en-têtes cors à chaque réponse. Permettre à mon application HTML 5 pure de lui parler, peu importe où elle est servie.

14
AnthonyJClink

Mettez simplement une ligne dans votre fichier de code

response.addHeader ("Access-Control-Allow-Origin", "*");

Remplacez * par votre http://www.votresite.com si vous souhaitez autoriser uniquement un domaine particulier

6
kunal saxena

L'ajout de ceci à votre httpServletResponse à Java c'est-à-dire côté serveur résoudra le problème.

 httpServletResponse.addHeader("Access-Control-Allow-Origin", "*");
 httpServletResponse.addHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, HEAD");
 httpServletResponse.addHeader("Access-Control-Allow-Headers", "X-PINGOTHER, Origin, X-Requested-With, Content-Type, Accept");
 httpServletResponse.addHeader("Access-Control-Max-Age", "1728000");
0
bosari