搜尋

搜尋結果

火鍋推介 | $88食齊原價$368的重慶火鍋八大碗!新一年更加紅紅火火!
澳城餐飲
食在澳門iFood・2021-02-20

生活的節奏愈發的急促 我們亦被迫著向前走 卻容易忘記身邊簡單的快樂 屋外寒風瑟瑟 屋內圍坐鍋前 來一鍋正宗火辣的重慶火鍋 更少不了焦香熱辣的燒烤 而這些,重慶格格都能為你實現 ▼ 火鍋八大碗 重慶格格|福利大放送 關注名門公眾號 加轉發文章到朋友圈 原價$368 優惠價$88 優惠價$88 優惠價$88 優惠價$88 優惠價$88 !食火鍋八大碗! 每檯限一份,關注及轉發文章後到店出示即可 龍頭火鍋氣勢不可擋,最經典的紅白鴛鴦鍋喺雙龍頭的映襯下暗藏玄機。 來重慶格格,必點火鍋八大碗!一份包攬火鍋八件套:腐竹、鴨血、午餐肉、鵝腸、鮮牛肉、香菇、毛肚、海帶,份量非同凡響!八種配菜各有風味,經典又醇厚! 重慶特色四格品味鍋底 麻辣火鍋的靈魂在於麻辣鮮香的鍋底,秉持重慶火鍋傳統的同時,更融合澳門人的口味變化。 特聘重慶資深老廚師,精心細研「麻辣紅油」、「山珍菌湯」、「蕃茄芝士湯」、「三鮮湯底」,四宮格演繹絕味之合! 錦繡海鮮記 澳門雖然冬無嚴寒,但辛苦勞作一年的澳門人應該放鬆身心,喺新年時期,享受豐收的碩果。 品嚐天然的海鮮品種,鮑魚、龍蝦、各式貝類、鮮蝦、大閘蟹、聖子皇,精心細選,應有盡有! 長板靚肥牛 長板靚肥牛果然名不虛傳,精選國外5A級肥牛,係最適合火鍋的部位! 漂亮的肥牛紅白相間,一片一片下鍋燙煮,口感細嫩,唇齒留香! 精選鮮毛肚 毛肚作為重慶火鍋的主角,重慶格格當然奉上上乘佳品! 精選高原秦川牛肚精心處理,穿州過省,直接空運抵達澳門,絕無化學處理,純正新鮮無添加! 鮮鵝腸 鮮鵝腸亦係招牌涮品,選用當天鮮宰獅頭鴛鴦腸,新鮮程度可想而知! 細細長長的鵝腸端上桌,記得秘密口訣下鍋ldquo;七上八下rdquo;,待鵝腸微微捲起口感才最佳,鮮嫩爽脆! 手打蝦滑amp;魚滑amp;蝦子墨魚滑 若喜歡追求極致鮮爽的感覺,仲有各類蝦滑魚滑為你奉上! 精選游水海蝦、鮮活鯪魚、進口大墨魚,純手工打造,嫩滑彈牙,鮮嫩無添加,入口都係食材本身的天然香甜! 重慶口水雞 口水雞作為一道傳統名菜,佐料豐富,集麻辣鮮香嫩爽于一身! 精選清遠北江山區的三黃雞,恰到好處地保留雞肉的鮮美程度,讓人直流口水! 麻辣花螺 晶瑩透露的麻辣花螺有著與眾不同的口感,軟糯彈牙,十分入味! 重慶師傅用傳統製作的「麻辣塊」烹製香花螺,霸道的辣加上後勁十足的香麻,讓人一試難忘! 燒烤拼盤 火鍋和燒烤拼盤雙管齊下,熱辣的蒸汽中品味焦香的燒烤拼盤,一干一濕,快樂翻倍! 嚴選優質肉類作為燒烤食材,搭配廚師獨特的燒烤手法,讓你感受不一樣的燒烤! 麻辣蝦 靠著口味脫穎而出的麻辣蝦,用料之鮮,烹飪之精! 精選鮮活游水海蝦,經廚師們反復鑽研創作,調配出滿滿四川風味的麻辣醬,那滋味甚是令人滿足! END 皇朝店:澳門皇朝帝景苑地下 電話:(853)28211547 營業時間:1700400 氹仔店:氹仔華寶花園第四座地下 電話:(853)28831308 營業時間:1700400 圖文|胖農夫的奶茶 攝影|嚕嚕米

KLOOK近期優惠大整理!
激安優惠
MO560・2019-11-29

