Spring Security 02 - Security Context? 從哪來?

上回我們說了SecurityContextHolder主要在做什麼,這回主要討論的是,SecurityContext到底是何方神聖,它從何而來。 SecurityContext它作為 Spring Security 核心中的一部分,它的作用可說是非常重要的。我們來看看SecurityContext的源碼。 public interface SecurityContext extends Serializable { /** * 獲取當前已驗證的身分或驗證請求令牌 * * @return the <code>Authentication</code> or <code>null</code> if no authentication * information is available */ Authentication getAuthentication(); /** * 改變目前已驗證的身分或刪除驗證資料 * * @param authentication the new <code>Authentication</code> token, or * <code>null</code> if no further authentication information should be stored */ void setAuthentication(Authentication authentication); } 可以看到SecurityContext主要是在管理Authentication的物件,那這個Authentication主要是存放當前使用者的身分(廢話)、存放是否已驗證以及取得目前使用者擁有的權限。 那 SecurityContext 從何而來呢? 同個包內的SecurityContextImpl就是它的實現,裡面都是很基本的邏輯,這次就不放了,可從官方GitHub找到相關源代碼。 那如何在不同request之間保存SecurityContext呢? 在Spring Security主要有兩個在不同request之間保存SecurityContext的策略,這邊簡單介紹一下,兩者都是ServerSecurityContextRepository的實現。 NoOpServerSecurityContextRepository: 很廢,當你叫它保存的時候它不會理你,左耳進右耳出,然後你問他那個東西在哪,它會直接說"我不知道,你有跟我講過嗎?",通常用於無狀態(Stateless)驗證,例如:httpBasic。 WebSessionServerSecurityContextRepository: 好學生,你叫它保存的時候,它會幫你做三件事,1. 取得當前Session -> 2....

October 8, 2020 · 1 min · Aitay

Spring Security 01 - 關於 ReactiveSecurityContextHolder 的一兩件事

