hello 各位小夥伴,國慶節終于過完啦,松哥也回來啦,今天開始咱們繼續發幹貨!
關于 Spring Security,松哥之前發過多篇文章和大家聊聊這個安全架構的使用:
- 手把手帶你入門 Spring Security!
- Spring Security 登入添加驗證碼
- SpringSecurity 登入使用 JSON 格式資料
- Spring Security 中的角色繼承問題
- Spring Security 中使用 JWT!
- Spring Security 結合 OAuth2
不過,今天要和小夥伴們聊一聊 Spring Security 中的另外一個問題,那就是在 Spring Security 中未獲認證的請求預設會重定向到登入頁,但是在前後端分離的登入中,這個預設行為則顯得非常不合适,今天我們主要來看看如何實作未獲認證的請求直接傳回 JSON ,而不是重定向到登入頁面。
前置知識
這裡關于 Spring Security 的基本用法我就不再贅述了,如果小夥伴們不了解,可以參考上面的 6 篇文章。
大家知道,在自定義 Spring Security 配置的時候,有這樣幾個屬性:
這裡有兩個比較重要的屬性:
- loginProcessingUrl:這個表示配置處理登入請求的接口位址,例如你是表單登入,那麼 form 表單中 action 的值就是這裡填的值。
- loginPage:這個表示登入頁的位址,例如當你通路一個需要登入後才能通路的資源時,系統就會自動給你通過重定向跳轉到這個頁面上來。
這種配置在前後端不分的登入中是沒有問題的,在前後端分離的登入中,這種配置就有問題了。我舉個簡單的例子,例如我想通路
/hello
接口,但是這個接口需要登入之後才能通路,我現在沒有登入就直接去通路這個接口了,那麼系統會給我傳回 302,讓我去登入頁面,在前後端分離中,我的後端一般是沒有登入頁面的,就是一個提示 JSON,例如下面這樣:
完整代碼大家可以參考我的微人事項目。
也就是說,當我沒有登入直接去通路
/hello
這個接口的時候,我會看到上面這段 JSON 字元串。在前後端分離開發中,這個看起來沒問題(後端不再做頁面跳轉,無論發生什麼都是傳回 JSON)。但是問題就出在這裡,系統預設的跳轉是一個重定向,就是說當你通路
/hello
的時候,服務端會給浏覽器傳回 302,同時響應頭中有一個 Location 字段,它的值為
http://localhost:8081/login
,也就是告訴浏覽器你去通路
http://localhost:8081/login
位址吧。浏覽器收到指令之後,就會直接去通路
http://localhost:8081/login
位址,如果此時是開發環境并且請求還是 Ajax 請求,就會發生跨域。因為前後端分離開發中,前端我們一般在 NodeJS 上啟動,然後前端的所有請求通過 NodeJS 做請求轉發,現在服務端直接把請求位址告訴浏覽器了,浏覽器就會直接去通路
http://localhost:8081/login
了,而不會做請求轉發了,是以就發生了跨域問題。
解決方案
很明顯,上面的問題我們不能用跨域的思路來解決,雖然這種方式看起來也能解決問題,但不是最佳方案。
如果我們的 Spring Security 在使用者未獲認證的時候去請求一個需要認證後才能請求的資料,此時不給使用者重定向,而是直接就傳回一個 JSON,告訴使用者這個請求需要認證之後才能發起,就不會有上面的事情了。
這裡就涉及到 Spring Security 中的一個接口
AuthenticationEntryPoint
,該接口有一個實作類:
LoginUrlAuthenticationEntryPoint
,該類中有一個方法
commence
,如下:
首先我們從這個方法的注釋中就可以看出,這個方法是用來決定到底是要重定向還是要 forward,通過 Debug 追蹤,我們發現預設情況下 useForward 的值為 false,是以請求走進了重定向。
那麼我們解決問題的思路很簡單,直接重寫這個方法,在方法中傳回 JSON 即可,不再做重定向操作,具體配置如下:
在 Spring Security 的配置中加上自定義的
AuthenticationEntryPoint
處理方法,該方法中直接傳回相應的 JSON 提示即可。這樣,如果使用者再去直接通路一個需要認證之後才可以通路的請求,就不會發生重定向操作了,服務端會直接給浏覽器一個 JSON 提示,浏覽器收到 JSON 之後,該幹嘛幹嘛。
結語
好了,一個小小的重定向問題和小夥伴們分享下,不知道大家有沒有看懂呢?這也是我最近在重構微人事的時候遇到的問題。預計 11 月份,微人事的 Spring Boot 版本會更新到目前最新版,請小夥伴們留意哦。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiYWan5iMkZGN2ETMmdTMjdDN4MGMhRjZlNWM5IzNjRGO1Y2M38CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.gif)
1、使用 Nginx 部署前後端分離項目,解決跨域問題
2、喜大普奔,兩個開源的 Spring Boot + Vue 前後端分離項目可以線上體驗了
3、Spring Boot 整合 OAuth2,松哥手把手教你!
4、一個小小的裡程碑!啥也不說了,簽名書奉上!
5、七個開源的 Spring Boot 前後端分離項目,一定要收藏!
6、一鍵部署 Spring Boot 到遠端 Docker 容器,就是這麼秀!
7、完結撒花!129 集 21 個小時,松哥自制的 Spring Boot2 系列視訊教程殺青啦!
8、40 篇原創幹貨,帶你進入 Spring Boot 殿堂!
9、Spring Boot 中的同一個 Bug,竟然把我坑了兩次!
喜歡就點個"在看"呗^_^