1. 程式人生 > >前後端分離-跨域

前後端分離-跨域

對於前後端分離的專案來說,如果前端專案與後端專案部署在兩個不同的域下,那麼勢必會引起跨域問題的出現。什麼是跨域?跨域,指的是瀏覽器不能執行其他網站的指令碼。它是由瀏覽器的同源策略造成的,是瀏覽器施加的安全限制。簡單來說就是不同域名之間相互訪問同源策略:請求的url地址,必須與瀏覽器上的url地址處於同域上,也就是域名,埠,協議相同.例如: http://www.a.com 要訪問 http://www.b.com 這樣域名不同,屬於跨域 http://www.a.com:8081/index.html呼叫http://www.a.com:8080的介面 這樣埠號不同 也屬於跨域 http://www.a.com:訪問https://www.a.com 這樣也是屬於跨域 協議不一樣所以在以前前後端不分離的開發模式中,從來不用關注這個問題,因為所有的請求都是在同一個域內綜合了網上解決跨域的方式目前有兩種1.使用JSONP不過我不太推薦使用,JSONP只支援GET請求,不管是對於前端還是後端來說,寫法與我們平常的ajax寫法不同,同樣後端也需要作出相應的更改。 JSONP的優勢在於支援老式瀏覽器,以及可以向不支援CORS的網站請求資料。2.通過cors協議解決跨域問題CORS支援所有型別的HTTP請求。 這個也是我非常推薦大家使用的方法 下面我來說下專案中遇到的問題 前端:vue.js 後端:springboot前端請求介面時,報錯資訊如下Origin 'h

ttp://localhost:8080’ is therefore not allowed access. The credentials mode of an XMLHttpRequest is controlled by the withCredentials attribute 解決方法: 前端請求開啟 withCredentials: true 後臺介面也需要對應的將 Access-Control-Allow-Credentials 設為 true。前端攜帶token傳後端時報錯Request header field token is not allowed by Access-Control-Allow-Headers in preflight response. 這是由於請求頭內並沒有這個名叫token的請求頭欄位 預設情況下,只有六種 simple response headers (簡單響應首部)可以暴露給外部: Cache-Control Content-Language Content-Type Expires Last-Modified Pragma 如果想要讓客戶端可以訪問到其他的首部資訊,可以將它們在 Access-Control-Expose-Headers 裡面列出來。所以解決方法是:在Access-Control-Allow-Headers新增自定義的請求頭欄位Token 如果還有其他請求頭欄位需要使用,也是需要在Access-Control-Allow-Headers新增,不然伺服器是不允許的後面還有一個問題:Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘
http://localhost:8080
’ is therefore not allowed access. The response had HTTP status code 503. 這個是請求頭返回服務不可用解決方式:我看了下程式碼原來是我寫了兩個跨域過濾一個是用寫過濾器Filter,一個是繼承 webmvcconfigureradapter然後我註釋了其中一個就可以了,我想應該是兩個跨域處理器衝突了拓展現在開發客戶端都是發非簡單請求 非簡單請求是那種對伺服器有特殊要求的請求,比如請求方法是PUT或DELETE,或者 Content-Type欄位的型別是application/json。也就是通過json資料互動 非簡單請求的CORS請求,會在正式通訊之前,增加一次HTTP查詢請求,稱為"預檢"請求(preflight)。流程瀏覽器先詢問伺服器,當前網頁所在的域名是否在伺服器的許可名單之中,以及可以使用哪些HTTP動詞和頭資訊欄位。只有得到肯定答覆,瀏覽器才會發出正式的 XMLHttpRequest請求,否則就報錯。"預檢"請求用的請求方法是OPTIONS,表示這個請求是用來詢問的。頭資訊裡面,關鍵欄位是Origin,表示請求來自哪個源。 一般不特殊指定源的話都將Access-Control-Allow-Origin設定為* 除了Origin欄位,"預檢"請求的頭資訊包括兩個特殊欄位。 (1)Access-Control-Request-Method 該欄位是必須的,用來列出瀏覽器的CORS請求會用到哪些HTTP方法 所使用到的方法也是要在跨域處理器中說明 也就是在Access-Control-Allow-Methods中加入各種請求方法 例如:POST PUT, GET, OPTIONS, DELETE (2)Access-Control-Request-Headers 該欄位是一個逗號分隔的字串,指定瀏覽器CORS請求會額外發送的頭資訊欄位 這個上面有說到,專案需要什麼額外的請求頭欄位就新增上去 伺服器收到"預檢"請求以後,檢查了Origin、Access-Control-Request-Method和 Access-Control-Request-Headers欄位以後,確認允許跨源請求,就可以做出迴應。 說了這麼 我分享下我的跨域處理的程式碼(我這裡是使用過濾器的寫法,也可以使用繼承 webmvcconfigureradapter的方法)

@Component
public class CorsFilter implements Filter {
    /*跨域請求配置*/
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;


 HttpServletRequest reqs = (HttpServletRequest) req;
    response.setHeader("Access-Control-Allow-Origin","*");
    response.setHeader("Access-Control-Allow-Credentials", "true");
    response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
    response.setHeader("Access-Control-Max-Age", "5000");
    response.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,Authorization,Token");
    chain.doFilter(req, res);
}
@Override
public void init(FilterConfig filterConfig) {}
@Override
public void destroy() {}}

繼承webmvcconfigurer的adapter的方法

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedOrigins("*").allowedMethods("GET", "POST", "OPTIONS", "PUT")
                .allowedHeaders("Content-Type", "X-Requested-With", "accept", "Origin", "Access-Control-Request-Method",
                        "Access-Control-Request-Headers")
                .exposedHeaders("Access-Control-Allow-Origin", "Access-Control-Allow-Credentials")
                .allowCredentials(true).maxAge(3600);
    }
}

注:以上寫法二選一

即可,兩個都寫估計還是會衝突,兩者作用一樣只是寫法不同