目前项目结构是VUE做前端,后端采用微服务架构,在开发时前端需要跨域请求数据,通过ZuulFilter配置解决了简单跨域请求需要。但当需要在请求的header中增加token信息时,出现了请求失败的情况,浏览器和后台均出现OPTIONS类型请求相关提示。

Failed to load http://192.168.1.149:8000/server/addressbook/delete: Response to preflight request doesn't pass access control check: The 'Access-Control-Allow-Origin' header contains multiple values 'http://192.168.1.242:5500, http://192.168.1.242:5500', but only one is allowed. Origin 'http://192.168.1.242:5500' is therefore not allowed access.

这里其实已经很明确了,说头包含多个值,只允许一个然后我们看请求信息

为什么会这样呢?其实是我们在使用ZuulFilter的时候获取的 RequestContext 他给我们自带了 Access-Control-Allow-Origin,Access-Control-Allow-Credentials 这两个参数,所以我们在程序里面就不需要加了

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.zuul.mgzuul.util.JwtHelperUtil;
import com.zuul.mgzuul.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; /**
* @Author 唐银
* @Description //TODO
* @Date 2018-01-03 14:20
* @ClassName MyFilter
* @ClassNotes
**/
@Slf4j
@Component
public class MyFilter extends ZuulFilter { @Resource
private RedisUtil redisUtil; @Autowired
private JwtHelperUtil jwtHelperUtil; @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();
// //过滤各种POST请求
// if(request.getMethod().equals(RequestMethod.OPTIONS.name())){
// return true;
// }
return true; } @Override
public Object run() { System.out.println("*****************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,Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,Authorization,Token,accessToken");
response.setHeader("Vary","Origin,Access-Control-Request-Method,Access-Control-Request-Headers");
String accessToken = request.getHeader("accessToken");
//跨域请求放行
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
ctx.setSendZuulResponse(true);
ctx.setResponseStatusCode(200);
System.out.println("*****************PostFilter run end*****************");
return null;
} String url = request.getRequestURI();
if(url.indexOf("/login")!=-1){
ctx.setSendZuulResponse(true);
ctx.setResponseStatusCode(200);
System.out.println("*****************PostFilter run end*****************");
return null;
} //验证token
//String accessToken = request.getHeader("accessToken");
/*String accessToken = request.getParameter("accessToken");
if(StringUtils.isBlank(accessToken)){
log.debug("accessToken 不存在!");
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401);// 返回错误码
ctx.setResponseBody("{\"result\":\"token不存在\"}");// 返回错误内容
ctx.set("isSuccess", false);
return null;
}
Object token_ob = redisUtil.get(accessToken);
if(token_ob == null){
log.debug("accessToken 已经过期");
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401);// 返回错误码
ctx.setResponseBody("{\"result\":\"token过期\"}");// 返回错误内容
ctx.set("isSuccess", false);
return null;
}else {
Claims claims = jwtHelperUtil.parseJWT(accessToken);
if(claims == null){
log.debug("accessToken 错误");
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401);// 返回错误码
ctx.setResponseBody("{\"result\":\"token错误\"}");// 返回错误内容
ctx.set("isSuccess", false);
return null;
}
}
//通过后更新登陆过期时间
redisUtil.set(accessToken,accessToken, 259200);*/
//允许继续路由
ctx.setSendZuulResponse(true);
ctx.setResponseStatusCode(200);
System.out.println("*****************PostFilter run end*****************");
return null;
}
}

注释掉以后ok 就成功解决了 (注意在zuul做了跨域设置就不需要在各个服务再做了不然也是会出现这个问题的)

QQ群:216868740