KLOOK近期優惠大整理! 臨近聖誕、新年旅遊旺季,KLOOK出咗超多超多Promo code啊!小編已經幫大家精選曬,分埋地點,無論你去邊到旅行都保證有得折上折,想訂幾多嘢都得啦!聖誕同新年假期都用得! 世界各地都用得! 優惠詳情:全線產品滿$800額外減$88預訂期限:2019年11月30日前活動網址:httpsbit.ly2NhWb9v 日韓台適用 1. 最後6日滿$500額外減$50活動網址:httpsbit.ly2Owjw81 2. 最後6日滿$1000額外減$120活動網址:httpsbit.ly2Owjw81 3. 滿$1500額外9折活動網址:httpsbit.ly2DqVjcM 4. 滿$3000額外88折活動網址:httpsbit.ly2DqVjcM 5. 最後6日買JR Pass送2日日本WiFi活動網址:httpsbit.ly2Owjw81 6. 台灣高鐵買一送一活動網址:httpsbit.ly2OtKfBW 泰國適用 1. 最後6日滿$500額外減$50活動網址:httpsbit.ly2Owjw81 2. 最後6日滿$1000額外減$120活動網址:httpsbit.ly2Owjw81 3. 滿$500額外95折布吉 喀比 清萊 北碧府 活動網址:httpsbit.ly2XTIGjO 歐美澳紐適用 1. 滿$1500額外9折活動網址:httpsbit.ly2DqVjcM 2. 滿$3000額外88折活動網址:httpsbit.ly2DqVjcM 緊貼最新最潮澳門信用卡、飛行里數、旅遊資訊,記得讚好MO560的Facebook! 如想查看更多詳情,請到MO560的網站查看。 更多KLOOK優惠:httpsmotravel.infoklookpromotecode 喜歡小編的文章嗎?比個Like支持我啦 Facebook MO560Instagram mo560_travelWebsite httpsmotravel.info 想追蹤最新最潮澳門信用卡、飛行里數、旅遊資訊?將MO560設定為 「搶先看See First」!

海鮮大餐 $228 起!麗思卡爾頓酒店「麗思咖啡廳」周四限定菜單
澳城餐飲
Cheers!・2018-09-13

澳門麗思卡爾頓酒店的「麗思咖啡廳」不時更換主題套餐,最近就以「海洋鮮味之旅」為設計靈感,在前菜、主菜中用上不少海鮮入饌,用料高質,海洋迷記得把握時機。 菜單開宗明義以海鮮作主打,龍蝦、扇貝、魷魚、生蠔、大蝦等絕對少不了。四選一的前菜中,就有海鮮沙律、龍蝦濃湯、烤法國生蠔和新鮮生蠔可選。 而主菜則有「番茄奶油意大利麵配大蝦、魷魚、扇貝」、「炒三文魚配蛤白酒汁及香腸」、「香煎海鱸魚配烤龍蝦」及「酸甜鱈魚配阿拉斯加蟹腿、香草及三文魚籽」。 不得不提的是,套餐還包括一杯 PerrierJoueuml;t 香檳和二選一的甜品,保證大家捧腹而回。 甜品二選一,有「草苺配巧克力醬香草雪榚及奶油」及「檸檬撻」可選。 試菜當日,小編就選擇了新鮮法國生蠔作前菜,配搭香煎海鱸魚配烤龍蝦。前者的生蠔一客三隻,清甜爽口。後者據說是餐廳主廚最拿手的煎海鱸,鱸魚煎至外脆內嫩,啖啖香口惹味;烤龍蝦彈牙中帶點焦香,大滿足! 海洋鮮味之旅 地點:澳門麗思卡爾頓酒店地下麗思咖啡廳 供應時間:逢周四(17302230) 價錢:$228 起 網址:httpswww.galaxymacau.comzhhantoffersdininggourmetfromtheseaattheritzcarltoncafe

Docker打包 App還是打包底層程式作為Image ?
科技新知
MacauYeah・2023-07-28

