電商 RESTFul API + Spring Security (3) UnitTest
商品 Service UnitTest這邊針對商品部分 Service 寫一些單元測試,下面先列出預計測試的名稱,主要根據實際方法內會出現判斷的條件去設計,嘗試讓每個 Service 單元測試都 100%。
先注入並且初始化我們需要用到的 Bean,這邊主要測試 ProductService ,所以加上 @InjectMocks 註解,其他應用到的 Dao 都用 @Mock 標住用 mock 產生虛擬元件注入有標住 @InjectMocks 的 ProductService,@BeforeEach 先初始化待會會測試用到的一些物件資料。
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071@ExtendWith(MockitoExtension.class)public class ProductServiceTest { @Mock private P ...
電商 RESTFul API + Spring Security (2) 訂單功能
這篇繼續擴充訂單功能,可以回顧一下先前畫的架構圖,我們要有一張中間的表來記錄購物車內有哪些商品資訊,這部分建立訂單可以想像完成選擇要購買的商品之後送出訂單所產生的資料紀錄。
訂單功能建立order_info 訂單資訊,用來記錄我們整筆訂單的彙整資訊,包含關聯哪位 user, 總金額多少
order_item 訂單項目資訊,用來記錄整筆訂單中各別項目關聯哪個 product (product_id)、購買數量是多少(quantity)、價錢(amount),從中也可以知道屬於哪筆訂單(order_info_id)。
基本資料建立1234567891011121314151617CREATE TABLE order_info( id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, user_id INT NOT NULL, total_amount DECIMAL(10, 2) NOT NULL, -- 訂單總花費 created_at ...
電商 RESTFul API + Spring Security (1) 商品功能
這系列文章會總結先前包含 JPA 和 Security 的應用,詳細可以回顧 Spring Security (1 ~ 4),整合成一個小電商專案 side project,針對後端 API 和認證的部分,內容因為前面大量的內容會比較長,大家有興趣的可以好好來了解一下。
資料庫結構如果先回顧前面 Security 部分建構的資料庫結構 UML
會有 users, roles, user_roles 三個表去紀錄關於使用者的資訊,也可以從多對多的關聯中找出使用者的角色權限
現在要來加入電商主要的資料就是商品部分,預計會規畫成下面這樣的關係
需求規格會拆分成兩階段來建構:
products 建構,先建立 products, suppliers 1 : 1 關係
order_info 建構,order_info 記錄總價和購買使用者 id,再由 order_item 分別關聯 products 和 order_info,可以關聯出購物車內容,所有需要購買的商品數量和同品項總金額,也關聯出屬於哪張 order_info
大致清楚架構之後接下來預計會實作的一些功能也列出來:
商品相關
p ...
Spring Security (4) - JWT 驗證及結合 FilterChain
接續上一篇我們已經成功產生 JWT 回傳,所以後續使用者需要攜帶 JWT 至 Header 內然後發送請求到我們後端,我們需要驗證 JWT 是否有效然後決定使用者是否可以進入瀏覽或是使用功能,而這相對應的驗證流程,其實 Spring Security 有一套 FilterChain 的機制可以協助我們,這其中包含我們前面實作的帳號密碼驗證等等都是包含在裡面,那我們需要做的就是把 JWT 的驗證放入 FilterChain 裡面。
解析 Token 取出 Claims把之前拿來產生 Token 的 密鑰( getKey() 產生的) 拿來解析 Token,extractAllClaims() 帶入 token 可以取出其中的 Claims 也就是 Payload 的部分。
因為 Payload 裡面有很多屬性,下面另外抽出各別取 username 使用者名稱, expiration 到期時間等等的方法,方便後續驗證時可以引用
1234567891011121314151617181920212223242526272829303132333435363738394041@Service@ ...
Spring Security (3) - JWT 介紹及導入
JWTJSON Web Token (JWT),是一種根據將 JSON 格式資料進行編碼的的開放標準(RFC 7519),用於雙方之間安全將訊息作為 JSON 物件進行傳輸,訊息是經過數位簽章 (Digital Signature) 加密,因此可以被驗證及信任。
目前也成為各大網站之間進行資源獲取時所採用證明身份的訊息格式。
為什麼要用?
授權 (Authorization):先前提過,授權就是指根據使用者身分給予特定的瀏覽或是存取權限,這也是 JWT 常用的情境,例如使用者登入後,點選特定的功能或區域,發送請求時,需夾帶 JWT,Server 端就可根據該 JWT 所帶的資訊驗證是否可以開放使用該功能。像是單一路口登錄 (Single Sign On) 實作上也是廣泛應用到 JWT 。
訊息交換 (Information Exchange):JWT 可以透過公鑰/私鑰來做簽章,讓我們可知道是誰發送這個 JWT,此外,由於簽章是使用 header 和 payload 計算的,因此可驗證內容是否遭到篡改。
JWT 結構可以透過這個網站來測試產生的 jwt 解開後的內容
htt ...
Spring Security (2) - 串接個人資料庫
實際要來看一下我們要使用個人的使用者資訊資料表要如何串接,因為 Security 提供很多客製化的介面所以需要實作許多特殊的物件就會讓流程蠻複雜的,整體來說可以先有個概念,我們原本需要透過 dao 來和 DB 溝通的部分需要改成 Security 框架的模式,原本可以由 Spring Data JPA 直接取得 User 的物件回傳,但因為 Security 將使用者資訊會封裝成 UserDetails 這個物件來回傳,必須要透過 UserDetailsService 這邊來取得這個物件,所以會想辦法把這些東西去實做出來。
資料庫是串接 MySQL ,相關配置可以參考 Spring Data JPA (1)基礎應用架構 引入相關 Dependency
資料庫架構 Database Schema提供 SQL 給大家參考
123456789101112131415161718192021222324CREATE TABLE users( id BIGINT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50) N ...
Spring Security (1) - 介紹及應用
相信大家應該作為軟體工程師都知道資訊安全的重要性,如果你寫好一個系統,沒有受到好的資安控管,容易成為駭客下手的目標。特別是許多網頁或應用程式都建立在會員系統的基礎之下,這些資訊對於認證(authentication)與授權(authorization)控管相當重要,認證就相當於帳號登入,對系統表示自己是個合法的使用者。而授權則是系統允許該使用者存取某服務,看到特定頁面或是功能等等,也就是存取 API 許可。Spring Security 就提供了這部分的支援讓我們能夠輕鬆整合到 Spring Boot 專案中。
介紹Spring Security 是 Spring Boot 框架中的提供的一個資訊安全模組,能夠靈活的配置來有效保護 Web 應用程序免受各種安全威脅,主要有下面這些特色:
快速整合:Spring Boot Security 可以通過簡單的配置快速整合到 Spring Boot 應用中。
預設安全性:即使沒有進行任何配置,它也能為應用程序提供基本的安全防護,包括預設的登入頁面和認證方法 。
靈活配置:開發者可以根據需求自定義安全設置,如用戶認證、授權規則等 。
角色權 ...
UnitTest(5)- Mock Test
接續前一篇進行 Service 的測試,我們接序同一個情境針對 Product 的 CRUD,但是應用不同的寫法, 這邊會運用到 Mockito 這個套件來幫助我們應用 Mock 的虛構物件進行測試。
關於 Mock
顧名思義 Mock 有模擬、假的意思,將這樣模擬概念應用到測試中,就是希望程式原先依賴的對象都可以透過 mock 方式建立一個假的對象去模擬真實行為。
先前介紹單元測試時,有提到特性是應該各單元測試互相獨立,不依賴其他外部系統,Mock Test 是一種單元測試方法,能專注於要測試的程式本身的運作中,避免測試一個方法卻要建構整個 bean 相關的依賴架構。
一個系統架構會有多個類別之間互相依賴,且在 Spring Boot 中會都註冊成為 Bean,如下圖這樣多個 Class 互相依賴,Class A 需要依賴 B 和 C
引入 mock 測試時,就可以創建假的對象類,替換掉真實的 Class B 和 C,並可以自己設定這個 mock 對象的參數和期望結果,讓我們可以專注在測試當前的 Class A 應該要得到的回傳或是要 Pass 的結果,不受其他的外部服務影響,就 ...
UnitTest(4)- Service/Dao 層測試撰寫
這一篇我們來針對 Service / Dao 層進行測試的撰寫吧,以 MVC 架構下算是 Model 的部分會比較常進行測試程式的撰寫,因為牽涉到主要業務邏輯的運作,所以會比起 Controller 和 View 來說比較常需要進行測試,以 MVC 架構之下我認為個別需要測試的頻率及重點表整理如下
Model(Service/Dao)
Controller
View
測試頻率
高
中
低
重點
業務邏輯
數據驗證狀態管理 | 請求/錯誤處理驗證rounting 邏輯數據轉換(DTO 轉換) | 數據綁定模板渲染 |
所以這篇來主要針對最高頻率進行測試部分作介紹,Controller 層會應用到的寫法又會不太一樣,之後有機會可以再補充。
單元測試準備簡單建立一個之前介紹 Jpa 關聯時使用的類似欄位架構
db schema and data
12345678910111213CREATE TABLE product ( id BIGINT AUTO_INCREMENT PRIMARY KEY, name VARCHAR( ...
UnitTest(3)- Junit 5 常用註解
Junit 5 常用註解
@Test:標註方法為測試程試
@BeforeEach:每項測試項目開始前都會執行一次
@AfterEach:每項測試項目結束都會執行一次
@BeforeAll:測試開始之前執行一次
@AfterAll:測試結束之後執行一次
@Disabled:不列入測試項目
@DisplayName:測試結果顯示特定名稱
延伸先前計算相關的方法測試,我們補齊加減乘除各種方法跟測試
123456789101112131415161718192021public class Calculator { public int add(int x, int y) { return x + y; } public int subtract(int x, int y) { return x - y; } public int multiply(int x, int y) { return x * y; } public int div ...