服务端支持跨域

大背景:前后端分离后,项目分开部署,域名不一致,ajax请求时需要解决跨域问题。

服务端支持跨域方案:

1、spring早已经支持跨域的配置。

2、@CrossOrgin注解方式,支持配置到controller或者具体的方法上。不多解释注解的参数。

说明:我理解的是,1和2方案都是通过spring提供的CorsFilter做了拦截。


3、spring 拦截器方式 

public classCrossDomainInterceptorextendsHandlerInterceptorAdapter {

@Override

   public booleanpreHandle(HttpServletRequest request,HttpServletResponse response,Object handler)throwsException {

if(RequestMethod.OPTIONS.name().equalsIgnoreCase(request.getMethod())) {

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

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

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

           response.addHeader("Access-Control-Allow-Headers","Content-Type,x-requested-with,access-token");

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

            //response.setStatus(HttpStatus.SC_OK);

            return false;

       }

return true;

   }

}

4、自定义Filter,然后在XML配置 filter。

public classCrossDomainFilterimplementsFilter{

@Override

   public voidinit(FilterConfig filterConfig)throwsServletException {

    }

@Override

   public voiddoFilter(ServletRequest servletRequest,ServletResponse servletResponse,FilterChain filterChain)throwsIOException,ServletException {

if(servletRequestinstanceofHttpServletRequest && servletResponseinstanceofHttpServletResponse) {

HttpServletRequest request = (HttpServletRequest) servletRequest;

           HttpServletResponse response = (HttpServletResponse) servletResponse;

            if(CorsUtils.isCorsRequest(request)) {

log.info(request.getRequestURL().toString() +" options request into CrossDomainFilter");

                if(!processRequest(request,response) || CorsUtils.isPreFlightRequest(request)) {

return;

               }

            }

filterChain.doFilter(request,response);

       }else{

filterChain.doFilter(servletRequest,servletResponse);

       }

    }

private booleanprocessRequest(HttpServletRequest request,HttpServletResponse response) {

booleanisValid =false;

       String curOrigin = request.getHeader("Origin");

       String[] domains ="http://localhost:8080,http://localhost:8090".split(",");

        if(domains.length>0) {

for(String domain : domains) {

if(curOrigin.equals(domain)) {

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

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

                   response.addHeader("Access-Control-Allow-Headers","Content-Type, x-requested-with, access-token");

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

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

                   isValid =true;

                    break;

               }

            }

        }

returnisValid;

   }

@Override

   public voiddestroy() {

    }

}

以上四种方案好像所以的看上去都是那么简单,没什么难度。我一开始也是这样认为的。然而。。。。

过程中遇到如下几个问题。

1)我们希望domain可支持的域名是可以动态配置,通过公司的配置系统可以动态获取allowOrigins。那么方案1被我抛弃了,因为xml里配置无法动态生效。因为是基于全局配置,就没有考虑方案2.

2)我用了spring拦截器方式CrossDomainInterceptor,或者CrossDomainFilter extends OncePerRequestFilter。就是这个过程都被spring管理着。但是出现了状况:

A、请求依然403. 原因:经过各种尝试发现,Access-Control-Allow-Credentials、Access-Control-Allow-Headers有设置时,Access-Control-Allow-Origin 不要设置成 *。并且Access-Control-Allow-Headers 需要和前端传上来的header 参数名匹配上,否则很容易403.

B、解决了测试环境的403之后,有同学又反应本地开发环境出现“Invalid Cors Request”。找了4个同学本地postman请求服务端接口,2个同学反应没有问题,2个同学反应出现“Invalid Cors Request”。这里很难理解,postman里的请求就是简单的接口测试,不存在跨域问题,无法理解。解决方案:在网上有看到帖子说是因为多个filter顺序问题,其他filter导致了跨域filter出现了问题。。。(确实项目还集成了其他需要用到过滤器的地方,如:安全框架接入)

基于以上出现的状况,我决定从头开始,回归本质。首先跨域就是需要对浏览器PreflightRequest(Options预检查请求)。进行过滤。那么就定义一个java filter吧。filter不再继承OncePerRequestFilter(毕竟让spring控制后自己就不会关注那么多了,这未必是好事)。然后把filter配置到web.xml(可以决定filter的顺序,也为了解决以上最后提到的filter顺序问题)。代码参考方案4。结果嘛,自然是一切就那么好起来了。

Access-Control-Allow-Headers 需要支持前端传上来的参数。

Access-Control-Allow-Credentials、Access-Control-Allow-Headers有设置时,Access-Control-Allow-Origin 不要设置成 *,只能支持一个。

注意过滤器的顺序问题。(即,你需要先做哪一步过滤)


引用一些参考的文章:

https://blog.csdn.net/dalangzhonghangxing/article/details/52911230

https://blog.csdn.net/pinebud55/article/details/60874725

https://segmentfault.com/a/1190000012469713

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,598评论 18 139
  • 一、HTTP简介 HTTP协议(HyperText Transfer Protocol,超文本传输协议)是用于从w...
    明燕南飞阅读 301评论 1 0
  • 关于 springmvc 3.x 版本对ajax跨域请求访问 ajax 请求后,浏览器出现跨域的问题那么在当前环境...
    山水风情阅读 505评论 0 0
  • 导入某些特殊Jar包中的类 在通常的开发中可能会去看下API的源代码,自己有时候也可以模仿API中的源代码做一些研...
    shoage阅读 186评论 2 0
  • 一、自行下载阿里云证书 此处不再概述 二、登陆阿里云之后,在安全(云盾)板块下-CA证书服务 这里选取apac...
    1367bfee4461阅读 415评论 0 1