雖然筆者對於Docker Swarm Mode的資歷尚淺,但由於後期更動的難點越來越多,筆者很想早一點討論其中不同操作的差異 Docker Swarm Docker Swarm Mode其實是Docker提供的一個Cluster群集環境。在其中運行的Image,都可以比較方便地隨時分身到不同的node節點上,對於提高負載或可用性,都是一個不錯的解決。 只要該Image跑起的Container是Stateless前後兩次執行的結果互不相干涉,或者是把Stateful的部份有干涉的部份外包到第三方例如儲存空間使用NFS,或記憶體暫存改為KeyValue Database,就可以方便地運作在Docker Swarm mode上。 部署Docker Swarm的選項 Docker Swarm可以把Image變成分身Container,但並不沒有硬性改變傳統App操作方式。大部份App在執行時,都需要另一個底層程式的支緩。例如 Php Web App,需要底層php fpm nginx或apache Java Web App,就需要java Tomcat 所以在發佈App時,可以選擇把 App直接打包成Image 只把底層程式打包在Image中例如Tomcat,再在跑起Container時再動態接起App。 兩者有何差別 就信心層面上,一定是把App直接打包成Image實際一點。因為這樣可以極大地減少測試環境和正式環境的差異而出現的問題。筆者一開始也不完全讚成,但也越來越傾向這種做法。 在解釋筆者為何有這個結論前,先條列式地對比一下兩種差別。 事項打包App成為Image打包底層程式成為Image 打包複雜度 需要把App用到的一些環境變數引入設定Image的entrypoint中,方便配合不同的環境可以改變App的行為。打包次數根據App數量有關。比較靈活,但比較需要學習和試錯。 底層程式統一設定環境變數,其中所有App都會使用類似或相同的設定,設定方式跟傳統方式無異。打包次數根據底層程式數量有關。比較死版,但要試錯的成本較低 發佈流程 打包App成Image。再靠Docker Swarm設定Image有多少分身,每個分身不需要特別再設定。 原來的底層程式已存在於Docker Swarm中,只需把新建或更新了的App放入不同分身的儲存空間,讓底層程式動態跑起App。 管理複雜度 每個App都是獨立的,代表有任何更新也是獨立更新。在微服務的協作環境中,需要管理員從Image層面為每個App設定網絡network或開放端口Port。但每個App可以設定不同的分身數量,靈活性一定比只打包底層程式要高。 使用同一個底層程式Image的App都會使用同一個網路和端口設定。在微服務的協作環境中,管理員要應付的設定數量一定比打包App要少。但由於是Conatiner分身是針對底層程式,所以若然某個App有不同需求,就要重新設定另一套底層程式。 上述幾個點,最後其實都是複雜度和靈活度的取捨。雖然打包App的工序更多,但提供的靈活性也更多。如果考慮要從傳統模式中過渡,方便與完成不懂Docker的同事協作,就首選打包底層程式。如果考慮可重複性和信心保證,還是打抱App比較直接,要複制一個環境到另一個環境,也比較易測試。

奶爸手記 - 百日紀念01
兒童成長
MacauYeah・2022-09-02

筆者初為人父,很多生活習慣都在變,但作為一個Gunpla 模型愛好者,突然要放棄所有模型,實在有點不捨。所以就趁著上月的BB展,馬上入手一台高達模型過癮(誤)。 好在,有聰明伶俐的老婆大人為老公豬帶來不一樣的替代品,BB百日立體手足模型為你BB制作獨一無二的紀念品。 材料主要為克隆粉(硅膠土)、模型粉(石膏) 克隆粉與水以體積比12的混合,攪勻,就可以放BB的手掌或腳掌進去開模。 難點是整個過程很短而且沒法重來,你只有1分鐘的時間攪勻液體,再久的話還沒來得及放手腳進去就已經開始凝固。放進手或腳後,亦很考耐力,手腳不能碰到容器壁,否則開模就有缺口。維持靜止大概5分鐘,開模就完成了。 因為操作上真的有難度,所以筆者亦沒有多餘時間拍照,只能補上開模完成後的照片,下圖便是我家BB的美腳掌。 然後,再使用模型粉與水21的方式調配模型液,倒入模具中過一夜。 隔天就可以拆了 httpsyoutube.comshortsn5jI9G8_x8Y 初次制作,筆者是建議先做腳,而且在BB熟睡時再進行開模,否則一個抖動,就前功盡廢。在熟知操作流程時,再去做手。 做手開模時,除了原本對時間的掌握要有了解外,還要選一個BB不會亂動的掌型。根據你們家BB的習慣,選擇完全握拳或是申開手掌,不要半開半握,因為在凝固和抽手的進程中,半開半握會破壞模具。筆者就是半開半握,結果後期就要花更多時間精修。 (未完、待續)

不丹 | Dochula Pass的108座佛塔
走遍世界
原來世界這樣大・2019-02-20

