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() {}
}
複製代碼
相關文章
相關標籤/搜索