ajax跨域问题(三)解决'跨域'——被调用方解决-服务端加头

ajax跨域问题(三)解决'跨域'——被调用方解决-服务端加头_第1张图片
a→b

被调用方解决(支持跨域):用户的浏览器上看到的访问b

b根据http协议关于跨域的要求,在返回里面加入一些字段,指明可以被a跨域,但是要是b不是我方的,没办法改 就不行了,
右边的nginx/tomcat,给响应加头

调用方的解决(隐藏跨域):用户浏览器上只能看到访问a,看不到访问b

a通过代理,达到实际上是b调用b
修改的是左边的nginx

被调用解决

ajax跨域问题(三)解决'跨域'——被调用方解决-服务端加头_第2张图片
被调用解决.png

右边的nginx或者tomcat,给响应加头

浏览器发现请求是跨域的,就会加一个请求头Origin:本域


ajax跨域问题(三)解决'跨域'——被调用方解决-服务端加头_第3张图片
Origin.png

如果服务端返回的响应头 没有对应的 同意跨域的头 浏览器就会拦下这个响应报错

服务器端(tomcat)实现

加一个过滤器, 过滤器里面手动加同意跨域的响应头

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 服务端通过加响应头 允许跨域
 */
public class CrosFilter implements Filter {

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

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
    

        HttpServletRequest req = (HttpServletRequest) request;

        HttpServletResponse res = (HttpServletResponse) response;
        String origin = req.getHeader("Origin");
        if (!org.springframework.util.StringUtils.isEmpty(origin)) {
            //带cookie的时候,origin必须是全匹配,不能使用*
            res.addHeader("Access-Control-Allow-Origin", origin);//加这个头表示:允许这个域 跨域访问
        }

        //不论是get post 所有方法都允许跨域
        res.addHeader("Access-Control-Allow-Methods", "*");

        //res.addHeader("Access-Control-Allow-Headers", "Content-Type");//允许非简单  就是往这里传json
        String headers = req.getHeader("Access-Control-Request-Headers");
        // 支持所有自定义头
        if (!org.springframework.util.StringUtils.isEmpty(headers)) {
            res.addHeader("Access-Control-Allow-Headers", headers);         
        }

        res.addHeader("Access-Control-Max-Age", "3600");//options预检命令缓存 这个时间段
        
        // enable cookie
        res.addHeader("Access-Control-Allow-Credentials", "true");
        
        chain.doFilter(request, response);
    }

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

    }

}

注册这个过滤器

@Bean
    public FilterRegistrationBean registerFilter() {

        FilterRegistrationBean bean = new FilterRegistrationBean();

        bean.addUrlPatterns("/*");//所有请求都必须经过这个
        bean.setFilter(new CrosFilter());//刚才自己写的加同意跨域响应头的 过滤器

        return bean ;
    }

关于非简单请求
cookie

现在响应头变为


ajax跨域问题(三)解决'跨域'——被调用方解决-服务端加头_第4张图片
注意看响应头.png

过滤器 加了这些响应头
Access-Control-Allow-Credentials: true cookie
Access-Control-Allow-Methods: * get post等所有方法都允许跨域
Access-Control-Allow-Origin: http://localhost:8081 允许这个origin跨域访问
Access-Control-Max-Age: 3600 缓存一小时 不用再发预检命令

其实!spring框架只要在controller里面加注解就能达到以上过滤器一样的效果!

@RestController
@RequestMapping("/test")
@CrossOrigin //最简单是就是spring 自带的解决跨域 这样就不用advice配合jsonp 或filter加响应头特许了
public class TestController {

这样或者只加相应方法上

你可能感兴趣的:(ajax跨域问题(三)解决'跨域'——被调用方解决-服务端加头)