首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

JSP/Servlet 登錄後將用戶完整信息存入 Session 的標準做法

     編輯:程式設計疑難解答

核心流程

登錄驗證成功後,從數據庫查詢用戶完整信息構建用戶對象,存入 Session,而非僅存用戶名。

完整實現步驟

1. 用戶實體類

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
}

2. 登錄 Action/Controller 處理

@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";
    }
}

3. Service 層實現

@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;
}

4. JSP 頁面獲取用戶信息

<%-- 直接通過 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
權限分離角色/權限單獨加載,支持動態刷新

進階:Spring Session + Redis 實現分布式 Session

<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 ID → Session Fixation 攻擊風險

標準做法:登錄驗證 → 查詢完整用戶對象 → 脫敏 → 存入 Session → 後續直接從 Session 獲取,配合攔截器/過濾器實現登錄檢查與用戶信息注入。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved