Maison  >  Article  >  Java  >  Zuul implémente Cors sur plusieurs domaines de deux manières : corsFilter et héritant de ZuulFilter

Zuul implémente Cors sur plusieurs domaines de deux manières : corsFilter et héritant de ZuulFilter

php是最好的语言
php是最好的语言original
2018-08-03 14:40:3911206parcourir

Tout le monde sait que Spring Boot peut réaliser des opérations inter-domaines via @CrossOrigin. Mais dans Spring Cloud, si vous souhaitez contrôler plusieurs domaines avec une granularité aussi fine, c'est trop lourd, donc d'une manière générale, cela sera implémenté dans le routage zuul.

La première façon : corsFilter

Ajoutez un corsFilter sous le service zuul pour obtenir un cross-domain, ce qui est facile à mettre en œuvre. Le code est le suivant

@Configuration
public class GateWayCorsConfig {
   @Bean
    public FilterRegistrationBean corsFilter() {
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        final CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        //这个请求头在https中会出现,但是有点问题,下面我会说
        //config.addExposedHeader("X-forwared-port, X-forwarded-host"); 
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return bean;
    }
}

Après tests, cette configuration est OK sur tous les domaines dans le cas de http, mais lorsque mon environnement passe en https, d'étranges problèmes surviennent. Expliquez le problème que j'ai rencontré. Le
Front-endService A et le Back-end Service B sont sur le même serveur lorsque le Service A appelle le Service B. , Lorsque le service A entre dans le service B via l'équilibrage de charge : lorsque
http est utilisé, la demande du service A réussit dans tous les domaines lorsque https l'est ; utilisé, service ALa requête a échoué sur tous les domaines.
C'est-à-dire que lorsque le port est 443, cela sera considéré comme un échec inter-domaines ! !
J'ai d'abord comparé les en-têtes de requête et j'ai pensé qu'il manquait le "X-forwared-port, X-forwarded-host" de ExposedHeader, mais après l'avoir ajouté, cela a toujours échoué. Parce que j'étais pressé d'aller en ligne, je n'ai pas effectué de test approfondi sur les causes de l'échec de la requête https entre domaines. (Donc, si vous trouvez quelque chose qui ne va pas dans ce que j'ai écrit, assurez-vous de m'en informer et de me faire comprendre pourquoi cela a échoué ! Merci !)

Deuxième façon : hériter de ZuulFilter

Parce que de la première façon Après avoir échoué sous https, j'ai essayé d'utiliser zuulfilter pour implémenter cors

Un total de deux filtres sont nécessaires : un pré, un post

Pré-filtre :

@Component
public class FirstFilter extends ZuulFilter {

    private Logger logger = LoggerFactory.getLogger(FirstFilter.class);

    @Override
    public String filterType() {
        /*
        pre:可以在请求被路由之前调用
        route:在路由请求时候被调用
        post:在route和error过滤器之后被调用
        error:处理请求时发生错误时被调用
        * */
        // 前置过滤器
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        //// 优先级为0,数字越大,优先级越低
        return 0;
    }
    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        //只过滤OPTIONS 请求
        if(request.getMethod().equals(RequestMethod.OPTIONS.name())){
            return true;
        }

        return false;
    }

    @Override
    public Object run() {
        logger.debug("*****************FirstFilter run start*****************");
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletResponse response = ctx.getResponse();
        HttpServletRequest request = ctx.getRequest();
        response.setHeader("Access-Control-Allow-Origin",request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Credentials","true");
        response.setHeader("Access-Control-Allow-Headers","authorization, content-type");
        response.setHeader("Access-Control-Allow-Methods","POST,GET");
        response.setHeader("Access-Control-Expose-Headers","X-forwared-port, X-forwarded-host");
        response.setHeader("Vary","Origin,Access-Control-Request-Method,Access-Control-Request-Headers");
        //不再路由
        ctx.setSendZuulResponse(false);
        ctx.setResponseStatusCode(200);
        logger.debug("*****************FirstFilter run end*****************");
        return null;
    }
}

Le pré-filtre est utilisé pour traiter les requêtes OPTIONS de pré-traitement Lorsqu'il s'avère qu'il s'agit d'une requête OPTIONS, un en-tête de réponse inter-domaines est donné, et il n'est pas acheminé par zuul et renvoie directement. success (200), permettant un service inter-domaines vers le service front-end


post-Filter :

@Component
public class PostFilter extends ZuulFilter {

    private Logger logger = LoggerFactory.getLogger(PostFilter.class);

    @Override
    public String filterType() {
        /*
        pre:可以在请求被路由之前调用
        route:在路由请求时候被调用
        post:在route和error过滤器之后被调用
        error:处理请求时发生错误时被调用
        * */
        // 前置过滤器
        return FilterConstants.POST_TYPE;
    }

    @Override
    public int filterOrder() {
        //// 优先级为0,数字越大,优先级越低
        return 2;
    }
    @Override
    public boolean shouldFilter() {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        //过滤各种POST请求
        if(request.getMethod().equals(RequestMethod.OPTIONS.name())){
            return false;
        }
        return true;
    }

    @Override
    public Object run() {
        logger.debug("*****************PostFilter run start*****************");
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletResponse response = ctx.getResponse();
        HttpServletRequest request = ctx.getRequest();
        response.setHeader("Access-Control-Allow-Origin",request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Credentials","true");
        response.setHeader("Access-Control-Expose-Headers","X-forwared-port, X-forwarded-host");
        response.setHeader("Vary","Origin,Access-Control-Request-Method,Access-Control-Request-Headers");
        //允许继续路由
        ctx.setSendZuulResponse(true);
        ctx.setResponseStatusCode(200);
        logger.debug("*****************PostFilter run end*****************");
        return null;
    }
}

Post-Filter est utilisé pour traiter les requêtes autres que le prétraitement. OPTIONS. Pour les requêtes normales, non seulement les en-têtes de requête inter-domaines doivent être fournis, mais vous devez également autoriser le routage de la requête (sinon votre requête se terminera ici), puis renvoyer le code d'état 200. (emmmm... Je pense que je devrai peut-être réfléchir à l'opportunité de renvoyer 200 ici...)

S'ils sont configurés de la manière ci-dessus, les problèmes qui surviennent dans la méthode seront résolus. Le service A peut demander le service B normalement

Bien que les exigences aient été remplies normalement, j'ai toujours l'impression qu'il y a beaucoup de doutes. J'espère que si vous le voyez, vous pourrez me signaler les lacunes. Discutons-en ensemble !

Articles connexes :

Solution inter-domaines 1 : utilisez CORS pour implémenter cross-domain_html/css_WEB-ITnose

Utilisez CORS pour implémenter la méthode de requête inter-domaines WebApi Ajax

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn