搜尋

搜尋結果

Spring Boot 05 - 為 http json api 加入登入要求
科技新知
MacauYeah・2024-07-02

本節,我們將為之前的http服務,加入認證機制,只有在資料庫現存的用戶可以登入及訪問我們的json api。 下戴模版 慣例,我們用Spring Initializr Maven 下載模版,Dependency主要選擇 Spring Web Spring Boot DevTools Spring Security Controller 跟上節一樣,我們起一個Controller,為簡化測試,我們只做http GET api。 由於本blog對於Source Code的顯示不太友好,有需要看source code的,請到Github查看 srcmainjavaiogithubmacauyeahspringboottutorialspringbootwebapidatacontrollerHomeController.java import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMappingquot;apiquot; public class HomeController @GetMappingquot;someRecorduuidquot; public Map readSomeRecord@PathVariable String uuid return Map.ofquot;retquot;, quot;your uuidquot; uuid; 準備我們的test case,但這次我們預期它應該要出現登入失敗的結果。 srctestjavaiogithubmacauyeahspringboottutorialspringbootwebapidatacontrollerHomeControllerTest.java @SpringBootTest @AutoConfigureMockMvc public class HomeControllerTest @Autowired private MockMvc mockMvc; @Test void testNoLogin throws Exception RequestBuilder requestBuilder = MockMvcRequestBuilders.getquot;apisomeRecord1234quot; .contentTypeMediaType.APPLICATION_JSON; this.mockMvc.performrequestBuilder .andExpectMockMvcResultMatchers.status.is4xxClientError .andExpectMockMvcResultMatchers.jsonPathquot;$.retquot;.doesNotExist .andDoMockMvcResultHandlers.print; 在我們執行上述的測試,test case 成功過了。我們的基本設定跟上一節其實沒有多大改動,為何現在http api會回傳狀態 401? 那是因為我們在依賴中加了,Spring Security,它配合了Spring Web,就會自動為所有api加入權限檢測。我們的測試中,沒有任何用戶登入,當然會出現 http 401。為了讓我們可以好好管理誰可以使用api,我們就來設定一定Security。 我們加一個WebSecurityConfig.java,暫時指定所有的訪問路徑都必需有USER權限,並且用 http basic的方式登入。 srcmainjavaiogithubmacauyeahspringboottutorialspringbootwebapidataconfigWebSecurityConfig.java import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.Customizer; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; @Configuration @EnableWebSecurity public class WebSecurityConfig @Bean SecurityFilterChain securityFilterChainHttpSecurity http throws Exception http.authorizeHttpRequestsauthorizeHttpRequests gt; authorizeHttpRequests.requestMatchersquot;quot;.hasRolequot;USERquot;; 所有的訪問路徑都必需有USER權限 ; http.httpBasicCustomizer.withDefaults; 使用http basic作為登入認證的方式 return http.build; 上述例子,只是擋了沒有權限的人,我們還需要讓有登入身份的用戶可以成得取限User權限。 我們繼續修改,WebSecurityConfig,加入只在記憶體有效的InMemoryUser import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.provisioning.InMemoryUserDetailsManager; public class WebSecurityConfig .. @Bean public PasswordEncoder passwordEncoder return new BCryptPasswordEncoder; 我們的密碼不應該明文儲,比較保險,我們使用BCrypt演算法,為密碼做單向加密。 @Bean public UserDetailsService userDetailsService UserDetails user = User.withUsernamequot;adminquot; .passwordpasswordEncoder.encodequot;passquot; .rolesquot;USERquot;.build; 我們在記憶中體,加入一個測試用的User,它的名字為admin,密碼為pass,權限為User return new InMemoryUserDetailsManageruser; 然後加入新的測試,直接模擬Role。結果是通過的。 srctestjavaiogithubmacauyeahspringboottutorialspringbootwebapidatacontrollerHomeControllerTest.java @Test void testLoginWithRoles throws Exception RequestBuilder requestBuilder = MockMvcRequestBuilders.getquot;apisomeRecord1234quot; .contentTypeMediaType.APPLICATION_JSON.with SecurityMockMvcRequestPostProcessors.userquot;someonequot; .rolesquot;USERquot;, quot;ADMINquot;; 沒有使用密碼,只使用Role this.mockMvc.performrequestBuilder .andExpectMockMvcResultMatchers.status.is2xxSuccessful .andExpectMockMvcResultMatchers.jsonPathquot;$.retquot;.valuequot;your uuid1234quot; .andDoMockMvcResultHandlers.print; 再來一個測試,改用密碼登入,分別輸入錯的和正確的密碼。 @Test void testLoginWithWrongPasswordAndNoRole throws Exception RequestBuilder requestBuilder = MockMvcRequestBuilders.getquot;apisomeRecord1234quot; .headerquot;Authorizationquot;, quot;Basic randompassquot; 輸入錯的密碼,應該回傳http 401 Unauthorized .contentTypeMediaType.APPLICATION_JSON; this.mockMvc.performrequestBuilder .andExpectMockMvcResultMatchers.status.is4xxClientError .andDoMockMvcResultHandlers.print; @Test void testLoginWithPassword throws Exception RequestBuilder requestBuilder = MockMvcRequestBuilders.getquot;apisomeRecord1234quot; .headerquot;Authorizationquot;, quot;Basic YWRtaW46cGFzcw==quot; http basic 就是把 adminpass 轉成base64 .contentTypeMediaType.APPLICATION_JSON; this.mockMvc.performrequestBuilder .andExpectMockMvcResultMatchers.status.is2xxSuccessful .andExpectMockMvcResultMatchers.jsonPathquot;$.retquot;.valuequot;your uuid1234quot; .andDoMockMvcResultHandlers.print; 最後,當然是正確的密碼才能通過。若果大家還是半信半疑,我們可以跑起真的正服務(IDE RUN或mvn springbootrun),然後用curl去試。 curl httplocalhost8080apisomeRecord1234 failed with 401 curl u quot;adminpassquot; httplocalhost8080apisomeRecord1234 successed 使用SQL Database讀取用戶登入資訊 一般而言,我們不可能把所有用戶登資訊打在InMemoryUser中,通常背後有一個資料庫儲存所有的用戶資訊,我們在登入時,讀取它來做對比檢證。 為此,我們在maven中,加入 Spring Data JPA h2 database (或任何你的資料庫,如mysql 、 sql server) 最後一步,我們把InMemoryUser去掉,改為從資料庫讀取。因為原始碼太多,就不全部貼上。最主要的是WebSecurityConfig.java要關掉之前的UserDetailsService,改為提供一個UserServiceImpl類,它會實現UserDetailsService的功能。 @Configuration @EnableWebSecurity public class WebSecurityConfig 把原來的Bean先變成註解,其他不變 @Bean public UserDetailsService userDetailsService UserDetails user = User.withUsernamequot;adminquot; .passwordpasswordEncoder.encodequot;passquot; .rolesquot;USERquot;.build; return new InMemoryUserDetailsManageruser; springboottutorialspringbootwebapidatasrcmainjavaiogithubmacauyeahspringboottutorialspringbootwebapidataconfigUserServiceImpl.java other import import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.password.PasswordEncoder; @Service public class UserServiceImpl implements UserDetailsService @Autowired PasswordEncoder passwordEncoder; @Autowired UserRepo userRepo; @Override public UserDetails loadUserByUsernameString username throws UsernameNotFoundException 因為我們資料庫沒有資料,為了方便測試密碼的加密,我們在java code上直接插入一筆資料。 UserEntity defaultUser = new UserEntity; defaultUser.setUsernamequot;adminquot;; defaultUser.setPasswordpasswordEncoder.encodequot;passquot;; defaultUser.setRolequot;USERquot;; defaultUser.setUuidUUID.randomUUID.toString; userRepo.savedefaultUser; 上述為測試用插入資料,不應該出現在正式使用環境中。 UserEntity user = userRepo.findOneByUsernameusername .orElseThrow gt; new UsernameNotFoundExceptionusername quot; not foundquot;; 找找資料庫有沒有正在登入的該名使用者username List authorities = List.ofnew SimpleGrantedAuthorityquot;ROLE_quot; user.getRole; LOG.debugquot;got user uuid, username, role from databasequot;, user.getUuid, username, user.getRole; 如果前面的 findOneByUsername 有結果回傳,我們就給它一個ROLE_XXX的權限。 return new Userusername, user.getPassword, authorities; 這裏從沒有檢查過密碼是否有匹配,全部交給Spring Security去做 springboottutorialspringbootwebapidatasrcmainjavaiogithubmacauyeahspringboottutorialspringbootwebapidataentityUserEntity.java springboottutorialspringbootwebapidatasrcmainjavaiogithubmacauyeahspringboottutorialspringbootwebapidatarepoUserRepo.java 上述段落中,筆者省略了UserEntity和UserRepo,它們只是一般的springdatajpa概念,有需要可以經文末的連結查看完全原始碼。最需要注意的,是UserEntity的password欄位,在資料庫中是以加密的方式儲存。我們在配匹登入者與資料庫記錄時,也沒有自行檢驗密碼的需要。我們只是在加密過的密碼回傳給Spring Security,Spring框架會自行把登入者輸入的密碼與加密了的密碼作比較。

釜山航空香港8週年優惠,2人同行香港/澳門飛釜山HKD1,253/MOP1,257/人起!
激安優惠
OHChance 旅遊誌・2019-05-16

釜山航空推出香港航線開航8週年優惠,2人同行價暑假都有,平均一人唔使1300值得看看,快d 孖個朋友仔去玩下水啦。 《優惠價錢(來回連稅)》*香港-釜山:HKD1,253人*澳門-釜山:MOP1,257人 優惠為必須2人同行,以上為平均每人價錢。  《出發日期及最長停留》.出發日期:5月16日至8月31日.最長停留:不限  《購票日期及方法》.購票日期:5月26日2259前.預訂方法:釜山航空官網.預訂網址:httpswww.airbusan.com  【行李資訊】#釜山航空特價票只包括手提行李10KG#加購托運行李每單程每件15KG價格為MOP294  附註:上述最低價錢為航空公司公告之最優惠價格,或本站能找到的最低價格;每一航班有否優惠票價及所存票量由航空公司決定,優惠票量有限售完即止。  價錢 Sample ndash; 澳門飛釜山2人同行來回連稅總價MOP2,514 ===== 想搵平機票去玩,即上 OH!Chance!澳燦旅行資訊 httpsohchance.info 去日本旅行買咩 JR Pass好?即上 OH!Note!小燦的旅行筆記做功課 httpsohnote.info 唔知間航空公司好唔好坐?馬上 Subscribe OH Chance Youtube 睇睇佢:httpsyoutube.comcOHChanceTravel 睇埋 Facebook 專頁 httpsfb.comohchance 第一時間獲得最新旅遊資訊!

[二維物語] 無法盡如人意的經典小說改編作 - 《日本沉沒2020》
娛樂殿堂
君尋・2020-11-30

《日本沉沒2020》是Netflix製作的原創動畫作品,改編自1973年的科幻小說《日本沉沒》。小說推出以來不單止奪下多個獎項,成為社會熱話,亦先後被多次改編成電影、電視劇和漫畫。動畫改篇則屬首次。看到標題大概可想像到故事內容,一直飽受地震、火山爆發、海嘯影響的日本,假如有一天整個沉沒並消失於地圖之上,對於世世代代居住於這個島國上的人民而言,他們應逃到哪裡?執筆之時,新聞報導日本方面即將製作全新的真人電影《日本沉沒~希望的人~》,由小栗旬、松山研一等多位知名藝人主演,證明「日本沉沒」這個題材對不同時代的日本人而言,始終具有相當的意義。 第一集的衝擊最大 不同於原作以成功預測日本沉沒的地球物理學者為主角,並以他的視角描述這場世紀災難的發生和日本的終結,《日本沉沒2020》則以一位生於相對普通的日本家庭的女高中生作為主角,講述遇上首場的大地震後,一起與家人逃生的故事,比較接近我們熟悉的西方災難電影的套路。災難電影常給觀眾一種錯覺,就是主角運氣太好。平凡的女高中生在絕望般的環境下求生理應不是簡單的事情,而且本作更強調是日本的沉沒,但旅途上予人感覺是相對順利,並在路途中遇上不少好人得到幫助。當在路上走到盡頭,突然出現一位新角色帶路。當缺乏某種資源時,碰巧再前一點的路上就找得到。在一望無際的海上飄流,也能夠被失散的同伴救起。而另一方面,同伴的加入和離隊亦過於公式化,先不說「插旗」相當明顯,當遇到某個難關只能由某個角色出面處理時,就會知道那位角色將會在該集結尾「離隊」。觀眾沒法在過程中體驗到緊湊的情節,亦無法感到與家人、同伴生離死別的情感。至於標題上刻意添加的「2020」,本意應是讓觀眾聚焦故事的背景年代,因此內容上亦強調不少現今的流行元素,如有一位同伴是知名Youtuber、主角弟弟沈迷電競,雖然是可有可無對故事無大影響,但亦加強了年輕一代觀眾的共鳴,讓人記住災難有可能隨時隨地發生。諷刺的是,在2020年考驗日本人的反而是COVID19而不是自然災害。 偶然遇到的Youtuber成為重要伙伴 整體而言,本作在敘事上存在明顯的不足,但《日本沉沒》的意義依舊能在本作找得到。缺乏天然資源、地理位置於大陸邊緣、容易遭受自然災害的日本,表面繁榮的背後其實是異常脆弱的。就算沒有如日本沉沒般的極巨大災害,單單是近年的311大震災、九州的暴雨以及多次的超強颱風的襲擊,都對日本不同地區帶來嚴重的破壞和人命傷亡。然而,就像本劇結尾一樣,災難過後,日本人總能像鳳凰一樣於浴火中重生,再次將大和民族和以及自豪的文化傳承下去。 雖然不盡如人意,但筆者依然推薦這套經典作品的改編動畫 關於二維物語 本欄目將會分享日本的動畫漫畫資訊。未必會看到主流作品的介紹,但會在這介紹的必定是值得一看的作品。 更多動畫和漫畫心得: httpsppt.ccfFXgvx

