filter导致跨域失效_【SpringMVC】与权限拦截器冲突导致的Cors跨域设置失效问题...

问题描述

前端域名FE.com向后端域名BE.com分别请求访问优惠券的列表和提交新增的优惠券,API设计所用的Method分别为Get和Post,结果为前一次访问成功而后一次访问失败。这两次请求都是跨域请求,其中请求1包含一个Get请求,请求2本应该包含一个Options请求和一个Post请求,但是只发生了Options请求。

后端Cors配置

CORS使用SpringMVC自带的标签全局配置,权限检测则实现自定义的拦截器校验Cookie中的Token信息。

allowed-methods="POST, GET, OPTIONS, DELETE, PUT, HEAD"

allowed-origins="http://test.i.meituan.com"

max-age="3600" path="/**"/>

在复杂请求的情况下(即请求2),由于预检请求不会包含Cookie信息(浏览器本身的实现决定其是否发送Cookie,前端无法控制,并且Chrome是不发送的),因此被权限拦截器提前结束,没有输出包含指定头部信息的响应。而一个被浏览器认为合格的预检请求响应必须包含如下的Http头部。

Access-Control-Allow-Origin: http://test.i.meituan.com

Access-Control-Allow-Methods: POST, GET, OPTIONS

Access-Control-Allow-Headers: Content-Type

Access-Control-Max-Age: 86400

为什么会发生提前结束这种情况?可以对dispatch()方法进行分析。

Handler和拦截器的执行顺序

DispatchServlet.doDispatch()方法是SpringMVC的核心入口方法,分析发现所有的拦截器的preHandle()方法的执行都在实际Handler的方法(比如某个API对应的业务方法)之前,其中任意拦截器返回false都会跳过后续所有处理过程。而SpringMVC对预检请求的处理则在PreFlightHandler.handleRequest()中处理,在整个处理链条中出于后置位。由于预检请求中不带Cookie,因此先被权限拦截器拦截。

// Determine handler for the current request.

mappedHandler = getHandler(processedRequest);

//省略代码

if (!mappedHandler.applyPreHandle(processedRequest, response)) {

return;

}

// Actually invoke the handler.

mv = ha.handle(processedRequest, response, mappedHandler.getHandler());

@CrossCors时序分析

除了在XML中设置全局的CORS配置,Spring提供了@CrossCors,可以注解在类和方法上,是一种更细粒度的配置方法。SpringMVC把其处理细节包装在getHandler(processedRequest);中,具体逻辑可以简述为如果请求是预检请求,则返回PreFlightHander;否则在拦截器末尾添加一个CorsInterceptor。因此可以看出,@CrossCors相关的执行和全局的类似,也是滞后于权限拦截器的。

解决方案

方案1:使用Spring-Web自带的CorsFilter

由于CorsFilter是定义在Web容器中的过滤器(实现了javax.servlet.Filter),因此其执行顺序先于Servlet,而SpringMVC的入口是DispatchServlet,因此该Filter会先于SpringMVC的所有拦截器执行。分析代码可知,CorsFilter会获取单个请求对应的Cors配置做相应的处理。因此可以和很好的结合,不需要增加额外的代码。(勘误:CorsFilter的构造需要CorsConfigurationSource实例,并且发生在SpringMVC配置文件解析之前,因此只能放在Spring的配置文件中,否则会发生找不到bean的异常;又由于的解析和Spring核心的解析不共享相同的ParserContext上下文,因此SpringMVC的跨域设置不能植入到CorsFilter中)

if (CorsUtils.isCorsRequest(request)) {

CorsConfiguration corsConfiguration = this.configSource.getCorsConfiguration(request);

if (corsConfiguration != null) {

boolean isValid = this.processor.processRequest(corsConfiguration, request, response);

if (!isValid || CorsUtils.isPreFlightRequest(request)) {

return;

}

}

}

filterChain.doFilter(request, response);

方案2:自己实现Interceptor

与方案1类似,把插入Http头的功能实现为SpringMVC的拦截器,然后在中声明为第一顺位。

public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

