微服務(wù)設(shè)計指導-糾正目前網(wǎng)上近90%以上錯誤的對于“API跨域”問題的所謂指導

背景

因為我們是前后臺分離的寫法;

因為我們用的是VUE/Angelar;

因為我們在開發(fā)這套東西時,存在上述兩個問題,而Spring Boot2默認是不允許跨域。因此我們開發(fā)時經(jīng)常會發(fā)生這樣的情況:

我們有一個spring boot controller如下

/**

* 系統(tǒng)項目名稱 org.sky.demo.redisdemo.controller RedisDemoController.java

*

* Jan 15, 2021-2:55:10 PM 2021XX公司-版權(quán)所有

*

*/packageorg.mk.demo.mvc1.api;importorg.mk.demo.mvc1.bean.Student;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.web.bind.annotation.PostMapping;importorg.springframework.web.bind.annotation.RequestBody;importorg.springframework.web.bind.annotation.RequestMapping;importorg.springframework.web.bind.annotation.ResponseBody;importorg.springframework.web.bind.annotation.RestController;importio.swagger.annotations.Api;importio.swagger.annotations.ApiOperation;/** *? * RedisDemoController *? *? * Jan 15, 2021 2:55:10 PM *? *@version1.0.0 *? */@RestController@RequestMapping("/demo")@Api(tags ="demo mvc1")publicclassApiController{privateLogger logger = LoggerFactory.getLogger(this.getClass());@ApiOperation(value ="修改學生信息接口", notes ="返回success或者是fail")@PostMapping(value ="/updStudent", produces ="application/json")@ResponseBodypublicString updStudent(@RequestBodyStudent std) {? ? ? ? logger.info(">>>>>>intp mvc1->updStudent");? ? ? ? logger.info(">>>>>>name->"+ std.getName() +"? age->"+ std.getAge());return"success";? ? }}

我們有一個vue端的axios提交如下:

/src/utils/request.js

importaxiosfrom'axios'axios.interceptors.response.use(response=>{constdata = response.dataconsole.log(data)? },? error => {console.log('error', error)? })exportconstrequest = axios

HelloWorld.vue

跨域訪問import{request}from'@/utils/request.js'exportdefault{name:'HelloWorld',methods: {? ? updateStudent () {? ? ? request.post('http://localhost:9081/demo/updStudent', {'name':'abc','age':10})? ? }? }}

運行后,我們點了一下這個“按鈕”,然后我們在瀏覽器的web console得到了如下這樣的“跨域不允許”的報錯

已攔截跨源請求:同源策略禁止讀取位于?http://localhost:9081/demo/updStudent?的遠程資源。(原因:CORS 頭缺少 'Access-Control-Allow-Origin')。狀態(tài)碼:403。

錯誤的做法來了

