Spring Boot对cors(跨域)的支持(六)

1.跨域的简介

当协议、域名、端口号任意一个不相同时,都算作不同域。不同域之间请求资源,就是跨域。

跨域并不是http请求发送不出去,请求可以发出去,服务端也能接受并正常返回结果,只是结果被浏览器拦截了。

当不同域访问,就会报以下错误:2.使用WebMvcConfigurerAdapter初始化参数

(1)使用@Bean注入的方式

添加@Configuration注解,配置Bean,具体使用如下:

@Configuration
public class Cors{
	
	@SuppressWarnings("deprecation")
	@Bean
	public WebMvcConfigurerAdapter webMvcConfigurerAdapter(){
		@Override
		    public void addCorsMappings(CorsRegistry registry) {
		        registry.addMapping("/**")
		        .allowedOrigins("*")
		        .allowedMethods("GET", "POST", "PUT", "OPTIONS", "DELETE", "PATCH")
		          .allowCredentials(true).maxAge(3600);
		    }
			
		};
	}

(2)继承WebMvcConfigurerAdapter方法,覆写addCorsMappings方法,具体实现如下:

@Configuration
public class Cors extends WebMvcConfigurerAdapter {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
        .allowedOrigins("*")
        .allowedMethods("GET", "POST", "PUT", "OPTIONS", "DELETE", "PATCH")
          .allowCredentials(true).maxAge(3600);
    }
  }

3.使用拦截器的方法进行处理

拦截器的书写方法如下:

package com.example.demo.util.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.http.HttpHeaders;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

public class CorsInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, 
            HttpServletResponse response, Object handler) throws Exception {
        if (request.getHeader(HttpHeaders.ORIGIN) != null)
        {
            response.addHeader("Access-Control-Allow-Origin", "*");
            response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD");
            response.addHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
            response.addHeader("Access-Control-Max-Age", "3600");
        }
       return true;
    }

    /**
     * 在业务处理器处理请求执行完成后,生成视图之前执行的动作
     * 可在modelAndView中加入数据,比如当前时间
     */
    @Override
    public void postHandle(HttpServletRequest request, 
            HttpServletResponse response, Object handler, 
            ModelAndView modelAndView) throws Exception {
    }

    /**
     * 在DispatcherServlet完全处理完请求后被调用,可用于清理资源等
     * 当有拦截器抛出异常时,会从当前拦截器往回执行所有的拦截器的afterCompletion()
     */
    @Override
    public void afterCompletion(HttpServletRequest request, 
            HttpServletResponse response, Object handler, Exception ex) 
            throws Exception {
    }

}

使拦截器生效:

如同2方法,覆写的方法改为addInterceptors即可,如下:

	@Bean
	public WebMvcConfigurerAdapter webMvcConfigurerAdapter(){
		return new WebMvcConfigurerAdapter() {
			@Override
			public void addInterceptors(InterceptorRegistry registry) {
				registry.addInterceptor(new CorsInterceptor());
			}
			
		};
	}

4.使用过滤器的方法进行处理,过滤器的使用方法如下:

public class InitCORSFilter implements Filter{

private Logger logger = LoggerFactory.getLogger(InitCORSFilter.class);

@Override
public void init(FilterConfig filterConfig) throws ServletException {
    logger.info("==== 初始化系统允许跨域请求 ====");
}

/**
 * 解决跨域:Access-Control-Allow-Origin,值为*表示服务器端允许任意Domain访问请求
 */
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
		throws IOException, ServletException {
		if(response instanceof HttpServletResponse) {
			HttpServletResponse httpServletResponse = (HttpServletResponse)response;
			httpServletResponse.addHeader("Access-Control-Allow-Origin", "*");
			httpServletResponse.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
			httpServletResponse.addHeader("Access-Control-Allow-Headers", "origin, content-type, accept, x-requested-with, sid, mycustom, smuser");
			httpServletResponse.addHeader("Access-Control-Max-Age", "1800");//30 min
		}
		chain.doFilter(request, response);
	}

	@Override
	public void destroy() {
		System.out.println("filter is destroy");
	}

}

5.细粒度处理,即单个方法处理

(1)使用注解,在对应的方法上使用注解,如下:

    @CrossOrigin(origins = "*")
	@RequestMapping(value="/find/{id}/{name}")
	public User find(@PathVariable int id, @PathVariable String name) {

		User user = new User();
		user.setId(id);
		user.setName(name);
		user.setDate(new Date());
		return user;
	}

添加HttpServletResponse,修改反应头文件,如下:

	@RequestMapping(value="/find/{id}/{name}")
	public User find(@PathVariable int id, @PathVariable String name, HttpServletResponse response) {
		response.addHeader("Access-Control-Allow-Origin", "*");
        response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD");
        response.addHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
        response.addHeader("Access-Control-Max-Age", "3600");
		User user = new User();
		user.setId(id);
		user.setName(name);
		user.setDate(new Date());
		return user;
	}

经测试,以上方法均可解决跨域问题。

猜你喜欢

转载自blog.csdn.net/qq_36831305/article/details/92563773