服务端Filter解决跨域方法

Posted zkai-007

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了服务端Filter解决跨域方法相关的知识,希望对你有一定的参考价值。

问题一、浏览器是先执行请求还是先判断跨域?

  浏览器请求-->判断响应中是否有允许跨域-->发现不允许跨域,阻止跨域

  说明:当执行跨域请求时,浏览器会提示当前接口不被允许,这说明浏览器已发出了当前请求,但是它的的响应内容被拦截;如果在Response header中的Access-Control-Allow-Origin设置的允许访问源不包含当前源,则拒绝数据返回给当前源。

问题二、判断当前请求是否是跨域请求?

  通过查看当前请求的Request Headers 中是否存在Origin属性,当前属性存储的是当前域的信息

问题三、什么是简单请求和非简单请求?

  说明:浏览器在发送跨域请求时会先判断当前请求是不是简单请求,如果是简单请求浏览器则会先执行请求,再判断是否支持跨域;如果是非简单请求它会先发送一个预检命令(即OPTIONS请求),检查通过后再把当前请求发出去。

  (1)简单请求:方法为GET、HEAD、POST的请求,并且请求头(header)里面没有自定义头;Content-Type为text/plain、multipart/form-data、application/x-www-form-urlencoded。

  (2)非简单请求:方法为PUT、DELETE的请求,发送JSON格式的ajax请求、带自定义请求头的ajax请求。

  例如:发送JSON格式数据的ajax请求

 

$.ajax({
  type : "post",
  url: base + "/postJson",
  contentType :
"application/json;charset=utf-8",
  data: JSON.stringify({name:
"小明"}),
  success:
function(json){
    var result
= json;
  }
});

问题四:Access-Control-Allow-Headers是什么?有什么作用?

  响应头部 Access-Control-Allow-Headers 用于 preflight request (预检请求)中,列出了将会在正式请求的 Access-Control-Expose-Headers 字段中出现的首部信息。简单首部,如 simple headers、Accept、Accept-Language、Content-Language、Content-Type (只限于解析后的值为 application/x-www-form-urlencoded、multipart/form-data 或 text/plain 三种MIME类型(不包括参数)),它们始终是被支持的,不需要在这个首部特意列出。

问题五:Access-Control-Max-Age是什么?
  浏览器的同源策略,就是出于安全考虑,浏览器会限制从脚本发起的跨域HTTP请求(比如异步请求GET, POST, PUT, DELETE, OPTIONS等等),所以浏览器会向所请求的服务器发起两次请求,第一次是浏览器使用OPTIONS方法发起一个预检请求,第二次才是真正的异步请求,第一次的预检请求获知服务器是否允许该跨域请求:如果允许,才发起第二次真实的请求;如果不允许,则拦截第二次请求。Access-Control-Max-Age用来指定本次预检请求的有效期,单位为秒,,在此期间不用发出另一条预检请求。

  例如:res.addHeader("Access-Control-Max-Age", "3600"),表示隔60分钟才发起预检请求

1、在被调用方解决跨域(支持跨域)通过自定义Filter来实现:

(1)在SpringBoot工程创建自定拦截器CrosFilter,如图:

package *;

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;

import org.apache.tomcat.util.buf.StringUtils;

public class CrosFilter implements Filter {

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

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // TODO Auto-generated method stub

        HttpServletResponse res = (HttpServletResponse) response;
        HttpServletRequest req = (HttpServletRequest) request;
        String origin = req.getHeader("Origin");
        if (!org.springframework.util.StringUtils.isEmpty(origin)) {
            //带cookie的时候,origin必须是全匹配,不能使用*
            res.addHeader("Access-Control-Allow-Origin", origin);            
        }
        res.addHeader("Access-Control-Allow-Methods", "*");
        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");
        // enable cookie
        res.addHeader("Access-Control-Allow-Credentials", "true");
        chain.doFilter(request, response);
    }

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

}

 (2)注册自定拦截器CrosFilter,作用于全局:

package com.imooc;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;

import com.fasterxml.jackson.databind.ser.impl.FilteredBeanPropertyWriter;

@SpringBootApplication
public class AjaxserverApplication {

    public static void main(String[] args) {
        SpringApplication.run(AjaxserverApplication.class, args);
    }

    @Bean
    public FilterRegistrationBean registerFilter() {
        FilterRegistrationBean bean = new FilterRegistrationBean();
        bean.addUrlPatterns("/*");
        bean.setFilter(new CrosFilter());
        return bean ;
    }
}

 








以上是关于服务端Filter解决跨域方法的主要内容,如果未能解决你的问题,请参考以下文章

后端解决跨域的问题

非jsonp解决跨域问题

Spring Boot前后端分离跨域问题

跨域访问接口上传图片出现options请求问题解决方法

vue跨域解决方法

Java服务端用CORS方法解决浏览器跨域问题