js与jquery 跨域问题

1.jQuery ajax方式以jsonp类型发起跨域请求,使用jsonp时也只能使用GET方式发起跨域请求。跨域请求需要服务端配合,设置callback,才能完成跨域请求。 

前端:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <title>CSRF跨站请求</title>
 
    <!-- 引入 JQuery -->
    <script src="https://code.jquery.com/jquery-3.3.1.js"
            integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="
            crossorigin="anonymous"></script>
 
    <script type="text/javascript">
        $(function () {
            $("#btn_jsonp").click(function () {
                $.ajax({
                    url: "http://localhost:8080/seals/getInfo", //请求地址
                    type: "GET",    //jsonp只支持get请求,不写时默认为get方式,可省略
                    dataType: "jsonp", //指定返回的数据类型为 jsonp
                    //jsonp:传递给服务器的参数,服务器需要根据此值封装数据返回,不写时JQuery默认为 callback,可省略
                    //这个参数值会自动追加到 Url 地址中 ?callback=xxxx
                    jsonp: "callback",
                    success: function (data) {
                        //返回的jsonp数据必须是 json 格式
                        console.log("success:" + JSON.stringify(data));
                    },
                    error: function (data) {
                        console.log("error:" + JSON.stringify(data));
                    }
                })
            });
        });
    </script>
</head>
<body>
<button id="btn_jsonp" type="button" style="font-size: 20px">jsonp跨域请求</button>
</body>
</html>

后端:


/**
 * Created by Administrator on 2019/3/13 0013.
 */
@Controller
public class InfoControler {
    /**
     * get请求:http://localhost:8080/seals/getInfo
     *
     * @param request
     * @return
     * @ResponseBody :表示内容直接返回给页面
     */
    @GetMapping("getInfo")
    @ResponseBody
    public String getInfo(HttpServletRequest request) {
        //根据前端$.ajax({jsonp:"callback"}) 设置的参数值进行取值,callback 的值是 JQuery 随机生成的
        String callback = request.getParameter("callback");
        System.out.println("callback=" + callback);
 
        //返回的参数必须是 json 格式,这里只是为了演示简单,实际中推荐使用 Gson、Fastjson、jackson 等库来操作 json
        String message = "{\"message\":\"I love You 西北的雪\"}";
        if (!StringUtils.isEmpty(callback)) {
            /**
             * callback 不为空,表示此时是 jsonp 跨域请求,后台返回的 json 数据必须放在 request.getParameter("callback") 的参数值中,如 callback(xxx) ,
             * 前端只会取其中的 xxx 纯数据
             * callback 为空时,表示是普通的 get 请求,此时不应该带上 callback(xxx) 中的前缀
             */
            message = callback + "(" + message + ")";
        }
        return message;
    }
}

2.<script src="">来完成跨域请求(就像你可以在自己的页面上使用<img src=""> 标签来随意显示某个域上的图片一样)

三个允许跨域标签:

<img src=XXX>
<link href=XXX>
<script src=XXX>

前端:

<%@ page pageEncoding="utf-8" contentType="text/html;charset=UTF-8"  language="java" %>
<html>
<head>
    <title>跨域测试</title>
    <script src="js/jquery-1.7.2.js"></script>
    <script>
        //回调函数
        function showData (result) {
            var data = JSON.stringify(result); //json对象转成字符串
            $("#text").val(data);
        }

        $(document).ready(function () {

            $("#btn").click(function () {
                //向头部输入一个脚本,该脚本发起一个跨域请求
                $("head").append("<script src='http://localhost:9090/student?callback=showData'><\/script>");
            });

        });
    </script>
</head>
<body>
    <input id="btn" type="button" value="跨域获取数据" />
    <textarea id="text" style="width: 400px; height: 100px;"></textarea>

</body>
</html>

后台:

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    response.setCharacterEncoding("UTF-8");
    response.setContentType("text/html;charset=UTF-8");

    //数据
    List<Student> studentList = getStudentList();


    JSONArray jsonArray = JSONArray.fromObject(studentList);
    String result = jsonArray.toString();

    //前端传过来的回调函数名称
    String callback = request.getParameter("callback");
    //用回调函数名称包裹返回数据,这样,返回数据就作为回调函数的参数传回去了
    result = callback + "(" + result + ")";

    response.getWriter().write(result);
}

2. js XdomainRequest作为ie8、9中的一种跨域手段,但是适用的业务场景还是比较局限:

varurl = 'http://localhost:8084/Server/HandlerServlet';
varxdr = new XDomainRequest();
xdr.onload = function() {           
    alert(xdr.responseText);
};
xdr.onerror = function() {
    alert("error");
};
xdr.timeout = 1000;
xdr.ontimeout = function() {
    alert("timeout");
};
xdr.open("get", url);
xdr.send();

3.Cors 跨域 (在response中设置允许跨域的header):jsonp 跨域只能解决 get 请求,对于其它的 post、put、delete 等请求都是无能无力的,使用 cors 则可以解决一切

