spring security下的跨域問題

什么是CORS藏否?

問題來源

web前后端工程的分離门驾,給傳統(tǒng)的web一體式開發(fā)或前后端工程師揉在一塊(前后端代碼在一個工程下,尤其前端開發(fā)需要在本地啟動后臺服務(wù)娃善,后臺也會被前端代碼分散注意力)的尷尬情況提出了解決方案论衍,同時也引來了一些不可避免的問題,而跨域問題就是其中之一会放。
設(shè)想一下饲齐,前端工程師正在開發(fā)登錄頁面的UI,基于nodejs(或基于nodejs的快速開發(fā)工具咧最,如vue-cli)捂人,可以很容易的在本地啟動一個服務(wù)端口用于頁面的開發(fā)。此時矢沿,前端代碼需要調(diào)用后臺的登錄接口做測試滥搭,于是將參考API文檔,拿到了登錄接口的相關(guān)信息(url=/login捣鲸,params={})準備調(diào)用后臺接口測試瑟匆,這時問題來了,如何遠程調(diào)用后臺接口栽惶,肯定不可能只配置一下axios(http工具)的baseUrl就完事愁溜,還要找到后臺的同學,請他將后臺web服務(wù)設(shè)置允許跨域請求外厂,不然你就會在瀏覽器控制臺收到類似下面的警告:

OPTIONS http://localhost:8088/login 404
Access to XMLHttpRequest at 'http://localhost:8088/login' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

解決方案

1冕象、讓前端工程師安裝nginx,設(shè)置http請求轉(zhuǎn)發(fā)汁蝶,這樣可以繞過瀏覽器跨域警告(不推薦渐扮,因為每一個前端開發(fā)都需要安裝nginx论悴,還需要學習配置nginx,透明度不夠)
2墓律、后端服務(wù)開啟跨域請求設(shè)置(推薦膀估,對于前端來說基本是透明的)

spring security如何解決跨域問題

環(huán)境說明
  • java8
  • spring boot 2.2.0.RELEASE
官方說明

通過官方文檔可以知道,配置是在spring security中耻讽,但是最終還是會交給spring mvc去處理
spring官方說明

繞坑察纯!

最開始以為這是很常見的問題,應(yīng)該很好解決齐饮,于是隨便baidu了一下捐寥,的確有一大堆相關(guān)的案例解決方案,基本思路和代碼大概有三種祖驱,這里就不詳細說了握恳,請自行百度相關(guān)問題。
百度出來的結(jié)果都大概看了下捺僻,也都試過乡洼,沒有一個可行,不知道是不是我的版本太新的原因匕坯。最后只好查看官方文檔(看英文有點慢束昵,需要加強啊)葛峻,意外的是锹雏,這次官方給出的說明很簡單也很直接(show you the best practice code),但是也沒有解決問題术奖。于是再次結(jié)合百度出來的結(jié)果礁遵,然后分析瀏覽器給出的錯誤警告內(nèi)容,將官方代碼稍作了調(diào)整后采记,跨域配置才終于生效佣耐。

code

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private ActiveProfile activeProfile;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
         //你的其他配置
        ......
        //dev config
        if (activeProfile.isDev()) {
            //允許跨域請求
            // by default uses a Bean by the name of corsConfigurationSource(官方說明,使下面配置的bean生效)
            http.cors(Customizer.withDefaults());
        }
    }

    @Profile("dev")
    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.addAllowedOrigin("*");//修改為添加而不是設(shè)置唧龄,* 最好改為實際的需要兼砖,我這是非生產(chǎn)配置,所以粗暴了一點
        configuration.addAllowedMethod("*");//修改為添加而不是設(shè)置
        configuration.addAllowedHeader("*");//這里很重要既棺,起碼需要允許 Access-Control-Allow-Origin
        configuration.setAllowCredentials(true);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

還沒有結(jié)束

