目前项目结构是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. redis cluster + sentinel详细过程和错误处理三主三备三哨兵

    redis cluster + sentinel详细过程和错误处理三主三备三哨兵1.基本架构192.168.70.215 7001 Master + sentinel 27001192.168.70. ...

  2. 关于a[i]++和a[i++]说明

    1.a[i]++:表示对当前数组元素值自增,此时可以把a[i]简单看做一个变量x,操作后,x的值加1: int main() { ]; ; a[i] = ; a[i]++; printf(" ...

  3. JetBrains 系列编译器 破解(idea,webstrom ,pycharm等)

    第一步: 下载安装好Idea 或者Pychar ,安装好后不可运行 第二步: 安装完成之后不要立即运行,以下提供JetbrainsCrack的jar包来破解: jar包资源自行百度 下载之后,把Jet ...

  4. Windows迁移打印机与打印队列

    移动打印机时,打印机当前所在服务器为源服务器,打印机将迁移到的服务器为目的服务器. 步骤: 1.为源服务器创建打印机配置文件 printbrm -b -s Servername -f SaveFile ...

  5. 基于HTTP协议的几种实时数据获取技术

    原文链接https://www.cnblogs.com/xrq730/p/9280404.html,作者博客园----五月的仓颉,转载请注明出处,谢谢 HTTP协议 HTTP协议大家都很熟悉了,开始本 ...

  6. 《ECMAScript6入门》___阮一峰 笔记

    let和const命令 let命令 循环体的let变量只对花括号作用域可见,花括号外不可见 循环体的语句部分是一个父作用域,而循环体内部是一个单独的子作用域 let声明的变量不存在变量提升,未声明的使 ...

  7. Java核心技术第五章——1.类、超类、子类(2)

    继上一篇Java核心技术第五章——1.类.超类.子类(1) 6.重载解析 假如调用ClassName.Method(args) 1.编译器列出类ClassName所有名为Method的方法. 2.编译 ...

  8. 怎么用Mac电脑创建多个桌面

    区别于win的单个桌面,Mac电脑可以设置多个桌面,方面用户处理各种多乱杂的情况.究竟怎么用Mac电脑创建多个桌面呢?一起来看看吧! 1.首先打开Mission Control,点击偏好设置 2.然后 ...

  9. [Err] 1055 - Expression #1 of ORDER BY clause is not in GROUP BY clause 的问题 MySQL

    问题:[Err] 1055 - Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nonaggregate ...

  10. Win32对话框程序(1)

    之前学C语言是一直都是在控制台下面操作的,面对的都是黑框框,严重的打击了学习的兴趣.后来在TC下进行C语言课程设计,做了图形界面编程,但都是点线面画的…… 中间隔了好长一段时间没有碰过C语言,最近才开 ...