Spring Security對於寫過Spring Boot的人應該是再熟悉不過了,這篇文主要紀錄我對於 ReactiveSecurityContextHolder的理解,原始碼版本為5.4.0-RC1。 在聊原始碼前,我想先聊一下Context到底是什麼。 Context,中文譯作「上下文」,我對於上下文的理解就是物件作用的環境。 打個比方,假設現在有一個物件叫做Weather,而假設Weather物件會有下雨、晴朗這兩種狀態,且EarthContext封裝其物件或者是強制其改變為某種狀態時,則可以說Weather的上下文是EarthContext。 對於Spring Security來說,SecurityContext就是整個Spring Security應用的上下文。 而SecurityContextHolder就是單純保存這個上下文而存在的。 在傳統Servlet應用SecurityContextHolder是存在多種保存上下文的策略,比方說GlobalSecurityContextHolderStrategy、InheritableThreadLocalSecurityContextHolderStrategy跟ThreadLocalSecurityContextHolderStrategy,但在ReactiveSecurityContextHolder中,並沒有多種策略去保存SecurityContext,唯一保存上下文的方法就是透過Reactor的上下文。 以下為個人部分翻譯的源碼: public class ReactiveSecurityContextHolder { private static final Class<?> SECURITY_CONTEXT_KEY = SecurityContext.class; /** * 從 Reactor {@link Context} 取得 {@code Mono<SecurityContext>} * @return 回傳 {@code Mono<SecurityContext>} */ public static Mono<SecurityContext> getContext() { // 從Reactor的上下文中取得SecurityContext return Mono.subscriberContext() .filter( c -> c.hasKey(SECURITY_CONTEXT_KEY)) .flatMap( c-> c.<Mono<SecurityContext>>get(SECURITY_CONTEXT_KEY)); } /** * 從 Reactor {@link Context} 清除 {@code Mono<SecurityContext>} * @return 清除Reactor上下文,並回傳一個 Mono<Void>,若清除失敗,則報錯。 */ public static Function<Context, Context> clearContext() { // 從Reactor的上下文中刪除SecurityContext return context -> context....

October 6, 2020 · 1 min · Aitay

ヨルシカ - 花人局【翻譯】

歌曲連結[Youtube Music] さよならを置いて僕に花もたせ 拋下一句再見就離開的妳為我留下了一朵花 覚束ぬままに夜が明けて 在沒有意識的情況下迎來了黎明 誰もいない部屋で起きた 於空無一人的房間裡醒來的我 その温もり一つ残して 身旁僅殘留一絲溫暖 昨日の夜のことは少しも覚えてないけれど 雖然一點也記不起來昨天晚上發生過的事情 他に誰かが居た、そんな気がただしている 也只是感覺昨晚似乎還有誰在的樣子 二日酔いが残る頭は回っちゃいないけれど 雖然腦袋還因為宿醉而無法好好運作 わからないままでもまぁ、それはそれでも綺麗だ 但是如果就這樣記不起來的話、也倒是有其美麗之處 洗面台の歯ブラシ、誰かのコップ、棚の化粧水 洗手台上的牙刷、不知道是誰的杯子、架子上的化妝水 覚えのない物ばかりだ 看到的盡是些沒有印象的物品 枕は花の匂いがする 枕頭上傳來了花的香味 さよならを置いて僕に花もたせ 拋下一句再見就離開的妳為我留下了一朵花 覚束ぬままに夜が明けて 在沒有意識的情況下迎來了黎明 誰もいない部屋で起きる 於空無一人的房間裡醒來的我 その温もり一つ残して 身旁僅殘留一絲溫暖 昨日の夜のことはそこまで覚えてないけれど 雖然記不清楚昨天晚上發生過的事情 美人局を疑う、そんな気もしないでいる 也懷疑過是一場仙人跳,但卻沒有那種感覺 二日酔いも醒めた頭で考えていたけど 儘管已經用宿醉過後的腦袋思考過了 わからないままでもいい 但卻覺得就這樣想不起來也不錯 むしろその方がいい 倒不如說這樣才是最好的 窓際咲くラベンダー、汚れたシンク、編み掛けのマフラー 窗邊盛開的薰衣草、骯髒的水槽、編織後掛著的圍巾 覚えのない事ばかりだ 想起來的淨是一些不記得的事情 部屋には春の匂いがする 房間裡飄散著春天的氣息 浮雲掴むような花人局 仿佛抓住浮雲一般的花人局 誰も来ないまま日が暮れて 等不到誰的回來,就這樣天色漸漸暗下 夕陽の差した窓一つ 只留下一扇照進夕陽餘暉的窗戶 何も知らない僕を残して 和一無所知的我 昨日の夜のことも本当は少し覚えてるんだ 昨天晚上發生過的事情其實還記得一些 貴方の居ない暮らし、それが続くことも 沒有了妳的生活、還是會繼續生活下去 今でもこの頭一つで考えているばかり 至今還是一股腦地去想著 花一つ持たせて消えた貴方のこと 留下一朵花後消逝的妳的事情 明日にはきっと戻ってくる 明天妳一定會回來的吧 何気ない顔で帰ってくる 一定會帶著若無其事的表情回來的吧 今にドアが開いて聞こえる 甚至現在把門打開好像就能聽到妳說 ごめんね、遅くなったって 「對不起、我遲到了」 言葉だけをずっと待っている 這樣的話語我一直在等待著 夕焼けをじっと待っている 靜靜地等待著晚霞 忘れてしまう前に花描け 在忘卻之前把花朵描繪出來吧 今日も一人また夜が来て 今日也是獨自迎來夜晚 誰もいない部屋で眠る 我能在空無一人的房間裡睡著 その温もり、僕に残して 是因為我還殘存著那份溫暖 馬鹿みたいに愛は花もたせ 把名譽拱手讓人的像笨蛋一樣的愛 この部屋にもまた春が来て 才能讓這個房間再次迎來春天 貴方のいない街を生きる 我能生活在沒有妳的街道上 その温もり、僕に残して 是因為我還殘存著那份溫暖 僕にひとつ、花を残して 給我留下一朵花的那份溫暖 言葉だけをずっと待っている 這樣的話語我一直在等待著 夕焼けをじっと待っている 靜靜地等待著晚霞 可供轉載,標明出處

August 13, 2020 · 1 min · Aitay

回頭看當年技藝競賽題目

這幾天在準備上課教材,所以回頭做了一些技藝競賽的歷屆考題 我還記得以前有一題在我高中的時候花了將近幾天在想答案,回去重做發現…… 什麼鬼???不就只是遞迴而已… 重寫後發現猜想真的是對的,可能當時練習的時候頭腦有點混亂吧,原本是寫了三、四個迴圈在裡面跑,有些數字還會直接當掉不給動只能說當時太笨了… 希望回去學校教的時候學弟不要太聰明,不然當時的我會站不了檯面阿阿阿。 因為太丟人了程式碼就不放上來了。

August 5, 2020 · 1 min · Aitay

Parsing A Boolean Expression

題目要求是要輸入一個運算式回傳該運算式的結果 有下列規則 “t”,代表為 True “f”,代表為 False “!(expr)",表示將expr得出的布林值反向 “&(expr1,expr2,…)",表示將所有expr{num}做AND “|(expr1,expr2,…)",表示將所有expr{num}做OR 馬上進入程式碼撰寫的部分,主要是以遞迴解決 我的想法應該算蠻差的,效能那些部分都不能強求,所以僅放上來做參考,歡迎底下討論 class Solution { companion object{ // 運算子列表 val operator = arrayOf('!', '&', '|') } fun parseBoolExpr(expression: String): Boolean { // 如果運算式為空,回傳 `False` if (expression.isEmpty()) return false return expr(expression) } fun expr(expression: String): Boolean{ // 如果運算式的首個元素不包含於運算子列表(!、&、|),回傳 `False` if (!operator.contains(expression[0])) return false // 取得運算子 val mod = expression[0] // 檢查運算子後的下一個字元是否為 `(` val optStart = if(expression[1] == '(') 1 else throw RuntimeException("not valid pattern") // 檢查運算式的最後一個字源是否為 `)` val optEnd = if(expression[expression....

August 3, 2020 · 2 min · Aitay