利用Access-Control-Allow-Origin解决跨域问题

当前端页面与后台运行在不同的服务器时,就必定会出现跨域这一问题,下面将介绍使用Access-Control-Allow-Origin头字段来解决跨域问题。在服务端响应请求中添加Access-Control-Allow-Origin头字段,如果该字段的值为*,则表示允许所有访问;如果指定特定的域名,则表示只允许该域名访问。

什么是跨域

当两个域具有相同的协议(如http), 相同的端口(如80),相同的host(如https://www.test.com:8080),那么我们就可以认为它们是相同的域(协议,域名,端口都必须相同)。

跨域就指协议,域名,端口不一致,出于安全考虑,跨域的资源之间是无法交互的 (例如:一般情况跨域的 JavaScript 无法交互,当然有很多解决跨域的方案,这里讲给出使用 Access-Control-Allow-Origin 头字段来解决)。

Access-Control-Allow-Origin

Access-Control-Allow-Origin 头字段是 HTML5 中定义的一种解决资源跨域的策略。他是通过服务器端返回带有 Access-Control-Allow-Origin 标识的 Response header,用来解决资源的跨域权限问题。

使用方法,在response添加 Access-Control-Allow-Origin,例如

Access-Control-Allow-Origin: https://www.test1.com

https://www.test1.com  是访问的域名,根据实际情况设置。

也可以设置为 * 表示该资源谁都可以用

Access-Control-Allow-Origin:  *

如果资源是html页面,可以设置 

<meta http-equiv="Access-Control-Allow-Origin" content="*">

实例:假如我们有两个应用,分别是 webapp_account(访问地址:https://www.account.com:8081/account) 和 webapp_payment(访问地址:https://www.payment.com:8082/payment),然后  webapp_payment 应用通过JS代码调用 webapp_account 的的服务。

webapp_account 提供了一个 AccountInfoServlet 服务,用来获取用户基本信息。代码如下:

import com.alibaba.fastjson.JSONObject;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class AccountInfoServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
        System.out.println("#### start......" + System.currentTimeMillis());
        // 设置返回数据的类型
        resp.setHeader("Content-Type", "application/json");
        JSONObject json = new JSONObject();

        try {
            json.put("id", "10010");
            json.put("name", "Bill");
            json.put("sex", "male");
        } catch (Exception e) {
            e.printStackTrace();
            json.put("errorMessage", e.getMessage());
        } finally {
            PrintWriter writer = resp.getWriter();
            writer.print(json.toJSONString());
            writer.flush();
            writer.close();
        }

        System.out.println("####   end......" +  + System.currentTimeMillis());
    }

}

webapp_payment 应用在前段页面通过JS访问 AccountInfoServlet  服务。代码如下:

<button id="btnTest">调用webapp_account</button>
<script type="text/javascript">
    $("#btnTest").click(function(){
        $.getJSON("https://www.account.com:8081/account/servlet/accountInfoServlet", function(ret){
            console.debug(ret);
        });
    });
</script>

执行上面的JS调用抛出了如下错误信息:

Failed to load https://www.account.com:8081/account/servlet/accountInfoServlet: The 'Access-Control-Allow-Origin' header contains the invalid value 'www.payment.com'. Origin 'https://www.payment.com:8082' is therefore not allowed access.

从上面的错误信息得知,出现了跨域错误。下面通过在 AccountInfoServlet  设置 Access-Control-Allow-Origin 头字段来解决。代码如下:

import com.alibaba.fastjson.JSONObject;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 该服务提供给 webapp_payment 进行调用,此时将抛出跨域错误信息。
 * 我们通过响应的 Access-Control-Allow-Origin 头字段来控制是否允许跨域访问。
 */
public class AccountInfoServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
        doPost(req, resp);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {
        System.out.println("#### start......" + System.currentTimeMillis());

        // 设置返回数据的类型
        resp.setHeader("Content-Type", "application/json");
        // 设置允许 www.payment.com 域进行跨域访问
        //  resp.setHeader("Access-Control-Allow-Origin", "https://www.payment.com:8082");
        // 允许任何域名都能访问
        resp.setHeader("Access-Control-Allow-Origin", "*");

        JSONObject json = new JSONObject();
        try {
            json.put("id", "10010");
            json.put("name", "Bill");
            json.put("sex", "male");
        } catch (Exception e) {
            e.printStackTrace();
            json.put("errorMessage", e.getMessage());
        } finally {
            PrintWriter writer = resp.getWriter();
            writer.print(json.toJSONString());
            writer.flush();
            writer.close();
        }
        System.out.println("####   end......" +  + System.currentTimeMillis());
    }

}

到这里,跨域问题就解决了。

自知之明是最难得的知识。——西班牙
0 不喜欢
说说我的看法 -
全部评论(
没有评论
目录
热门标签
热门文章
关于
本网站属于个人的非赢利性网站,转载的文章遵循原作者的版权声明,如果原文没有版权声明,请来信告知:hxstrive@outlook.com
公众号