/**

* 系統(tǒng)項目名稱 org.mk.demo.skypayment.config.webmvc WebMvcConfig.java

*

* Feb 21, 2022-10:30:19 AM 2022XX公司-版權(quán)所有

*

*/package org.mk.demo.config;importjava.util.ArrayList;importjava.util.Collections;importjava.util.List;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.web.cors.CorsConfiguration;importorg.springframework.web.cors.UrlBasedCorsConfigurationSource;importorg.springframework.web.filter.CorsFilter;importorg.springframework.web.servlet.config.annotation.CorsRegistry;importorg.springframework.web.servlet.config.annotation.WebMvcConfigurer;/**

*

* WebMvcConfig

*

*

* Feb 21, 2022 10:30:19 AM

*

* @version 1.0.0

*

*/@ConfigurationpublicclassWebMvcConfigimplementsWebMvcConfigurer{/**? ? * 跨域配置? ? */@Value("${project.basePath}")? ? privateStringbasePath;@Beanpublic CorsFilter corsFilter() {? ? ? ? UrlBasedCorsConfigurationSource source =newUrlBasedCorsConfigurationSource();? ? ? ? CorsConfiguration config =newCorsConfiguration();? ? ? ? config.setAllowCredentials(true);// 允許訪問的客戶端域名List allowedOriginPatterns =newArrayList<>();? ? ? ? allowedOriginPatterns.add("*");? ? ? ? config.setAllowedOrigins(allowedOriginPatterns);// 允許服務(wù)端訪問的客戶端請求頭config.addAllowedHeader("*");// 允許訪問的方法名,GET POST等config.addAllowedMethod("*");// 對接口配置跨域設(shè)置source.registerCorsConfiguration("/**", config);returnnewCorsFilter(source);? ? }}

改完后我們再去點一下vue端的按鈕,哎,請求正常進來了,好了,完事了,上生產(chǎn)了。

然后生產(chǎn)生產(chǎn),定期有安全掃描,每年還有等保資質(zhì)審核,等保不過,你網(wǎng)站也別開了就,直接到時可以找個電子廠上班了哈。

一看,哎呀。。。到處API都有這個,然后此時再一看我們的商城相關(guān)的系統(tǒng)已經(jīng)成下面這樣了

任何一根API的改動,就得來一次回歸測試。。。一般來說比如說中臺系統(tǒng),幾十個模塊。。。幾千個API,這個改大了。

不改嗎。。。如梗在咽喉,唉。。。

正確的做法

因此,我們在一開始碰到這種問題時就需要引起注意,這邊只教各位對的做法。而不是簡單的什么后臺來一句:allow(*),網(wǎng)上90%以上的教程都這種,?全是錯的?!

/**

* 系統(tǒng)項目名稱 org.mk.demo.skypayment.config.webmvc WebMvcConfig.java

*

* Feb 21, 2022-10:30:19 AM 2022XX公司-版權(quán)所有

*

*/package org.mk.demo.config;importjava.util.ArrayList;importjava.util.Collections;importjava.util.List;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.web.cors.CorsConfiguration;importorg.springframework.web.cors.UrlBasedCorsConfigurationSource;importorg.springframework.web.filter.CorsFilter;importorg.springframework.web.servlet.config.annotation.CorsRegistry;importorg.springframework.web.servlet.config.annotation.WebMvcConfigurer;/**

*

* WebMvcConfig

*

*

* Feb 21, 2022 10:30:19 AM

*

* @version 1.0.0

*

*/@ConfigurationpublicclassWebMvcConfigimplementsWebMvcConfigurer{/**

? ? * 跨域配置

? ? */@BeanpublicCorsFiltercorsFilter() {UrlBasedCorsConfigurationSourcesource = newUrlBasedCorsConfigurationSource();CorsConfigurationconfig = newCorsConfiguration();? ? ? ? config.setAllowCredentials(true);// 允許訪問的客戶端域名List allowedOriginPatterns = newArrayList<>();? ? ? ? allowedOriginPatterns.add(basePath);//config.setAllowedOriginPatterns(allowedOriginPatterns);config.setAllowedOrigins(allowedOriginPatterns);// 允許服務(wù)端訪問的客戶端請求頭config.addAllowedHeader("*");// 允許訪問的方法名,GET POST等config.addAllowedMethod("*");// 對接口配置跨域設(shè)置source.registerCorsConfiguration("/**", config);returnnewCorsFilter(source);? ? }}

此處的這一句:

List<String> allowedOriginPatterns = new ArrayList<>();

這一句話就是把你允許訪問后臺的域名一個個加進去,而我們在設(shè)計上應該如下操作:

把允許的訪問的域名,一個個加到以下這個List<String>中,可以用一個mongoDb的collection存所有的“被允許的域名”;

然后把這個List給到config.setAllowedOrigins(allowedOriginPatterns);

最后,以上代碼適合spring boot 2.1~2.3,對于2.4及以后版本上述的config.setAllowedOrigins要寫成“config.setAllowedOriginPatterns(allowedOriginPatterns);”

我們來看,正確設(shè)置了跨域后的訪問吧。

首先,我們在.yml里配置一個允許的跨域訪問(這塊我為了演示因此配在.yml文件里了,各位生產(chǎn)上一定要按照我的核心設(shè)計來做這件事以便于應用上擴展性更好)。

server:port:9081tomcat:max-http-post-size: -1max-http-header-size:10240000spring:application:name: mvc1servlet:multipart:max-file-size:10MBmax-request-size:10MBswagger:enable: falseproject:basePath:http://localhost:8080

/**

* 系統(tǒng)項目名稱 org.mk.demo.skypayment.config.webmvc WebMvcConfig.java

*

* Feb 21, 2022-10:30:19 AM 2022XX公司-版權(quán)所有

*

*/package org.mk.demo.config;importjava.util.ArrayList;importjava.util.Collections;importjava.util.List;importorg.springframework.beans.factory.annotation.Value;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importorg.springframework.web.cors.CorsConfiguration;importorg.springframework.web.cors.UrlBasedCorsConfigurationSource;importorg.springframework.web.filter.CorsFilter;importorg.springframework.web.servlet.config.annotation.CorsRegistry;importorg.springframework.web.servlet.config.annotation.WebMvcConfigurer;/**

*

* WebMvcConfig

*

*

* Feb 21, 2022 10:30:19 AM

*

* @version 1.0.0

*

*/@ConfigurationpublicclassWebMvcConfigimplementsWebMvcConfigurer{/**? ? * 跨域配置? ? */@Value("${project.basePath}")? ? privateStringbasePath;@Beanpublic CorsFilter corsFilter() {? ? ? ? UrlBasedCorsConfigurationSource source =newUrlBasedCorsConfigurationSource();? ? ? ? CorsConfiguration config =newCorsConfiguration();? ? ? ? config.setAllowCredentials(true);// 允許訪問的客戶端域名List allowedOriginPatterns =newArrayList<>();? ? ? ? allowedOriginPatterns.add(basePath);// config.setAllowedOriginPatterns(allowedOriginPatterns);config.setAllowedOrigins(allowedOriginPatterns);// config.addAllowedOrigin(serverPort);// 允許服務(wù)端訪問的客戶端請求頭config.addAllowedHeader("*");// 允許訪問的方法名,GET POST等config.addAllowedMethod("*");// 對接口配置跨域設(shè)置source.registerCorsConfiguration("/**", config);returnnewCorsFilter(source);? ? }}

我們在vue上點一下原來這個按鈕,前端什么都不需要動。

看,后臺請求進來了。

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

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

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