ajax、跨域、session、filter

        在web开发中,标题列举的这几项内容都是很常见的,遇到问题也不难解决。但最近我在项目中却遇到一个这几项组合出的问题,卡了好几个小时,值得记一下。

        首先项目是前后端分离的结构。前端我用nodejs来调试,后端用spring boot跑的各种接口。因为两者端口不同,所以首先得解决跨域调用问题。通常有简便的方法我就不会去用麻烦的方法,所以直接在接口上加注解@CrossOrigin,轻松搞定。

        接着发现虽然大部分功能接口调用正常,但是获取profile信息的接口不行。profile信息是从session中获取的。那么自然想到跨域的session没有解决。随便一搜答案很多,在jquery调用时加上一个属性xhrFields: {withCredentials: true} 即可。此时前端有个报错The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*',原因是因为加了这个属性后@CrossOrigin就不能再用默认值(默认值是*,表示任意地址都可以跨域访问)。这个好办,加上域名限制@CrossOrigin(value="http://localhost:8000")。这里还有个注意点,开始我没写http://,光写域名是不行的。然而还是报错The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true'。原来Access-Control-Allow-Credentials也不能是默认值'',必须为true。也不说一次说清楚,大喘气啊,接着加@CrossOrigin(value="http://localhost:8000",allowCredentials="true")。好了,登录、获取profile信息都正常,十多分钟全解决了,乐呵呵继续。

        然而naive了,在获取一个需要权限验证的接口时,怎么都获取不到。因为权限验证是通过一个filter来获取session中的用户信息判断的。那么按理来说和之前的get profile是一样的。前端写法也是一模一样的,为什么一个能获取到一个不行呢。于是各种自我怀疑、花样尝试。好几个小时过去了,就在打算放弃、曲线救国的时候,猛然发现发送这个请求的方法是options,可是我分明用的是post方法。查阅了一下相关资料,options是一个“探测”请求。当发送的是简单请求时,ajax就直接发出去了。(简单请求指的是以下HTTP方法之一:HEAD、GET、POST且Content-Type的值为text/plain、multipart/form-data或application/x-www-form-urlencoded);如果不是简单请求,ajax会先发一个options方法的预检请求以确认对方是否可以接收。我这个接口恰恰是提交json格式的查询条件,所以先发了一个options请求。而且貌似发送options请求时默认就不会带上cookie,于是第一轮请求就被过滤器拦截返回401了,真正的请求就没发出去。猜到是这个原因之后,改写了一下filter:
String method = req.getMethod();
if(method.equals("OPTIONS")){
    chain.doFilter(request, response);
}else{... ...}
如果是options方法直接放过,真正的判断逻辑放在else里。终于顺利通过了。

        虽然是一个不太常见的组合情景,但也说明自己对http协议的了解还是不够深入,真是学无止境啊。

继续又发现一个问题,当被过滤器拦截返回401代码时,ajax 的error.status却是404,导致转向的错误提示页不正常。后来发现是这样的,因为在过滤器处理时忘了加消息头,所以尽管返回状态码是401,但浏览器仍然认为是无法访问(404)。把filter里加上信息头就可以了。

关键是这个:res.setHeader("Access-Control-Allow-Origin", req.getHeader("Origin"));

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值