employee_id (工號),非空唯一。+----------------+ +----------------+ +------------------+
| Web1 (舊) | | Web2 (舊) | | Web3 (舊) |
| user1/123 | | zhangsan/456 | | abc/789 |
| emp_id: 001 | | emp_id: 001 | | emp_id: 001 |
+-------+--------+ +-------+--------+ +--------+---------+
| | |
v v v
+-------+----------------------------------------------+--------+
| CAS Server (身分提供者) |
| 1. 驗證 employee_id + 密碼 (統一認證源) |
| 2. 簽發 TGT (Ticket Granting Ticket) |
| 3. 回調各系統 /sso/login?ticket=ST&emp_id=001 |
+-------+----------------------------------------------+--------+
| | |
v v v
+-------+--------+ +-------+--------+ +--------+---------+
| Web1 (新) | | Web2 (新) | | Web3 (新) |
| 1. 驗證 ST | | 1. 驗證 ST | | 1. 驗證 ST |
| 2. 查詢本地 | | 2. 查詢本地 | | 2. 查詢本地 |
| user by | | user by | | user by |
| emp_id | | emp_id | | emp_id |
| 3. 不存在則 | | 3. 不存在則 | | 3. 不存在則 |
| 自動建立 | | 自動建立 | | 自動建立 |
| 並綁定 | | 並綁定 | | 並綁定 |
+--------------+ +--------------+ +------------------+
建立獨立 cas_user 表:employee_id (PK), password_hash, status。遷移時由各系統同步工號與初始密碼(或強制首次登入修改)。
public class CasSsoFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
HttpServletRequest request = (HttpServletRequest) req;
String ticket = request.getParameter("ticket");
String empId = request.getParameter("emp_id");
if (StringUtils.isBlank(ticket)) {
// 重導向 CAS 登入頁,帶上 service=本系統回調地址
response.sendRedirect(casLoginUrl + "?service=" + URLEncoder.encode(callbackUrl));
return;
}
// 1. 驗證 ST -> 獲取 employee_id (CAS SDK)
String validatedEmpId = CasClient.validateTicket(ticket, callbackUrl);
if (!empId.equals(validatedEmpId)) throw new SecurityException("工號不匹配");
// 2. 即時佈建
User localUser = userService.findByEmpId(empId);
if (localUser == null) {
localUser = userService.provisionFromCentral(empId); // 呼叫中心介面同步基本資料
}
// 3. 建立本地 Session
request.getSession().setAttribute("CURRENT_USER", localUser);
chain.doFilter(req, res);
}
}
CAS Server 單點登出:配置各系統 logoutUrl,CAS 登出時以 HTTP POST 通知各系統銷毀 Session。
此方案不修改舊系統密碼邏輯,僅在登入攔截器植入 CAS 協議,風險可控、平滑過渡。