关于跨域请求的另一种解决思路

目录

 

●问题产生

●问题解决

●问题反思


●问题产生

最近笔者遇到一个项目,描述如下:对方给我们提供了一个Url,可以通过get请求返回一串字符串作为token,我们拿到这个token后,将作为其中一个参数,和其他参数一起组装成数据,在我们自己页面上点击按钮,通过ajax的post请求提交给我们自己的后台进行业务逻辑处理。

笔者首先通过浏览器直接访问这个Url,验证了确实可以拿到字符串token,因此,决定采用如下思路进行开发:第1步,页面点击按钮,触发点击事件,通过ajax的get请求拿到字符串token,其中返回的dataType设置为text类型;第2步,在其success对应的回调函数中,通过ajax的post请求将这个token作为参数一起组织成数据,提交给我们的后台。

$("#xxBtn").on("click",function(){
    //第一步,Get请求
    $.ajax({
        type:"GET",
        url : getRequestUrl,
        dataType :'text',
        success:function(response){
            //第二步,Post请求
            $.ajax({
                type:"POST",
                url : postRequestUrl,
                dataType :'json',
                data{
                    user:postuser,
                    name:postname,
                    token:response
                },
                success:function(response){
                    console.log(response.msg);
                }
            });
        }
    });
});

然而,诡异的事情出现了,通过浏览器F12查看确实发起了Get请求,并且状态码200,也有响应数据,但页面上死活不进入success的回调函数。后来经过查询知道,原来是跨域请求惹的祸。

解释一下什么是跨域请求。通常,我们开发的前端页面,发起的请求,无论是Get、Post、Put还是什么,其请求的Url大都是自己的系统,即同一个工程中。而上述例子中,请求的Url确是对方提供的系统,不属于我们自己的。基于安全因素的设计,前端Ajax做这种跨域请求时,网上提供两大类解决思路,分别对应于我们开发的前端以及对方的后端。其中最常见的是网上一搜“跨域请求”时几乎都有的方法(同质化太严重,都是互相copy的……),将返回类型dataType写为"jsonp",但是上述项目中却不适应,原因在于其返回的压根就不是Json对象,只是单纯的一个字符串,该方法淘汰。另一类是说让对方的系统设置运行跨域请求,添加我们请求源的Ip为信任地址,但该方法依然不适用,对方并不提供支持。这么看来似乎无解了,网上也查不到更多有效信息。

●问题解决

后来,和小伙伴讨论了一番,想到了另外一种解决思路,将第一步的Get请求,交给我们自己的后端去完成,拿到响应token后,直接和其他参数在后台一同处理。

首先验证了Java后端去做Get请求时是否会出现跨域问题,发现确实并不会出现前端那样的跨域请求问题,请求的代码如下:

public String sendGet(String url) {
    String result = "";
    BufferedReader in = null;
    try {
        URL realUrl = new URL(url);
        URLConnection connection = realUrl.openConnection();
        // 设置通用的请求属性
        connection.setRequestProperty("accept", "*/*");
        connection.setRequestProperty("connection", "Keep-Alive");
        connection.setRequestProperty("user-agent",
                "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
        // 建立实际连接
        connection.connect();
        // 定义 BufferedReader输入流来读取URL的响应
        in = new BufferedReader(new InputStreamReader(
                connection.getInputStream()));
        String line;
        while ((line = in.readLine()) != null) {
            result += line;
        }
    } catch (Exception e) {
        System.out.println("发送GET请求出现异常!" + e);
        e.printStackTrace();
    }
    // 使用finally块关闭输入流
    finally {
        try {
            if (in != null) {
                in.close();
            }
        } catch (Exception e2) {
            e2.printStackTrace();
        }
    }
    return result;
}

相应地,前端的代码就修改成如下:

$("#xxBtn").on("click",function(){
    //直接向后端发Post请求,数据不带token,token由后端去Get请求获取
    $.ajax({
        type:"POST",
        url : postRequestUrl,
        dataType :'json',
        data{
            user:postuser,
            name:postname,
            token:response
            },
        success:function(response){
            console.log(response.msg);
        }
    });
});

最后,就是配置Struts或SpringMVC相关xml,接收前端请求,进行处理,返回前端的过程了,该部分涉及工作具体内容,就不举例了,大家可以结合自己的实际业务去编写代码。

●问题反思

确实,通过这种方式,能够解决跨域请求的问题。一方面提醒了我们遇到问题,可能会有不同的解决途径,需要勤加思索;另一方面也给我们敲了警钟,如果是前后端分离开发的项目,无法获得后端支持,前端真的就无解了吗?后来笔者继续学习,发现还是有不少解决思路的,例如通过代理等方式。今天,你学会了吗?

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值