ajax 跨域 CROS

在某域名下使用ajax向另一个域名下的地址请求数据时,浏览器出于安全考虑,会限制在脚本中发起的跨域请求。然而怎样才能算跨域?协议,域名,端口都必须相同,才算在同一个域。也就是说如果协议、域名、端口中有一个不同,就是在不同的域。

例如我现有一个jsp页面,http://localhost:8080/domainReq/index.jsp,若用ajax请求下面地址的服务时,会出现跨域问题。

地址端口跨域
http://100.111.10.48:8080/8080地址不同
http://localhost:80808080地址、端口相同,可以请求。
http://localhost:80818081端口不同
https://100.111.10.48:80808080协议不同

例外:由于JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求。这里不考虑JSONP。
HTML5带来了一个新的跨域解决方案CORS,CORS是一个W3C标准,全称是”跨域资源共享”(Cross-Origin Resource Sharing)。具体看百科

CROS header简单的描述

标头描述
Access-Control-Allow-Origin多个域名可以用逗号隔开。如www.ios.com,www.android.com。*表示谁都可以,不限制域名(不建议使用)。
Access-Control-Expose-Headers设置浏览器允许访问的服务器的头信息的白名单
Access-Control-Max-Age在CROS协议中,一个AJAX请求被分成了两步。第一步OPTION为预检测请求,第二步为正式请求。请求的结果的有效期是多久,单位秒。
Access-Control-Allow-Credentials是否允许请求带有验证信息
Access-Control-Allow-Methods资源可以被哪些方式请求GET, POST,TRACE等,多个值时用逗号分开,*为不受限制。
Access-Control-Allow-Headers允许自定义的头部,逗号隔开。如:Content-Type, x-requested-with, Authorization等。

比如:Access-Control-Allow-Headers,若ajax请求时header带了Authorization令牌,而这里又未设置时会出现(已拦截跨源请求:同源策略禁止读取位于 http://100.111.10.48:8080/domain/MyServlet 的远程资源。(原因:来自 CORS 预检通道的 CORS 头 ‘Access-Control-Allow-Headers’ 的令牌 ‘authorization’ 无效)。


下面来看看ajax调用跨域服务,和服务端分别通过spring mvc 注解方式或Servlet + Filter 方式发布服务。

1.请求示例
客户端IP为100.111.10.17
这里写图片描述

2.未设置Response Headers时
btn1事件引用的地址并没有设置任何Response Headers信息。
返回错误信息:XMLHttpRequest cannot load http://100.111.10.48:8080/domain/MyServlet. No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://localhost:8080’ is therefore not allowed access.
这里写图片描述

3.设置Response Headers时
btn2事件引用的地址,Response Headers设置了Access-Control等信息。可以成功返回结果,已经打印出信息了。
在这里发现会请求两次,第一次Method为OPTIONS,第二次为POST。这是因为在做跨域请求时浏览器会自动发起一个 OPTIONS 到服务器,是一种预检测请求,用来检测是否安全。
从服务器返回的headers中,可以看到分别设置了CROS 各种信息:

Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:x-requested-with,Authorization
Access-Control-Allow-Methods:POST, GET, OPTIONS, DELETE
Access-Control-Allow-Origin:http://localhost:8080
Access-Control-Max-Age:10
Allow:GET, HEAD, POST, TRACE, OPTIONS
Content-Length:0
Date:Thu, 01 Dec 2016 08:36:36 GMT
Server:Apache-Coyote/1.1

这里写图片描述

4.后台服务

1.采用Spring CrossOrigin

CrossOrigin注解在spring mvc 4.2 之上才有的特性。可参考http://spring.io/blog/2015/06/08/cors-support-in-spring-framework

@RestController
@RequestMapping(value = "/helloworld")
public class HelloController {

    /**
     * CrossOrigin注解在spring mvc 4.2
     * @param id
     * @param request
     * @param response
     * @return
     */
    @CrossOrigin(origins = "http://localhost:8080", maxAge = 10)
    @RequestMapping(value = "/rest/{id}", method = { RequestMethod.POST, RequestMethod.GET })
    public Message getms(@PathVariable int id, HttpServletRequest request, HttpServletResponse response) {
        System.out.println("---------------rest/" + id + " request-------------");
        System.out.println(request.getHeader("Authorization"));
        System.out.println(request.getHeader("x"));
        Message message = new Message();
        message.setId(Integer.toString(id));
        message.setName("123");
        message.setText("hello,123");
        return message;
    }
}
2.过滤器方式

Filter

public class CORSFilter implements Filter {

    @Override
    public void destroy() {
        System.out.println("Filter-destroy");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
            throws IOException, ServletException {
        //String origin = (String) servletRequest.getRemoteHost()+":"+servletRequest.getRemotePort();
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        System.out.println("Filter-Method:" + request.getMethod()); // GET, POST, OPTIONS
        System.out.println("Filter-Authorization:" + request.getHeader("Authorization"));

        HttpServletResponse response = (HttpServletResponse) servletResponse;
        response.setHeader("Access-Control-Allow-Origin", "http://localhost:8080");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "10");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with,Authorization");
        response.setHeader("Access-Control-Allow-Credentials", "true");

        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void init(FilterConfig arg0) throws ServletException {
        System.out.println("Filter-init");
    }
}

Servlet

/**
 * Servlet implementation class MyServlet
 */
public class MyServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public MyServlet() {
        super();
    }

    @Override
    public void init() throws ServletException {
        super.init();
        System.out.println("Servlet-init");
    }

    @Override
    public void destroy() {
        super.destroy();
        System.out.println("Servlet-destroy");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {       
        System.out.println("Servlet-Method:" + request.getMethod());
        System.out.println("Servlet-Authorization:" + request.getHeader("Authorization"));

        response.getWriter().append("{\"CTY\": \"china\"}");
        response.getWriter().close();
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值