登錄驗證成功後,從數據庫查詢用戶完整信息構建用戶對象,存入 Session,而非僅存用戶名。
public class User implements Serializable {
private Long id;
private String username;
private String password; // 不建議存入 Session
private String email;
private String phone;
private String gender;
private Date registerTime;
private Integer status;
private List roles; // 權限相關
// Getter/Setter/toString
// 重寫 equals/hashCode 基於 id
}
@PostMapping("/login")
public String login(@RequestParam String username,
@RequestParam String password,
HttpSession session,
Model model) {
// 1. 調用 Service 驗證並獲取完整用戶信息
User user = userService.authenticateAndGetUser(username, password);
if (user != null) {
// 2. 存入 Session(關鍵步驟)
session.setAttribute("currentUser", user);
// 可選:存入用戶 ID 便於快速獲取
session.setAttribute("userId", user.getId());
return "redirect:/dashboard";
} else {
model.addAttribute("error", "用戶名或密碼錯誤");
return "login";
}
}
@Transactional(readOnly = true)
public User authenticateAndGetUser(String username, String password) {
// 1. 根據用戶名查詢
User user = userMapper.selectByUsername(username);
if (user == null) return null;
// 2. 密碼驗證(生產環境必須用 BCrypt/SCrypt)
if (!passwordEncoder.matches(password, user.getPassword())) {
return null;
}
// 3. 可選:加載關聯數據(角色、權限、配置文件等)
user.setRoles(roleMapper.selectByUserId(user.getId()));
user.setProfile(profileMapper.selectByUserId(user.getId()));
// 4. 安全處理:清空敏感字段再存入 Session
user.setPassword(null);
return user;
}
<%-- 直接通過 EL 表達式訪問 --%>
歡迎,${sessionScope.currentUser.username}!
郵箱:${sessionScope.currentUser.email}
手機:${sessionScope.currentUser.phone}
<%-- 權限控制示例 --%>
<c:if test="${sessionScope.currentUser.roles.contains('ADMIN')}">
<a href="/admin">管理後台</a>
</c:if>
| 原則 | 說明 |
|---|---|
| 存對象而非散字段 | 維護性強,擴展方便,避免 Session 屬性污染 |
| 脫敏處理 | 密碼、鹽值、token 等敏感信息絕不存入 Session |
| 實現 Serializable | 支持 Session 集群/序列化持久化 |
| 設置過期時間 | web.xml 或 Spring Session 配置適當 timeout |
| 權限分離 | 角色/權限單獨加載,支持動態刷新 |
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
# application.yml
spring:
session:
store-type: redis
timeout: 30m
redis:
host: localhost
port: 6379
自動將 `HttpSession` 操作映射到 Redis,支持多實例部署、Session 共享、重啟不丟失。
標準做法:登錄驗證 → 查詢完整用戶對象 → 脫敏 → 存入 Session → 後續直接從 Session 獲取,配合攔截器/過濾器實現登錄檢查與用戶信息注入。