核心模型:RBAC (Role-Based Access Control)
| 實體 | 關鍵欄位 | 說明 |
| User | id, username, password_hash, status | 系統使用者 |
| Role | id, name, description | 角色(如 admin、editor、viewer) |
| Permission | id, code, url_pattern, method | 細粒度權限(如 user:create、/api/users/*) |
| User_Role | user_id, role_id | 多對多關聯 |
| Role_Permission | role_id, permission_id | 多對多關聯 |
分層架構
com.example
├── filter
│ └── AuthFilter.java // 攔截未登入/無權限請求
├── servlet
│ ├── LoginServlet.java
│ ├── UserServlet.java // 用戶增刪改查
│ ├── RoleServlet.java
│ └── PermissionServlet.java
├── service
│ ├── UserService.java
│ └── PermissionService.java // 核心:hasPermission(user, url, method)
├── dao
│ └── ...
└── jsp
├── login.jsp
├── layout.jsp // 共用佈局、動態選單
├── user/list.jsp
└── role/edit.jsp
關鍵元件實作要點
1. 登入驗證與 Session 存權限碼集合
// LoginServlet
List permCodes = permissionService.getPermissionCodesByUserId(user.getId());
session.setAttribute("permissions", new HashSet<>(permCodes));
session.setAttribute("user", user);
2. 權限攔截過濾器
@WebFilter("/*")
public class AuthFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
HttpServletRequest request = (HttpServletRequest) req;
String uri = request.getRequestURI();
// 靜態資源、登入頁放行
if (uri.endsWith(".css") || uri.endsWith(".js") || uri.equals("/login")) {
chain.doFilter(req, res); return;
}
HttpSession session = request.getSession(false);
if (session == null || session.getAttribute("user") == null) {
((HttpServletResponse)res).sendRedirect("/login"); return;
}
Set perms = (Set) session.getAttribute("permissions");
String requiredPerm = PermissionService.resolvePermission(uri, request.getMethod());
if (requiredPerm != null && !perms.contains(requiredPerm)) {
((HttpServletResponse)res).sendError(403, "無權限訪問"); return;
}
chain.doFilter(req, res);
}
}
3. JSP 動態渲染選單/按鈕
<c:if test="${permissions.contains('user:create')}">
<a href="/user/add" class="btn">新增用戶</a>
</c:if>
進階擴充
- 資料權限:在 Service 層依部門/機構 ID 過濾查詢條件。
- 快取權限集合:Redis 存
user:{id}:perms,登入時載入,減少 DB 壓力。
- 前後端分離:Servlet 返回 JSON,前端 Vue/React 根據
permissions 控制路由守衛與按鈕顯示。