7月10日至7月16日一周鼠生肖運程
玄學星相
熊神進・2023-07-09

鼠: 【每一個發奮努力的背後,必有加倍的賞賜】 在精神上要隨時做好面臨突發疑問的準備,沉著面臨,勇於堅持,艱難僅僅是暫時的。要多收斂脾氣,凡事多忍受,防止因為脾氣方面的緣由惹出禍端。工作上不宜強出面,低調為好,關於不必要的外交活動,少參加為妙,自然能夠縫凶化吉。財運一般,不應賭博炒股,多行正道,維穩為上。吉祥方位:西方。 7月10日至7月16日一周牛生肖運程 牛: 【一個人至少擁有一個夢想有一個理由去堅強】 工作壓力比較大,很可能會遇到人為阻止或意外變故使一切的努力付諸東流。財運平平,破財跡象明顯,平時就要注意開源節流。你太在意自己的感受,會猜疑自己在對方的心中是否還不夠重要。給對方更多的關愛,你也才會得到相同的回報,愛永遠是需要相互付出的。已婚的朋友則要注意自己的桃花運了,也許並不是什麼好事。 7月10日至7月16日一周虎生肖運程 虎: 【夢是一種欲望,想是一種行動。夢想是夢與想的結晶】 在工作上應該積極進取,爭取獲得最理想額回報。感情上其實你更在乎的是家人,所以家人的意見想法好像會成為你們之間的加分或減分。財運也大幅度回升,經商者可適當根據市場的形式加大投資。此外,慎防辦公室內有女人小人製造事端,搞風搞雨,謹記少說話、多幹事,儘量防止捲進對錯之中。筆者依然建議你在包包裡擺放一件「黑岩刀」。 7月10日至7月16日一周兔生肖運程 兔: 【學會忘記痛苦,為陽光記憶騰出空間】 平時多注意積累跟上級和同事之間的友好關係,和異性同事太多牽連,容易讓人引起誤會,容易受到小人非議。桃花運佳,單身者宜好好把握機會締結良緣。不過財星化忌,涉及到金錢的活動要小心謹慎,以免上當受騙,凡事多留個心眼,不要輕易動錢。簽署檔時要加倍留意,勿太自我感覺良好,亦小心溝通和言語誤會。 7月10日至7月16日一周龍生肖運程 龍: 【不懼人言,不畏歲月】 運勢較為平穩,偶然遇到一些小的阻止也能輕鬆化解,關於盡力之後卻無法處理的疑問,不用過於糾結,應當調整好心態和狀況,回頭看時自是晴空萬里,一望而知。求職面試機會和表現都不錯。合作、競標等波折較多,可能要反反復複修改和調整,特別提醒你多點耐心,以維繫好關係為首要目標。幸運顏色 深紫色。 7月10日至7月16日一周蛇生肖運程 蛇: 【No fear of words, no fear of year】 這一周生肖蛇身體情況稍見好轉,不妨整理一下手中的事務,去偽存真,將工作中的不利因素篩選出來,儘早採取措施將其消除為好。財氣偏低迷,出資時應當擬定具體的計畫,魯莽的人永久無法取得財氣的喜愛。豪情上應順從其美,應多花時間與心思呵護感情,莫強求。本周之內很可能遇上貴人,請留心身邊的人和上司,仔細想想有甚麼方法能夠吸引別人注意自己。 7月10日至7月16日一周馬生肖運程 馬: 【While there is life there is hope】 跟上司起了口角,內心很憤憤不平,但千萬要退讓一步,否則吃虧的會是自己,到時候就算想後悔,恐怕也來不及道歉。要多注意身體,好好保護身體,才可保健康。單身者異性緣分不錯,可多借助親友力量。家長要看護好自己的孩子,平時也要注意飲食衛生,補養腎氣保護腸胃平衡。出遠門宜謹慎,備妥常備藥;簽約事務稍安勿躁,請專家陪同為佳。 7月10日至7月16日一周羊生肖運程 羊: 【愛也空,情也空,到頭全進高煙囪】 運勢積極向上,是個值得等待的日子,當時機來臨時,要自動掌握。提防身邊小人,莫要聽信讒言,留心客戶簽約內容細節。在財運運勢方面表現不錯,找父母朋友借錢是非常容易的事。工作方面遇強則強,你有好夥伴,你變得很有企圖心,最近也有一些好事發生,譬如得獎等重要性提升等等。行商買賣,薄利多銷會是好策略,業務推廣值得努力,因為辛苦有成;投資求財,見好便收。 7月10日至7月16日一周猴生肖運程 猴: 【我不等了, 就當風沒吹過, 你沒來過, 我沒愛過】 最近會對海外的事情滿上心,譬如你在規劃出國旅行的事,雖然沒有你想像中順利,不過規劃一下也滿有趣,或你本身是外商公司,跟外國人有比較多聯繫,這周可能會往返比較頻繁,因為溝通有點不順,可是會慢慢溝通到點上。財運不俗,因為本身的盡力得到的報答會讓人歡喜不已,經商者亦是坐收果實的好時機。 7月10日至7月16日一周雞生肖運程 雞: 【自己選擇的路,跪著也要把它走完】 孩子會早熟, 接觸感情火苗,家長注意正確的引導,可在文化心理藝術等方面給孩子些資源轉移孩子的情感能量。獨身者本周或許會有意中人呈現,要盡力爭取,成功的時機必將大增;身體方面要防止過於勞累,應多多歇息。對於孩子喜歡的體育文藝支持並讚賞一些。正向的引導孩子就穩重踏實的做好功課利於取的好成績。 7月10日至7月16日一周狗生肖運程 狗: 【勝也空,敗也空,人生如戲夢一通】 今星期要小心摔倒、碰撞意外,有骨折的可能,生活中該睡覺的時候也要睡覺,好的作息習慣才能夠有好的精神狀態。由於你們一直忙碌於事業而且會經常參加應酬,這就導致你們的腸胃會出現問題,所以平時需要多加注意飲食習慣,不能暴飲暴食,一日三餐按時進食,能夠更好的保養你們的腸胃,在減少應酬同時,也要多多鍛煉。 7月10日至7月16日一周豬生肖運程 豬: 【人,要有夢想,才能有前進的動力】 本周很容易有口舌之爭,劍拔弩張會影響人脈友情。尤其是在工作之中要特別注意,和同事有意見分歧的時候不要偏激逞能,心平氣和地進行商討,或是採納長輩的意見,能夠使同事關係變得和睦融洽。而平時也切記不可參與是非,不要湊熱鬧,以免惹來無端是非。健康狀態不佳,注意可能會有上火發炎。幸運色是卡其色。 微信 macaumickey 公共微信 macaumasterxiong