SpringCloud微服务Zuul跨域问题的更多相关文章

  1. SpringCloud微服务之跨服务调用后端接口

    SpringCloud微服务系列博客: SpringCloud微服务之快速搭建EurekaServer:https://blog.csdn.net/egg1996911/article/details ...

  2. 【微服务】之六:轻松搞定SpringCloud微服务-API网关zuul

    通过前面几篇文章的介绍,我们可以轻松搭建起来微服务体系中比较重要的几个基础构建服务.那么,在本篇博文中,我们重点讲解一下,如何将所有微服务的API同意对外暴露,这个就设计API网关的概念. 本系列教程 ...

  3. springcloud微服务实战:Eureka+Zuul+Feign/Ribbon+Hystrix Turbine+SpringConfig+sleuth+zipkin

    相信现在已经有很多小伙伴已经或者准备使用springcloud微服务了,接下来为大家搭建一个微服务框架,后期可以自己进行扩展.会提供一个小案例: 服务提供者和服务消费者 ,消费者会调用提供者的服务,新 ...

  4. springcloud微服务实战:Eureka+Zuul+Ribbon+Hystrix+SpringConfig

    原文地址:http://blog.csdn.net/yp090416/article/details/78017552 springcloud微服务实战:Eureka+Zuul+Ribbon+Hyst ...

  5. SpringCloud微服务(基于Eureka+Feign+Hystrix+Zuul)

    一.搭建注册中心 1.1.创建一个cloud-service项目 1.2:POM文件依赖 1 <?xml version="1.0" encoding="UTF-8 ...

  6. 【微服务】之七:轻松搞定SpringCloud微服务-API权限控制

    权限控制,是一个系统当中必须的重要功能.张三只能访问输入张三的特定功能,李四不能访问属于赵六的特定菜单.这就要求对整个体系做一个完善的权限控制体系.该体系应该具备针区分用户.权限.角色等各种必须的功能 ...

  7. springcloud微服务架构搭建

    SpringCloud微服务框架搭建 一.微服务架构 1.1什么是分布式 不同模块部署在不同服务器上 作用:分布式解决网站高并发带来问题 1.2什么是集群 多台服务器部署相同应用构成一个集群 作用:通 ...

  8. SpringCloud微服务基础学习

    看了蚂蚁课堂的微服务学习,确实学习了不少关于微服务的知识,现在总结学习如下 : SpringCloud微服务基础单点系统架构传统项目架构传统项目分为三层架构,将业务逻辑层.数据库访问层.控制层放入在一 ...

  9. java~springcloud微服务目录索引

    回到占占推荐博客索引 最近写了不过关于java,spring,微服务的相关文章,今天把它整理一下,方便大家学习与参考. java~springcloud微服务~目录索引 springcloud~服务注 ...

随机推荐

  1. Windows -- cmd命令: ipconfig 和 nbtstat

    1. ipconfig 命令格式及参数如下: 2. nbtstat 命令格式及参数如下:

  2. Windows API编程(SDK编程)配置VS2017——出现LNK 2019错误的win32项目如何解决

    最近刚入门SDK编程,在 我终于知道为什么windowsApi学的人这么少了 这篇文章中,确实发现了这样的问题,我的教程使用VS2013->Windows桌面->win32,就诞生了能使用 ...

  3. python进程和线程(四)

    线程同步条件.信号量及队列 同步条件(event) 下面是官方文档对event的一些解释: An event is a simple synchronization object; the event ...

  4. linux 下搭建php环境

    linux 下搭建php环境 1.下载apache (http://httpd.apache.org/download.cgi) 下载php组件 ( http://cn2.php.net/get/ph ...

  5. qml demo分析(text-字体展示)

    上一篇文章分析了一个小游戏,使用qml编写界面+js进行复杂逻辑控制,算是一个比较完整的qml示例代码了,今天就不那么继续变态啦,来看一个简单的字体示例程序吧,该示例代码比较简单,主要是展示了几个简单 ...

  6. Spring Boot 2.x 系列教程:WebFlux REST API 全局异常处理 Error Handling

    摘要: 原创出处 https://www.bysocket.com 「公众号:泥瓦匠BYSocket 」欢迎关注和转载,保留摘要,谢谢! 本文内容 为什么要全局异常处理? WebFlux REST 全 ...

  7. 微信小程序开发01-小程序的执行流程是怎么样的?

    前言 我们这边最近一直在做基础服务,这一切都是为了完善技术体系,这里对于前端来说便是我们需要做一个Hybrid体系,如果做App,React Native也是不错的选择,但是一定要有完善的分层: ① ...

  8. Asp.Net Core 轻松学-利用 Swagger 自动生成接口文档

    前言     目前市场上主流的开发模式,几乎清一色的前后端分离方式,作为服务端开发人员,我们有义务提供给各个客户端良好的开发文档,以方便对接,减少沟通时间,提高开发效率:对于开发人员来说,编写接口文档 ...

  9. Css-移动端适配总结

    前言 工作以后,大部分的业务工作都是基于移动端H5的,开发过程中学习了很多东西,遇到过许多问题,诸如rem\em\css px\device px等,本文纯属个人的归纳总结,如有问题,请指出亲喷~ P ...

  10. .NET CAD二次开发学习第一天

    基于浩辰CAD2019 需求: 开发线转圆简单命令.命令过程:1) 请选择图中直线(要求支持一次选多个):2) 弹出对话框,输入圆的图层名和半径3) 点对话框中确定按钮,结束命令.命令执行效果:所选每 ...