Java - CORS跨域协议实践

in TCEHJava with 0 comment

一、简介

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

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

CORS详细介绍请点击《跨域资源共享 CORS 详解

二、示例

说明

  本示例将使用原始HttpServlet的方式来实现,能更加清晰的理解该协议。第三方框架(如Spring framework 4.2以上版本可通过注解@CrossOrigin设置跨域)大多实现了该协议,简单配置即可使用,不再赘述。

  可利用内网穿透的方式(如:http://xxx.xxx.com/Cors/index)访问主页,并设置ajax请求为http://localhost:8080/Cors/corsTest访问测试接口。以达到模拟跨域测试的目的。或者开启两个端口不同的Tomcat,如多加8081,可从8081的页面访问8080接口进行跨域测试。

相关代码如下

测试页面

<html>
<title>Cors Test</title>
<style type="text/css">
.container {
    display: flex;
    align-items: center; /* 垂直居中 */
    justify-content: center; /* 水平居中 */
}

.container div {
    width: 100px;
    height: 100px;
}
</style>
<body class="container">
    <font id="msg" size="20px" color="red"></font>
    <button onclick="todo();"
        style="width: 200px; height: 50px; background: #FF6666; color: white">跨域测试</button>
</body>
</html>

<script src="http://libs.baidu.com/jquery/2.1.1/jquery.min.js"></script>
<script>
    function todo() {
        var xmlhttp = new XMLHttpRequest();
        //简单请求
        xmlhttp.open("GET", "http://localhost:8080/Cors/corsTest", false);

        //非简单请求
        //xmlhttp.open("POST","http://localhost:8080/Cors/corsTest", false);
        //xmlhttp.setRequestHeader('Content-Type',"application/json");

        try {//此处通过捕获异常的方式判断跨域的成功或失败有误!
            xmlhttp.send();
            var corsText = xmlhttp.responseText;
            console.log(corsText);
            $('#msg').html(corsText);
        } catch (e) {
            console.log("跨域请求失败");
            $('#msg').html("跨域请求失败");
        }

    }
</script>

页面接口


package com.back.cors;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/index")
public class Index extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public Index() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        request.getRequestDispatcher("/WEB-INF/index.html").forward(request, response);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doGet(request, response);
    }

}

在接口上设置跨域

package com.back.cors;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 在接口上设置跨域
 * 
 * @author Back
 *
 */
@WebServlet("/corsTest")
public class Cors extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public Cors() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 取消下一行注释即可跨域请求。
        // response.addHeader("Access-Control-Allow-Origin", "*");
        // response.addHeader("Access-Control-Expose-Headers","Access-Control-Allow-Origin");
        response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().println("简单请求-跨域请求成功!");

    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 需在请求头的ContentType设置为application/json,模拟非简单请求
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json;charset=utf-8");
        response.getWriter().println("{\"msg\",\"非简单请求-跨域请求成功!\"}");

    }

}

在过滤器里设置跨域

package com.back.filter;

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.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;

/**
 * 在过滤器里设置跨域
 * 
 * @author Back
 *
 */
@WebFilter(urlPatterns = "/*")
public class CrosFilter implements Filter {

    @Override
    public void destroy() {
        // TODO Auto-generated method stub

    }

    @Override
    public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
            throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) arg1;
        // 非简单请求因需要预检,但是预检不进入方法,因此只能在过滤器设置跨域

        // 简单或非简单均需要该字段
        response.addHeader("Access-Control-Allow-Origin", "*");
        //非简单请求
        //response.addHeader("Access-Control-Allow-Headers", "Content-Type");
        arg2.doFilter(arg0, arg1);

    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
        // TODO Auto-generated method stub

    }

}
Comments are closed.