前端:前台 javaScript 的代码和平时一样即可,不用任何特殊处理

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <title>CSRF跨站请求</title>
 
    <!-- 引入 JQuery -->
    <script src="https://code.jquery.com/jquery-3.3.1.js"
            integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="
            crossorigin="anonymous"></script>
 
    <script type="text/javascript">
        $(function () {
            $("#btn_jsonp").click(function () {
                $.ajax({
                    url: "http://localhost:8080/seals/postInfo", //请求地址
                    type: "POST",    //post 请求
                    data: {"info": "奋六世之余烈8080"},   //传递给服务器的数据
                    success: function (data) {
                        //接收返回的数据
                        console.log("success:" + data);
                    },
                    error: function (data) {
                        //错误时打印错误信息
                        console.log("error:" + JSON.stringify(data));
                    }
                })
            });
        });
    </script>
</head>
<body>
<button id="btn_jsonp" type="button" style="font-size: 30px;margin-top: 50px">Cors跨域请求</button>
</body>
</html>

后端:

    // 设置哪个源可以访问我
    res.setHeader('Access-Control-Allow-Origin', origin)
    // 允许携带哪个头访问我
    res.setHeader('Access-Control-Allow-Headers', 'name')
    // 允许哪个方法访问我
    res.setHeader('Access-Control-Allow-Methods', 'PUT')
    // 允许携带cookie
    res.setHeader('Access-Control-Allow-Credentials', true)
    // 预检的存活时间
    res.setHeader('Access-Control-Max-Age', 6)
    // 允许返回的头
    res.setHeader('Access-Control-Expose-Headers', 'name')

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashSet;
import java.util.Set;
/**
 * Created by Administrator on 2019/3/13 0013.
 */
@Controller
public class InfoControler {
    /**
     * post 请求:http://localhost:8080/seals/postInfo
     *
     * @param response
     * @param info
     * @return
     */
    @PostMapping("postInfo")
    @ResponseBody //内容直接返回页面
    public String postInfo(String info, HttpServletResponse response, HttpServletRequest request) {
        /**
         * response.setHeader("Access-Control-Allow-Origin", "*"):表示允许所有 域名 的脚本进行访问
         * response.setHeader("Access-Control-Allow-Origin", "http://localhost:55555"):表示允许指定的 协议://域名:端口 中的应用中的脚本访问
         * 注意 协议://域名:端口 必须完全一致,比如 localhost 与 127.0.0.1 虽然都是指向本机,但是也会认为是跨域
         */
        //设置IP 白名单如下,这里只是演示方便才写死,实际中应该从数据库或者配置文件中读取
        Set<String> witchIpSet = new HashSet<>();//
        witchIpSet.add("http://localhost:55555");
        witchIpSet.add("http://192.168.1.20:55555");
 
        String origin = request.getHeader("Origin");//获取请求头信息中的源
 
        System.out.println("origin=" + origin);
        if (origin != null && witchIpSet.contains(origin)) {
            System.out.println("白名单之列,放行....");
            response.setHeader("Access-Control-Allow-Origin", origin);
        }
        System.out.println("info=" + info);
        return info;
    }
}

4.Cors 跨域 :通过一个过滤器来解决

前端:前台 javaScript 的代码和平时一样即可,不用任何特殊处理

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
    <title>CSRF跨站请求</title>
 
    <!-- 引入 JQuery -->
    <script src="https://code.jquery.com/jquery-3.3.1.js"
            integrity="sha256-2Kok7MbOyxpgUVvAk/HJ2jigOSYS2auK4Pfzbm7uH60="
            crossorigin="anonymous"></script>
 
    <script type="text/javascript">
        $(function () {
            $("#btn_jsonp").click(function () {
                $.ajax({
                    url: "http://localhost:8080/seals/postInfo", //请求地址
                    type: "POST",    //post 请求
                    data: {"info": "奋六世之余烈8080"},   //传递给服务器的数据
                    success: function (data) {
                        //接收返回的数据
                        console.log("success:" + data);
                    },
                    error: function (data) {
                        //错误时打印错误信息
                        console.log("error:" + JSON.stringify(data));
                    }
                })
            });
        });
    </script>
</head>
<body>
<button id="btn_jsonp" type="button" style="font-size: 30px;margin-top: 50px">Cors跨域请求</button>
</body>
</html>

后台过滤器:通过一个过滤器来解决

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;

/**
 * 允许跨域过滤器(Cross-Origin Resource Sharing)
 * @author user
 *
 */
@Component
public class CorsFilter implements Filter {
    
    private final Logger logger = Logger.getLogger(this.getClass().getPackage().getName());
    
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {  
        HttpServletResponse response = (HttpServletResponse) res;  

        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "*");
        response.setHeader("Access-Control-Max-Age", "3600");
//        response.setHeader("Access-Control-Allow-Headers", "*");
        response.setHeader("Access-Control-Allow-Headers", "Authorization,Origin,X-Requested-With,Content-Type,Accept,"
                + "content-Type,origin,x-requested-with,content-type,accept,authorization,token,id,X-Custom-Header,X-Cookie,Connection,User-Agent,Cookie,*");
        response.setHeader("Access-Control-Request-Headers", "Authorization,Origin, X-Requested-With,content-Type,Accept");
        response.setHeader("Access-Control-Expose-Headers", "*");

        chain.doFilter(req, response);
    }
    
    public void init(FilterConfig filterConfig) {}
    
    public void destroy() {}
    
}

web.xml: 

<!-- 跨域过滤器 -->
<filter>  
    <filter-name>corsFilter</filter-name>  
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>corsFilter</filter-name>
    <url-pattern>/dental/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>corsFilter</filter-name>
    <url-pattern>/toothCheck/*</url-pattern>
</filter-mapping>

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值