解決問題之跨域問題

本文主要介紹的解決方式:

  • Vue 項(xiàng)目中配置代理
  • 后端注解 @CrossOrigin
  • 繼承 WebMvcConfigurer 的全局配置類

跨域其實(shí)并不是一種問題,而是瀏覽器的安全機(jī)制。在 Web 開發(fā)中,由于瀏覽器的同源策略限制,導(dǎo)致不同源(域、協(xié)議、端口)之間的網(wǎng)頁訪問受到限制或出現(xiàn)安全問題。

協(xié)議://域名:端口(如 http://localhost:8080): 同源策略表示協(xié)議、域名和端口必須一致。比如在前后端分離項(xiàng)目中,后端項(xiàng)目運(yùn)行在本機(jī)的 8080 端口,前端運(yùn)行在 80 端口,這樣前端訪問后端就會(huì)因?yàn)椴煌矗ǘ丝诓煌?dǎo)致跨域限制。

解決跨域問題可以通過下面幾種方式:

  • 跨域資源共享 ( CORS ):服務(wù)端設(shè)置響應(yīng)頭,允許特定源訪問資源;
  • JSONP ( JSON with Padding ):利用 Script 標(biāo)簽可以跨域的特性,在前端頁面通過動(dòng)態(tài)創(chuàng)建 Script 標(biāo)簽來獲取跨域數(shù)據(jù);
  • 代理:后端通過代理將請(qǐng)求轉(zhuǎn)發(fā),避免前端直接跨域請(qǐng)求;
  • 服務(wù)器設(shè)置跨域規(guī)則:配置服務(wù)器,使其允許跨域請(qǐng)求訪問資源。

方式一:前端配置

  1. Vue 項(xiàng)目,在 vite.config.js 文件中可添加如下代理配置,在該文件最后另起一行進(jìn)行添加即可。

    module.exports = {
      devServer: {
        proxy: {
          '/api': {
            target: 'http://localhost:8989',
            changeOrigin: true,
            pathRewrite: {
              '^/api': ''
            }
          }
        }
      }
    }
    

    以上配置是將帶有 /api 前綴的請(qǐng)求進(jìn)行代理,將其代理到 'http://localhost:8989',并將 /api 去掉

  2. 如果項(xiàng)目中的 Axios 配置文件 (我的項(xiàng)目中該配置的文件名是 axios.js)有配置 baseURL 完整路徑的,則需要將 協(xié)議://域名:端口 部分去掉,只保留一個(gè) /api/。這樣做的目的是:所有的 Ajax 請(qǐng)求都會(huì)加一個(gè) /api/ 前綴,然后所有帶有 /api 前綴的又將被代理到 http://localhost:8989,從而避免瀏覽器的跨域限制。

import axios from 'axios';
// 創(chuàng)建一個(gè) Axios 實(shí)例,可以給所有的請(qǐng)求都加上一個(gè) /api 前綴
const http = axios.create({
    baseURL: '/api/'
});
export default http;

方式二:后端注解 @CrossOrigin

前面介紹的是前端配置咯,其實(shí)在后端也可以解決跨域問題。

  1. 在控制類上加注解 @CrossOrigin,然后通過 origins 參數(shù)指定允許跨域訪問的域地址。
@RestController
@RequestMapping("/api/test")
//@CrossOrigin
@CrossOrigin(origins = {"http://localhost:5173", "https://xxxx.com"})
public class TestController {
//    @CrossOrigin(origins = "http://xxx.icu")
    @GetMapping()
    public String test() {
        return "test success!!!";
    }
}
  • origins: 允許可訪問的域列表;

  • maxAge: 準(zhǔn)備響應(yīng)前的緩存持續(xù)的最大時(shí)間(單位秒);

  • @CrossOrigin 后面不加任何參數(shù),表示允許所有源訪問。其后可以通過 origins 參數(shù)指定一個(gè)或多個(gè)域,表示允許這些指定的域進(jìn)行訪問。該注解也可以加在方法上,含義一樣,表示允許跨域訪問該方法。

方式三:配置全局跨域支持

創(chuàng)建一個(gè)繼承自 WebMvcConfigurer 的配置類,重寫其中的 addCorsMappings 方法來配置允許跨域的規(guī)則。(注意類上要加 @Configuration 注解表面這是一個(gè)配置類,并將其交由 Spring 容器管理)

@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOriginPatterns("*")
                .allowedMethods("*")
                .allowCredentials(true)
                .allowedHeaders("token")
                .maxAge(3600);
    }
}
  • addMapping("/**"): 指定允許跨域訪問的路徑,通常是所有路徑;

  • allowedOriginPatterns(“*"): 表示允許所有的來源;

  • allowedOrigins("http://xxx.com"): 表示允許指定的來源,區(qū)別在于 allowedOriginPatterns() 可以進(jìn)行模式匹配,而這個(gè)需要指定明確地地址;

  • allowedMethods("*"): 表示允許所有的 HTTP 方法進(jìn)行跨域請(qǐng)求;

  • allowedCredentials(true): 允許跨域請(qǐng)求攜帶身份憑證 (如 cookies、HTTP 認(rèn)證信息等);

  • allowedHeaders("token"): 指定了允許跨域請(qǐng)求攜帶的請(qǐng)求頭信息,這里表示只允許攜帶名為 "token" 的請(qǐng)求頭;

  • maxAge(3600): 指定預(yù)檢請(qǐng)求有效期,即在多久內(nèi)不需要再發(fā)送預(yù)檢請(qǐng)求,這里是 3600 秒(1 小時(shí))。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容