去完 Thimuph(廷布)後,我們繞過山向Punakha(普納卡)這個城市進發。 繞過山的意思是指車子由Thimuph駛到山頂,再沿著山路下山去到別的城市 ndash; 即是Punakha。而從Thimuph到Punakha那段路的山頂有中途的景點叫Dochula Pass,順道可以讓我們下車,鬆鬆腰骨。 這個Dochula Pass是從Thimuph到Punakha必經的地方,而正正因為Dochula Pass位於山頂之上(海拔3,100米),溫度跟Thimuph有很大差別。Thimuph(海拔2300米)大概是8度的氣溫了,去到Dochula Pass還要再冷多些,差不多是02度,然後去到Punakha(海拔1200米)又回暖到1718度氣溫的地方,皮膚感受的溫度猶如坐過火車,每去到另一個城市天氣也給我們感受不同的溫度。 Dochula Pass的108座佛塔是為了紀念2003年與印度發生戰爭所喪身的108名士兵,而今日則成為了遊客必到的景點之一。每次導遊說著歷史故事我都有點心虛,因為以前上歷史課學習的知識也送回老師那兒去了,對於歷史我是個一知半解的人。不過這樣沒有壓力地聽導遊說歷史故事,我也挺喜歡這個感覺的。世界遺留下這麼多歷史遺跡的原因,就是希望我們對以前世界多一點了解。但現在大家去的旅遊,有幾多次是真正了解這個地方?而不是單憑為了「打卡」?不知為何見到為打卡而瘋狂拍照的人,心裡總會有莫名的火起,但我明白這是社會造成,不能怪人,只是不喜歡這種風氣,但是我不喜歡又有什魔用?可能這個願望有點奢侈,希望世界上有更多人醒覺,不要單純的為打卡,而是把時間花在去一些歷史遺跡、參觀博物館,用別個角度了解地方的歷史和文化。 這Dochula Pass紀念戰爭的殘酷,也紀念當時犧牲生命保衛國家的士兵,壯觀之外也給人一份平靜的感覺。 向天仰望,站在海拔3100米的地上,我們似乎跟天空的距離,又接近了一點。

配合大市走勢來選股的程式寫法
創富坊
程式交易 www.quants.hk (導師: 財經書藉作家: 麥振威)・2015-07-25

配合大市走勢來選股的程式寫法 例子 經過六月至七月的跌市,較多學員問的問題是,如何利用程式配合市況來選股,同時再做BACKTEST。假設大家希望恆指在20EMA之上的日子,才買入創52週新高的股票,又或恆指由高位回落30%,又或50%,才買入創52週新低的股票,這些準則其實很簡單便能利用程式寫出來,Amibroker中,foreignticker, datafield這個語法便能做法。 以上述的作例子,AFL 的寫法如下 HSIClose = Foreign ldquo;HSIquot;, ldquo;Cquot; ; TimeFrameSet inweekly; ABC =Cgt;REFHHVH,52,1; TimeFrameRestore; ABC = TimeFrameExpandABC, inWEEKLY; condition = ABC AND Cgt;O AND C gt; Ref C, 1 AND H gt; Ref H,1 ; Filter= condition AND HSIClose gt; EMAHSIClose, 20; 恆指在20EMA之上的日子,才買入創52週新高的股票,寫下這個準則來選股,那恆指在20EMA以下的日子程式便不會選出股票,當然也可以加上BUY、SELL的準則,即買入及沽出的準則來為以上的選股方法做測試當然這個只是例子,創52週新高的股票大多是缺乏成交的,未必可以做實際交易時的選股準則 究竟恆指處於什麼情況下才適合選股 這個其實利用程式便能很容易做BACKTEST。也可特別留意大跌市的日子,若在過去十年中,比如在2008年金融海嘯期間,又或過去的兩個月等等日子,恆指究竟是處於那種情況 利用程式寫出來,避免在這種情況下選股,看看是否能提高勝算 又或反過來,在恆指大跌後,比如設定恆指創10日新低後,買入跌穿保歷加通道底部同時成交量急增的股票,這些利用以上的FILE,大家也可以自行作出修改 AMIBROKER的使用步驟 利用Amibroker的「Auto update quoteAmiQuote」功能更新股票的基本數據,選Yahoo Current current day only, stocks, funds , USamp;international50 但留意你的選股LIST中必需有「HSI」這個代號,這樣才能同時更新恆指的數據。 開啟Amibroker的Formula Editor,再把以下的afl file 貼上 HSIClose = Foreign ldquo;HSIquot;, ldquo;Cquot; ; TimeFrameSet inweekly; ABC =Cgt;REFHHVH,52,1; TimeFrameRestore; ABC = TimeFrameExpandABC, inWEEKLY; condition = ABC AND Cgt;O AND C gt; Ref C, 1 AND H gt; Ref H,1 ; Filter= condition AND HSIClose gt; EMAHSIClose, 20; 可看以下解釋 再根據圖中設定來選股 能自行做BACKTEST才真正開始交易,是程式交易的優勢之一,而且數據是可免費網上下載,配合大市走勢來選股,所需要懂的語法也十分簡單,希望這對大家有幫助

【香港。食記】John Anthony 莊館
專題報導
原來世界這樣大・2018-10-15

在銅鑼灣這個繁華的地區,大家都一向把焦點落在靠近地鐵站的希慎或時代廣場,卻遺忘了很多值得發掘的地方。 在利園三期,可算是銅鑼灣寧靜的一面,不知道你對這邊的了解又有幾多呢?近期的John Anthony莊館在利園三期正式開幕,為食客帶來另一片天空,以現代烹調方法重新炮製傳統中菜,每道菜式似曾熟悉的同時又帶來一點新意,讓我們一起來欣賞John Anthony莊館主廚的創意和心思吧。 人齊才開始,既然未到齊的,不妨把莊館逛一圈,長長的酒吧檯第一眼會投射到的焦點,格局乾淨俐落,感覺叫人舒適。就算是吃晚飯或是跟朋友來摸摸酒杯底聊天,這兒絕對登得上大雅之堂,不會失禮。 在Mott32姊妹店John Anthony是位於地庫的位置,走過一條長長的樓梯,別有洞天。在酒吧檯的位置,最觸目的就是四條的Gin酒柱,是John Anthony 自家製的Gin酒。這四條Gin的酒柱是菊花杞子普洱、薰衣草、番茄露絲瑪麗、煎茶四種口味。當日沒有什麼心水,正在猶豫要不要點些酒精飲料時,嚐了一口朋友的Sencha,是煎茶加入了Tonic Water的飲料,有著煎茶的清香,容易入口,Tonic Water的味道相當輕量,不太愛好酒精的朋友也可以點來試試,不用過於擔心。 先為我們呈上的是中式點心類型的菜式,小籠包、蝦餃、腸粉跟餃子相信大家也相當熟悉,但是莊館的當然是跟傳統茶樓的來點不一樣啦!在這些中式點心之中,加入了各種食材,例如營養豐富的紅菜頭、近年流行的墨汁等等。 而在眾多點心之中我最軟殼脆蟹腸粉。以前的膠粉怎會有這麼多的變奏呢?由春風得意卷到現在莊館的軟殼脆蟹腸粉,我都覺得每一次都能為我帶來驚喜,膠粉皮包裹著脹卜卜的軟殼蟹,即使大口一咬依然有著那份脆感,叫人滿足! 低溫泡椒蟶子之中,蟶子的肉質美味,泡椒的方法處理讓辣感輕量地滲入蟶子的肉質。在有點辣感的同時,大廚很巧妙地加上黑醋珍珠,要是咬到黑醋珍珠,那份酸酸的味道能沖淡泡椒的辣度,中和及平衡口腔內殘留的味道,這份口感相當的特別。 邪惡的花雕魚籽滷水燻蛋做得好吃又夠滑嫩,在蛋上簡單加上魚籽已經是最好的配搭。 緊接著的是慢煮口水和牛面頰,一放到枱上已經傳來聞聞的香味,叫人相當期待。而旁邊的朋友吃完過後都是展露著同一個表情,是暗示著這道菜不能不嚐的意思嗎?慢煮口水和牛面頰是以一片牛面頰和一片西瓜組成,建議吃用的方式是把牛面頰和西瓜同一時間放到口中,麻辣的牛肉感相當突出,但當吃到西瓜時它的清涼卻消除了麻辣,兩者之間的配搭實在太特別了,難怪嘩聲四起。 吃中菜的當然不能少得叉燒了,即使一碟司空見慣的叉燒,莊館也付出很大的努力把不足為奇的叉燒成為食客心頭好。採用澳洲和牛叉燒,質素不在話下,以慢煮的方法炮製,肉味濃郁肉質軟腍,配上特調的蔥蒜,令我們每個都由衷地讚嘆這碟叉燒又好吃又難忘! 想滋潤一下除了嚐嚐甜品外,湯水也是個不錯的選擇。以椰皇作為容量,加入了鮑魚、昆布,味道有著椰皇的清香還是有點滋潤喉嚨的效果。 蔥蒜燒虎蝦上的蔥蒜也是用了剛剛叉燒上的醬料,醬料放在虎蝦之上又帶來不一樣的感覺。以最簡單的方法調製海鮮,能把鮮味帶出,蔥蒜輕輕作個點綴,品味最原始的味道。 一個大大的蓋子把茶燻脆皮雞蓋住,一把蓋子拿開,濃郁的煙燻走到我們的味蕾,雖然白煙只是維持了一陣子,但煙燻味殘留在脆皮雞上,而脆皮雞也不是浪得虛名,香脆脆皮與嫩滑雞肉一拼放到口中,滋味滿瀉! 對於每次吃飯都要有澱粉質的朋友,可以試試棉花泡飯,味道清淡,可以作點緩衝。 莊館的精緻中菜叫人樂而忘返,每道菜充滿驚喜,要是叫我揀選最喜歡的一道菜的,我想也是太為難了。糅合上乘的食材,以嶄新的烹調方法,重新製作傳統中菜,想來點新意思的,不妨來一回莊館吧!喜歡拍照的朋友,記得帶備相機,必定能滿載而歸呢! 莊館銅鑼灣新寧道1號利園三期B1樓B01B10號舖

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框架會自行把登入者輸入的密碼與加密了的密碼作比較。

【大灣區】觀落日無遺的橫琴 ※二井灣濕地公園 ※
環保自然
莫雪・2023-10-25

【大灣區】觀落日無遺的橫琴 ※ 二井灣濕地公園 ※ 已被國家允許澳門政府加入共治共管的珠海橫琴, 位於橫琴新區橫琴濱海濕地公園, 總面積約三百九十二公頃, 便包括這一片遼闊的二井灣紅樹林濕地片區, 約占面積332公頃。 另一片則是芒洲濕地片區, 約占面積60公頃。 生活在澳門的小小城區, 真值得節假日來走走, 來這一處原始的天然氧吧, 多種動植物的棲息地, 吸收滿滿的免費大自然的清新空氣, 曠野郊區更是免門票的, 放鬆一下緊張了一星期的工作思緒。 二井灣紅樹林濕地片區出遊那天, 也是節日假期, 但人流不多, 可能這裡異常遼闊吧, 繞海邊走走, 一圈大約需要一個小時, 名正其實的行大運了哈 下午時分, 已有相當的人群於面朝大海的草地上扎駐帳蓬, 嬉玩野餐、天倫之樂中了。 太陽還掛在半高空中, 人們正等待著落日黃昏的來臨, 觀一幕大自然上演的 幻麗晚霞共落日餘暉再沉醉落入無際海面。 而海上遠處, 有一橋橫跨, 那便是新建成剛開通不久的「香海大橋」, 若從斗門到達珠海主城區 僅需約2030分鐘的車程。悠閒至天黑暗下來, 人們才徐徐不捨收拾離開。 二井灣紅樹林濕地片區在《橫琴總體規劃》裡, 已入選擬建十大國家級濕地公園的其中一席, 被列為生態綠地, 當地政府定位這片濕地為一流的精品濕地公園, 將進一步打造成為鳥類生態家園為目標;珠江口區域珍稀紅樹林濕地資源區; 和候鳥遷徙舒適驛站停留處。 偌大的二井灣, 喜歡釣魚的, 可以臨海邊垂釣、 或草地上曬曬日光浴、走走伸展拍照觀日落, 一個放鬆優閑人少的好地方,大橋、湖面、日落、 蘆葦隨手拍都能出美照,當然, 黃昏時刻最是美麗! 地址:廣東省珠海市橫琴新區珠海橫琴濱海濕地公園 門票:無門票,免票進入 開放時間:整天 交通: 公共交通:14路;62路;86路;k10路;k11路;長隆高峰專線 自駕車輛:珠三角環線高速 環島東路 長隆大道(視實際情況可用手機導航) #珠海萬山‧東澳島# #横琴十里花海# 其它文章, 詳情請點擊澳門科學館「蒸氣誌電子月刊」 內之「近代中國科學家事蹟及其精神」 httpswww.msc.org.mozhflipbook55STEAMISSUE 本篇文章、相片版權屬作者所有,經由版權持有人授權CyberCTM.com發表。 聯絡及邀約 irene801802@hotmail.com