ajax请求跨域,兼容重定向

问题:

由于项目登陆系统新增登陆模式,需要新增接口对接登陆系统,同时为了兼容以前老登陆接口的各个功能特性,须兼容之前登陆模式。

而之前老登陆系统,为转跳访问接口,接口直接重定向。

 

问题出现原因:

由于需要整合新登录接口,同时支持老登陆的功能特性,因此将老登陆的功能特性实现代码提前为公共代码。

由于老登陆逻辑直接使用的是登陆系统 中的登陆页面,所以使用的是ajax验证验证码,验证成功进行页面转跳重定向。【全部操作均在登录系统中完成,不涉及ssion跨域】

而新登录使用同样方法,将出现ssion跨域。所以没有使用该方法,且使用ajax访问接口,如果是response.sendRedirect(url); 将不会进行重定向

 

解决办法:

新登录使用接口方式,返回json数据, app项目user_api 暴露一个接口提供前端访问(如/xxx)【json数据返回注解@ResponseBody】,   /xxx接口中实现对登陆接口的访问,获取token或登陆系统返回的验证码错误信息, 判断登陆系统返回的信息,

如果是错误信息则对app返回json错误信息,

如果是正确的,开始通过token换取用户信息,进行老登陆系统的业务功能逻辑。在进行老登陆用逻辑之前,设置HttpServletResponse 的响应头  允许跨域,设置响应头白名单(具体原因后面会说)【红色为必不可少的设置】

//设置响应头

response.setHeader("Access-Control-Allow-Origin","*");

response.setHeader("Access-Control-Allow-Headers","x-requested-with,content-type,REDIRECT,CONTENTPATH");

response.setHeader("Access-Control-Expose-Headers","REDIRECT,CONTENTPATH");

在原来的  重定向代码前 添加ajax请求判断【ajax 请求会在请求头中夹带X-Requested-With  消息头

 

//判断ajax请求

if("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))){

//前端需要判断是否是重定向

response.setHeader("REDIRECT","REDIRECT");

//需要重定向的路径

response.setHeader("CONTENTPATH",url);

response.setStatus(HttpServletResponse.SC_FORBIDDEN);

}else{

response.sendRedirect(url);

}

对于ajax不能进行重定向, 后面介绍原因。    

设置好服务端之后,现在修改前端

【由于跨域请求 jsonp不会有ajax的请求头,所以我们需要自己添加该标记,否者服务端无法判断是否是ajax请求】

补充:JSONP调用本质上不是AJAX调用。因此,在JSONP调用中,您将看不到任何X-Requested-With头字段。

$.ajax({

type:

dataType:"JSONP",

headers:{'X-Requested-With':'XMLHttpRequest'},

url:',

data:{

phone:params.phone,//手机号

password:params.password,//验证码

},

success:function(data){

codeError(data);

},

error:function(XMLHttpRequest,textStatus,errorThrown){

if(XMLHttpRequest.status==403){

if("REDIRECT"==XMLHttpRequest.getResponseHeader("REDIRECT")){//若HEADER中含有REDIRECT说明后端想重定向,

varwin=window;

while(win!=win.top){

win=win.top;

}

win.location.href=XMLHttpRequest.getResponseHeader("CONTENTPATH");//将后端重定向的地址取出来,使用win.location.href去实现重定向的要求

}

}

},

});

 

CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。

它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制

 

三个与CORS请求相关的字段,都以Access-Control-开头

Access-Control-Allow-Origin

该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。

 

Access-Control-Allow-Credentials

该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。

 

Access-Control-Expose-Headers

该字段可选。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。

【】

非简单跨域请求

会发送一个预请求,检测是否与服务器相通。

"预检"请求用的请求方法是OPTIONS,表示这个请求是用来询问的。头信息里面,关键字段是Origin,表示请求来自哪个源。

 

服务器收到"预检"请求以后,检查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段以后,确认允许跨源请求,就可以做出回应。

服务器回应的其他CORS相关字段如下

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

Access-Control-Allow-Headers: X-Custom-Header

Access-Control-Allow-Credentials: true

Access-Control-Max-Age: 1728000

Access-Control-Allow-Methods

该字段必需,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次"预检"请求。

Access-Control-Allow-Headers

如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在"预检"中请求的字段。

Access-Control-Allow-Credentials

该字段与简单请求时的含义相同。

Access-Control-Max-Age

该字段可选,用来指定本次预检请求的有效期,单位为秒。上面结果中,有效期是20天(1728000秒),即允许缓存该条回应1728000秒(即20天),在此期间,不用发出另一条预检请求。

 

参考文档

跨域资源共享 CORS 详解

来自 <http://www.ruanyifeng.com/blog/2016/04/cors.html>

 

跨域AJAX不发送X-Requested-With头

来自 <https://codeday.me/bug/20180112/116116.html>

 

如有错误还望指正

 

 


 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值