if (request.getHeader(HttpHeaders.ORIGIN) != null) {

response.addHeader("Access-Control-Allow-Origin", "http://test.i.meituan.com");

response.addHeader("Access-Control-Allow-Credentials", "true");

response.addHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT, HEAD");

response.addHeader("Access-Control-Allow-Headers", "Content-Type");

response.addHeader("Access-Control-Max-Age", "3600");

}

return true;

}

方案3:增强自定义Interceptor

利用AOP环绕增强所有自定义拦截器的preHandle()方法,令其跳过预检请求的拦截。

@Around(value = "cut()")

public Object processTx(ProceedingJoinPoint jp) throws Throwable {

HttpServletRequest request = (HttpServletRequest) jp.getArgs()[0];

if (request != null && CorsUtils.isPreFlightRequest(request)) {

return true;

} else {

return jp.proceed();

}

}

Reference

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/486151.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

美国专利商标局发布人工智能专利扩散分析报告

以下文章来源:中科院知识产权信息,2020-11-23报告显示,从2002到2018年,美国人工智能专利的年申请量增长超过100%,从每年3万件增加到6万多件,含人工智能的专利申请所占份额从9%上升到近16%。同时&#xff0c…

java 开发环境的搭建

这里主要说的是在windows 环境下怎么配置环境。 1.首先安装JDK java的sdk简称JDK ,去其官方网站下载最近的JDK即可。。http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html点击下载好的exe文件安装即可。 2.接下来我们需要配置环…

linux内核等价多路径路由,Linux内核分析 - 网络[四]:路由表

路由表的创建inet_init() -> ip_init() -> ip_fib_init() -> fib_net_init() -> ip_fib_net_init()[net\ipv4\fib_frontend.c]首先为路由表分配空间,这里的每个表项hlist_head实际都会链接一个单独的路由表,FIB_TABLE_HASHSZ表示了分配多少个…

2017级面向对象程序设计 作业二

以下均以扫描方式为例,即电梯只会在最底层和最高层选择掉头,路途中遇到路径方向相同的乘客将他带上电梯。 文字描述面向过程实现的步骤: 一. 定义有关电梯的变量,如:1.电梯当前所在楼层.,2. 电梯内的人数&a…

server sql top速度变慢解决方案_SQL Server数据库查询速度慢的原因和解决方法

SQL Server数据库查询速度慢的原因有很多,常见的有以下几种:1、没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷)2、I/O吞吐量小,形成了瓶颈效应。3、没有创建计算列导致查询不优化。4、内存不足5、网络速度慢…

新型支架状电极允许人类思想操作计算机

Illustration: Synchron来源:IEEE电气电子工程师据悉,两名患有神经肌肉疾病的澳大利亚人在他们的大脑中植入了支架状的电极,使他们能够利用自己的思想操作电脑,从而恢复了一些个人独立性。据发明者介绍,这是这种被称为…

java中的foreach

foreach 并不是java中的关键字,是for语句的特殊简化版,在比那里数组,集合时,foreach更加简单快捷,从字面上的意思理解 foreach 也就是 “ for每一个 ”的意思,那么到底怎么使用 foreach语句呢? …

linux c 子线程sleep,linux c之sleep的多种实现

#include #include #include //使用select实现精确到1微秒(0.000001秒)的sleepvoid sleep_us(unsigned int nusecs){struct timevaltval;tval.tv_sec nusecs / 1000000;tval.tv_usec nusecs % 1000000;select(0, NULL, NULL, NULL, &tval);}int main(){printf("star…

ACM数论-素数

ACM数论——素数 素数定义: 质数(prime number)又称素数,有无限个。质数定义为在大于1的自然数中,除了1和它本身以外不再有其他因数,这样的数称为质数。例 子:2、3、5、7、11、13、17、19。&am…

cors 前后端分离跨域问题_SpringBoot 实现前后端分离的跨域访问(CORS)

序言:跨域资源共享向来都是热门的需求,使用CORS可以帮助我们快速实现跨域访问,只需在服务端进行授权即可,无需在前端添加额外设置,比传统的JSONP跨域更安全和便捷。一、基本介绍简单来说,CORS是一种访问机制…

