You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java Web开发TODO列表如何实现不同用户待办数据隔离

待办应用跨账号数据隔离实现方案

你遇到的不同账号看到相同待办内容的问题,核心原因是待办数据没有和所属用户做绑定,数据查询、操作时没有按用户身份做过滤,按照以下步骤改造即可实现用户只能查看、操作自己的待办内容:

相关参考截图如下:
待办页面截图1
待办页面截图2

改造步骤

1. 调整数据库表结构

首先给todo表新增用户关联字段,标记每条待办的所属用户:

-- 新增user_id字段存储待办所属用户的ID
ALTER TABLE todo ADD COLUMN user_id INT NOT NULL COMMENT '所属用户ID';
-- 给user_id加索引提升查询效率
ALTER TABLE todo ADD INDEX idx_user_id(user_id);

前提:你需要先完成用户登录模块开发,用户登录校验通过后,将当前登录用户的ID存入服务端Session。

2. 扩展Model实体类

给待办Model类新增userId属性及对应的get/set方法:

public class Model {
    private int ID;
    private String TODO;
    private int userId; // 新增:所属用户ID

    public Model() {
        super();
    }

    public Model(int iD, String tODO, int userId) {
        super();
        ID = iD;
        TODO = tODO;
        this.userId = userId;
    }

    public int getID() {
        return ID;
    }

    public void setID(int iD) {
        ID = iD;
    }

    public String getTODO() {
        return TODO;
    }

    public void setTODO(String tODO) {
        TODO = tODO;
    }

    // 新增userId的get/set方法
    public int getUserId() {
        return userId;
    }

    public void setUserId(int userId) {
        this.userId = userId;
    }
}

3. 改造Dao层数据操作逻辑

所有待办相关的增删改查SQL,都必须带上user_id作为过滤条件,从数据层避免越权访问:

public class Dao {
    private final static String url = "jdbc:mysql://localhost:3306/todolist";
    private final static String user = "root";
    private final static String password = "";
    private final static String dbloader = "com.mysql.jdbc.Driver";
    // 修改新增待办SQL,写入时绑定user_id
    private final static String ADD = "INSERT INTO `todo`(`TODO`,`user_id`) VALUES (?,?)";
    // 新增:查询指定用户的待办列表SQL
    private final static String QUERY_USER_TODOS = "SELECT ID, TODO, user_id FROM todo WHERE user_id = ?";
    // 新增:删除待办时必须同时校验待办ID和所属用户ID,防止越权删除
    private final static String DELETE_TODO = "DELETE FROM todo WHERE ID = ? AND user_id = ?";
    // 新增:更新待办时同样要校验用户ID
    private final static String UPDATE_TODO = "UPDATE todo SET TODO = ? WHERE ID = ? AND user_id = ?";

    public static void Driver(String dbloader) {
        try {
            Class.forName(dbloader);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Connection getConnection() {
        Connection con = null;
        try {
            con = DriverManager.getConnection(url, user, password);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return con;
    }

    public static int ADDTODO(Model mod) {
        int i = 0;
        Connection con = null;
        PreparedStatement pst = null;
        try {
            Driver(dbloader);
            con = getConnection();
            pst = con.prepareStatement(ADD);
            pst.setString(1, mod.getTODO());
            pst.setInt(2, mod.getUserId()); // 绑定当前用户ID
            i = pst.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 补全资源释放逻辑,避免数据库连接泄漏
            try {
                if (pst != null) pst.close();
                if (con != null) con.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return i;
    }

    // 新增:查询指定用户的待办列表方法
    public static List<Model> getUserTodoList(int userId) {
        List<Model> todoList = new ArrayList<>();
        Connection con = null;
        PreparedStatement pst = null;
        ResultSet rs = null;
        try {
            Driver(dbloader);
            con = getConnection();
            pst = con.prepareStatement(QUERY_USER_TODOS);
            pst.setInt(1, userId);
            rs = pst.executeQuery();
            while (rs.next()) {
                Model item = new Model();
                item.setID(rs.getInt("ID"));
                item.setTODO(rs.getString("TODO"));
                item.setUserId(rs.getInt("user_id"));
                todoList.add(item);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 释放资源
            try {
                if (rs != null) rs.close();
                if (pst != null) pst.close();
                if (con != null) con.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return todoList;
    }
}

4. 改造Servlet层逻辑

从服务端Session中获取当前登录用户ID,禁止从前端请求参数中接收用户ID(防止参数篡改越权):

protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
    // 登录校验:未登录直接跳转登录页
    HttpSession session = request.getSession();
    Object loginUserIdObj = session.getAttribute("loginUserId");
    if (loginUserIdObj == null) {
        response.sendRedirect("login.jsp");
        return;
    }
    int loginUserId = (Integer) loginUserIdObj;

    String todoContent = request.getParameter("todo");
    Model mod = new Model();
    mod.setTODO(todoContent);
    mod.setUserId(loginUserId); // 给新待办绑定当前登录用户ID

    Dao dao = new Dao();
    int res = dao.ADDTODO(mod);
    if (res > 0) {
        response.sendRedirect("Userpage.jsp");
    }
}

5. 调整Userpage.jsp数据加载逻辑

页面加载待办列表时,调用getUserTodoList方法传入当前登录用户ID,只查询当前用户自己的待办数据渲染到表格,禁止查询全表待办数据。
你提供的原有页面表单代码如下,不需要大改,只需要把后端查询到的当前用户待办列表循环渲染到表格区域即可:

<form action="Addtodo" method="post">
    <div class="add-items d-flex"> 
        <input type="text" class="form-control todo-list-input" name="todo" placeholder="What do you need to do today?"> 
        <button type="submit" class="btn btn-success btn-lg btn-block" value="add" >Add</button>
    </div>
</form>

核心注意事项

  • 所有待办的增、删、改、查操作,都必须以服务端Session中存储的登录用户ID作为过滤条件,绝对不能信任前端传来的用户ID参数
  • 删除、修改待办时,必须同时校验待办ID和当前用户ID,避免用户通过修改待办ID参数操作其他人的待办
  • JDBC操作后必须及时释放Connection、PreparedStatement、ResultSet资源,否则会出现数据库连接泄漏,服务运行一段时间后会无法连接数据库

内容的提问来源于stack exchange,提问作者Benjie Alcontin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 16:18:20