前期的基礎建設完成後,可以開始廣邀開發成員投入開發。此時不論是前端功能或後端 API 的數量,都會快速成長。前端功能在初期就已經有對應 RBAC 的角色控管,用來限制登入者可使用的功能。但後端呢?後端的 API 如果也能做到權限管理呢?本篇將討論本專案如何管理後端 Backend API 的存取權限。
先說明本專案的前端功能與使用者帳號權限管理機制。原則上,各別功能(如圖17-1 功能A1~C3)都會先分類到固定的 Group,每個新功能開發時就會分配到某個功能群組。而前端功能則透過管理者自行建立群組(如圖17-1 User Group1~99),並指定可使用的功能與使用者帳號。藉由這兩層關聯,就能管控各帳號可存取的 Controller。
圖17-1:功能群組權限設計
圖17-2:個人帳號可使用的功能清單示意圖
1.後端 backendAPI 專案中,增加 enumHelper.cs
public static class EnumHelper_enumGroupTypeCode
{
public const string AppGroupA= "AppGroupA";
public const string AppGroupB= "AppGroupB";
public const string AppGroupC= "AppGroupC";
public static readonly Dictionary<enumGroupTypeCode, string> GroupTypeCodeDictionary = new Dictionary<enumGroupTypeCode, string>
{
{ enumGroupTypeCode.AppGroupA, AppGroupA},
{ enumGroupTypeCode.AppGroupB, AppGroupB},
{ enumGroupTypeCode.AppGroupC, AppGroupC},
};
}
2.後端 backendAPI 專案中 prgram.cs
加入授權策略。
builder.Services.AddAuthorization(options =>
{
// 根據 enumGroupTypeCode 的字典生成授權策略
foreach (var groupTypeCode in EnumHelper_enumGroupTypeCode.GroupTypeCodeDictionary)
{
options.AddPolicy(groupTypeCode.Value, policy =>
policy.RequireClaim("GroupTypeCode", groupTypeCode.Key.ToString()));
}
});
Program.cs
中加入 UseAuthentication
、UseAuthorization
,讓每個 HTTP 請求在進入 Controller 前,根據設定的授權策略(如角色、權限、Claims)進行檢查。如果沒有權限,則會回傳 403 Forbidden。 app.UseAuthentication();//驗證身份
app.UseAuthorization();//授權驗證(提醒:通常要放置於app.UseRouting(); 之後、app.MapControllers(); 之前。)
Controller.cs
,加入 Filter,並指定可存取的 Policy,例如在 Controller 或 Action 上使用 [Authorize(Policy = "YourPolicyName")]
來限制只有符合該 Policy 的使用者才能存取。namespace backendAPI.Controllers
{
[Authorize(Policy = EnumHelper_enumGroupTypeCode.AppGroupC)]
[ApiController]
[Route("api/[controller]")]
public class PermissionController : ControllerBase
{
private readonly UserInfoService _userInfoService;
public PermissionController(UserInfoService userInfoService)
{
_userInfoService = userInfoService ?? throw new ArgumentNullException(nameof(userInfoService));
}
// GET: api/permission
[HttpGet]
[ProducesResponseType(typeof(UserAccessDto), 200)]
public async Task<IActionResult> GetPermission()
{
var emailClaim = User.FindFirst(ClaimTypes.Upn)?.Value;
try {
UserAccessDto? userInfo = await _userInfoService.GetUserInfobyEmail(emailClaim);
}
catch (Exception ex)
{
Log.Error("Error ex : " + ex.TargetSite);
}
return Ok(userInfo );
}
}
}
啟動服務,發送 API 請求,確認可以收到 403 Forbidden 回應。
圖17-3:發送 API 請求後,Filter 權限政策生效。
調整 Filter,移除 Policy 驗證,確認可以收到 200 OK 回應。
namespace backendAPI.Controllers
{
[Authorize] // 僅驗證身份
[ApiController]
[Route("api/[controller]")]
public class PermissionController : ControllerBase
{
private readonly UserInfoService _userInfoService;
public PermissionController(UserInfoService userInfoService)
{
_userInfoService = userInfoService ?? throw new ArgumentNullException(nameof(userInfoService));
}
// GET: api/permission
[HttpGet]
[ProducesResponseType(typeof(UserAccessDto), 200)]
public async Task<IActionResult> GetPermission()
{
var emailClaim = User.FindFirst(ClaimTypes.Upn)?.Value;
try {
UserAccessDto? userInfo = await _userInfoService.GetUserInfobyEmail(emailClaim);
}
catch (Exception ex)
{
Log.Error("Error ex : " + ex.TargetSite);
}
return Ok(userInfo );
}
}
}
圖17-4:沒有 Filter 管控,可順利存取 PermissionController
下的 API 服務。
不過這個機制仍有調整的空間。回顧剛剛設計的範例,Holiday 僅被授權功能 B1,但也因此可以存取所有 GroupB 的 API 服務。因此,在個別 API 服務中,仍需要增加額外的邏輯處理來管控,以提升安全性與嚴謹度。
圖17-5:授權單一功能,便可存取整個 Controller 的所有API,仍有調整改善之處。
透過本篇的說明與實作,我們展示了如何在後端 Backend API 中建立完整的存取權限管理機制。從前端功能群組與使用者帳號的權限規劃,到後端透過 JWT、Policy 與 Filter 的授權控制,每個 HTTP 請求都能依據角色、權限或 Claim 進行驗證,確保功能僅授權使用者可存取。
實作與驗證結果顯示,啟用 Policy 後,未授權的請求會正確回傳 403 Forbidden,移除 Policy 後則可順利取得 200 OK,說明權限控管機制運作正常且可靈活調整。整體設計不僅提升系統安全性,也為團隊提供可擴展、可維護的權限管理架構,適用於多角色、多功能的企業級專案。