跨域

一. 什么是跨域:

域名地址的组成:

http:// www . google : 8080 / script/jquery.js

1. http:// (协议号)

2. www  (子域名)

3. google (主域名)

4. 8080 (端口号)

script/jquery.js (请求的地址)

* 当协议子域名主域名端口号中任意一各不相同时,都算不同的“”。

不同的域之间相互请求资源,就叫“跨域”。

比如:http://www.abc.com/index.html 请求 http://www.def.com/sever.php

 同源策略

同源策略,它是由Netscape提出的一个著名的安全策略。现在所有支持JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。

二. 处理跨域的方法

1. JSONP

JSONP 跨域请求, 可以参考我这篇博客   Jsonp 跨域 处理

2. 响应头中设置  Access-Control-Allow-Origin

//如果是普通的前端跨域请求的话, 就直接在后端返回参数时设置响应头就可以了 
response.setHeader("Access-Control-Allow-Origin", "*");

3. CORS 跨域(OPTIONS)

浏览器会在发送真正请求之前,先发送一个方法为OPTIONS的预检请求 Preflighted requests 这个请求是用来验证本次请求是否安全的,而且并不是所有请求都会发送,需要符合以下条件:

  • 请求方法不是GET/HEAD/POST
  • POST请求的Content-Type并非application/x-www-form-urlencoded, multipart/form-data, 或text/plain
  • 请求设置了自定义的header字段

对于管理端的接口,我有对接口进行权限校验,每次请求需要在header中携带自定义的字段(token),所以浏览器会多发送一个OPTIONS请求。

那为什么OPTIONS请求报错了。。。

经过debug发现,OPTIONS请求只会携带自定义的字段,并不会将相应的值带入进去,而后台校验token字段时 token为NULL,所以验证不通过,抛出了一个异常。

解决

先在项目中加个过滤器 Filter. 
import org.springframework.stereotype.Component;

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;

@Component
public class OriginFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        httpResponse.setHeader("Access-Control-Allow-Origin", httpRequest.getHeader("Origin"));
        httpResponse.setHeader("Access-Control-Allow-Methods", httpRequest.getMethod());
        httpResponse.setHeader("Access-Control-Max-Age", "3600");
        httpResponse.setHeader("Access-Control-Allow-Headers", httpRequest.getHeader("Access-Control-Request-Headers"));
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {
        
    }
}
然后在你项目的拦截器中 放行就行
 if ("OPTIONS".equals(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
            return true;
        }

  实际代码根据实际项目, 实际需求来, 但是原理是一样的.  可以根据原理来写相对应的代码

  CORS 详解可以 去查看,参考这篇博客 跨域资源共享 CORS 详解

4. 代理

  比如在北京(www.beijing.com/sever.php)和上海(www.shanghai.com/sever.php)各有一个服务器,北京的后端(www.beijing.com/sever.php)直接访问上海的服务,然后把获取的响应值返回给前端。也就是北京的服务在后台做了一个代理,前端只需要访问北京的服务器也就相当与访问了上海的服务器

posted @ 2020-06-15 21:42  经济人  阅读(182)  评论(0编辑  收藏  举报