SpringBoot+Ajax跨域安全问题及解决方法

〇、遇到跨域安全问题

在学习SpringBoot过程当中,遇到了这样一个问题。当时用SpringBoot开发Rest服务接口,而后用Ajax请求获取数据,来实现先后端分离。可是在前端请求时,始终不能显示应该显示的数据。从浏览器的控制台报错来看(以下图),应该是遇到了跨域安全的问题。前端

1、为何会出现跨域安全问题?

要解决这个问题,首先得知道为何会出现这个问题。经过了解,出现跨域安全问题的缘由通常是如下三个问题:浏览器收到了正确的返回数据可是作出了限制、发出去的请求是XMLHttpRequest请求而不是JSON请求、先后端协议域名端口等不同形成了跨域。java

2、怎么去解决出现的跨域安全问题?

根据上面的三个问题,去解决此次出现的跨域安全问题。web

1. 让浏览器不去作限制spring

不一样的浏览器应该有不一样的设置参数的方法。例如谷歌浏览器就是disable-web-security。不过咱们在应用中应该不会让咱们的用户去改浏览器的参数,因此我没有采用这种方法。后端

2. 让发出去的请求不是XMLHttpRequest请求跨域

在网上搜了一下,很多解决方法是把请求数据类型设为JSONP。可是存在一个问题就是若是用JSONP类型请求那么后台的服务接口也要作改动,由于用JSONP数据类型的请求虽然不是XHR但也不是JSON而是Script。而我想用的是JSON来实现先后端传输数据,并且JSONP对GET方式之外的请求不支持(我想用REST啊怎么能够木有POST\PUT\DELETE),因此我也没有采用这种方法。浏览器

3. 解决先后端协议域名端口等不同形成的跨域。安全

解决跨域能够从客户端考虑,也能够从服务端考虑。从客户端考虑,能够用代理来将服务端的请求转换成与客户端相同的域的请求从而解决跨域问题;从服务端考虑,能够考虑在响应头里增长字段。由于服务端就是我用SpringBoot写的,而增长字段并不须要对每一个接口进行改动,只要添加一个拦截器在全部的返回里添加返回头就能够了。固然,若是是调用别人家的接口,没法改动别人的服务端,那就只能考虑在客户端这边加代理了。markdown

根据控制台的错误信息,能够在服务端添加请求头Access-Control-Allow-Origin,来告诉浏览器服务端容许这个跨域。SpringBoot中我用的实现方式是增长一个Filter来拦截全部的请求在返回头里添加Access-Control-Allow-Origin和Access-Control-Allow-Method字段。事例代码以下(仅供参考):前后端分离

/*SpringBoot启动类*/
package net.tsingmo.SpringBootDemo;

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

@SpringBootApplication
public class SpringBootDemoApplication {

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

	@Bean
	public FilterRegistrationBean filterRegistrationBean () {
		FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
		filterRegistrationBean.addUrlPatterns("/*");
		filterRegistrationBean.setFilter(new ResponseHeaderFilter());
		return filterRegistrationBean;
	}
}


/*ResponseHeaderFilter类*/
package net.tsingmo.SpringBootDemo;

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

public class ResponseHeaderFilter implements javax.servlet.Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {}

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
        httpServletResponse.addHeader("Access-Control-Allow-Origin", "*");
        httpServletResponse.addHeader("Access-Control-Allow-Methods", "GET");
        filterChain.doFilter(servletRequest, httpServletResponse);
    }

    @Override
    public void destroy() {}
}
复制代码
相关文章
相关标签/搜索