上述配置沒有問題讽挟,到目前為止,服務(wù)器端已經(jīng)完全支持跨域請求了丸冕,但是的確還沒有結(jié)束耽梅。應(yīng)為筆者在測試過程中又遇到了坑,下面來具體談一談晨仑。
提示:如果你的前端用到了axios,一定注意axios雖然默認的content-type='application/x-www-form-urlencoded',但是body中的參數(shù)是以json字符串的格式提交的洪己,請使用 URLSearchParams 封裝妥凳,如下:

const params = new URLSearchParams();
params.append('param1', 'value1');
params.append('param2', 'value2');
axios.post('/foo', params);

回到正題,基于上面的配置答捕,現(xiàn)在登錄已經(jīng)沒有了問題逝钥,但是在跨域訪問api時會發(fā)現(xiàn)接口返回302,接口被重定向的原因經(jīng)過查看spring security的dubg日志發(fā)現(xiàn)是因為該接口是匿名訪問拱镐,也就是說你未登錄艘款。但是剛才也的確登錄成功了,而且瀏覽器cookie當中還有我們的sessionid沃琅,再仔細觀察發(fā)現(xiàn)api接口發(fā)送未帶cookie哗咆,這才是接口被解決的真正原因而并非真的沒有登錄。查看官方對于跨域的說明后益眉,發(fā)現(xiàn)跨域訪問默認是不會攜帶cookie的晌柬,除非你設(shè)置參數(shù)告訴瀏覽器我要帶cookie去跨域訪問資源,代碼如下:

//全局配置郭脂,告訴瀏覽器無論如何都要攜帶cookie去請求資源
axios.defaults.withCredentials=true

或者

                        //也可以在單獨的請求顯示指明 withCredentials=true
                        self.axios({
                            method: 'post',
                            url: '/api/getSomething',
                            data: params,
                            withCredentials: true//
                        }).then(function (rep) {
                            //your code......
                        });

如果你使用的是webpack或者基于webpack或nodejs構(gòu)建的開發(fā)工具(如:vue-cli)
你可以通過配置代理年碘,這樣的好處是你可以省略對 withCredentials 參數(shù)的配置,例:

//vue.config.js
module.exports = {
  devServer: {
    proxy: 'http://localhost:4000'
  }
}

關(guān)于該配置的詳細說明參考:
http-proxy-middleware

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末展鸡,一起剝皮案震驚了整個濱河市屿衅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌莹弊,老刑警劉巖涤久,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異箱硕,居然都是意外死亡拴竹,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門剧罩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來栓拜,“玉大人,你說我怎么就攤上這事惠昔∧挥耄” “怎么了?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵镇防,是天一觀的道長啦鸣。 經(jīng)常有香客問我,道長来氧,這世上最難降的妖魔是什么诫给? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任香拉,我火速辦了婚禮,結(jié)果婚禮上中狂,老公的妹妹穿的比我還像新娘凫碌。我一直安慰自己,他們只是感情好胃榕,可當我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布盛险。 她就那樣靜靜地躺著,像睡著了一般勋又。 火紅的嫁衣襯著肌膚如雪苦掘。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天楔壤,我揣著相機與錄音鹤啡,去河邊找鬼。 笑死挺邀,一個胖子當著我的面吹牛揉忘,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播端铛,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼泣矛,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了禾蚕?” 一聲冷哼從身側(cè)響起您朽,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎换淆,沒想到半個月后哗总,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡倍试,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年讯屈,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片县习。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡涮母,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出躁愿,到底是詐尸還是另有隱情叛本,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布彤钟,位于F島的核電站来候,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏逸雹。R本人自食惡果不足惜营搅,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一云挟、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧转质,春花似錦植锉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽狮暑。三九已至鸡挠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間搬男,已是汗流浹背拣展。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留缔逛,地道東北人备埃。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像褐奴,于是被迫代替她去往敵國和親按脚。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,486評論 2 348