机器视觉中彩色成像必须考虑的十个问题

来源:Imagination Tech在为你的产品开发最适合的机器视觉系统时,需要考虑很多因素,以下列出开发过程中需要考虑的一些问题:颜色准确性/差异化首先要考虑的是应用程序所需的颜色精度和差异程度。在某些应用中,机器视觉相…

彩色的砖块

小易有一些彩色的砖块。每种颜色由一个大写字母表示。各个颜色砖块看起来都完全一样。现在有一个给定的字符串s,s中每个字符代表小易的某个砖块的颜色。小易想把他所有的砖块排成一行。如果最多存在一对不同颜色的相邻砖块,那么这行砖块就很漂亮的。请你帮助小易计算有多少种方…

linux 6.5桌面环境kde,CentOS 5/6 安装 GNOME 或 KDE 桌面

1、安装 XWindowyum-ygroupinstallXWindowSystem2.1、Centos 5.x 安装 GNOME 或 KDE (可择一安装)GNOMEyum-ygroupinstallGNOMEDesktopEnvironmentKDEyum-ygroupinstallKDE(KDesktopEnvironment)2.2、Centos 6.x 安装 GNOME 或 KDE (可择一安装)GNOMEyum-ygroupinstallDesktopK…

Zabbix的简单使用

0. 卸载mariadb 安装mysql 方法 rpm -qa |grep mariadb 然后 rpm -e --nodeps mariadb***** 安装mysql # 下载mysql源安装包 shell> wget http://dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpm # 安装mysql源 shell> yum localinstall mysql57-communi…

嫦娥“挖土”归来有多难?看看中国首颗返回式卫星的故事

本文转载自“科技日报(kjrbwx)”,原标题《嫦娥“挖土”归来有多难?看看中国首颗返回式卫星的故事》,作者 | 吕炳宏 付毅飞2020年11月30日,嫦娥五号探测器在环月轨道上,成功实施着陆器上升器组合…

springboot 添加拦截器之后中文乱码_spring boot 2.x 添加拦截器配置未生效的问题

背景: 今天有一个需求需要拦截除登录相关请求以外的所有请求,并查看request 中是否包含指定的信息,而自然就想到了使用拦截器就可以轻松实现编写拦截器,获取请求头信息中的test,并打印出来Componentpublic class Autho…

等差数列

[编程题] 等差数列时间限制:1秒空间限制:32768K如果一个数列S满足对于所有的合法的i,都有S[i 1] S[i] d, 这里的d也可以是负数和零,我们就称数列S为等差数列。小易现在有一个长度为n的数列x,小易想把x变为一个等差数列。小易允许在数列上做交换任意两…

179.【2023年华为OD机试真题(C卷)】最大坐标值(模拟实现JavaPythonC++JS)

请到本专栏顶置查阅最新的华为OD机试宝典 点击跳转到本专栏-算法之翼:华为OD机试 🚀你的旅程将在这里启航!本专栏所有题目均包含优质解题思路,高质量解题代码,详细代码讲解,助你深入学习,深度掌握! 文章目录 179.【2023年华为OD机试真题(C卷)】最大坐标值(模拟…

2018 UESTC Training for Data Structures

Link A - 一棵简单的线段树 标准线段树 #include<bits/stdc.h> #define ll long long using namespace std;const int maxn 1e67;int n,q; struct node {int l,r,maxx,minx;ll num;ll sum; }t[maxn*4];void build(int x,int l,int r) {t[x].ll,t[x].rr;if(lr){t[x].numt…

linux下的驱动大小,(转)Linux驱动开发需要注意的点/KO大小/内存管理

1.不要想不通就写代码&#xff0c;不要为了存粹的解决问题而加代码&#xff0c;不要忽视任何一种场景可能&#xff0c;因为躲得了一时&#xff0c;躲不了一波&#xff0c;BUG迟早会被挖出来的&#xff0c;到时候更加苦逼。2.内存是个很严肃的问题&#xff0c;不要直接调用系统函…