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

Java代码修复Broken Access Control 实现用户权限内数据访问咨询

Java代码失效访问控制修复方案

你的现有代码核心问题是仅校验了用户登录状态,未验证请求的accountId是否属于当前登录用户,恶意用户登录后只要修改传入的accountId参数,就能遍历查询所有用户的账户信息,属于典型的失效访问控制漏洞。

具体修改步骤

  • JWT签发阶段必须存入当前登录用户的唯一ID(建议字段名为login_user_id),原JWT仅存登录状态缺少身份标识,无法做权限校验
  • 解析JWT后优先取出登录用户ID,和传入的accountId做强制比对,不一致直接抛出权限不足异常,终止后续流程
  • 额外修复原代码的SQL注入风险,将Statement替换为PreparedStatement,避免SQL拼接导致的注入攻击
  • 所有权限校验通过后再执行数据库查询操作,减少不必要的资源消耗

修复后完整代码

import java.sql.*;
import java.util.*;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.Claims;

class LoggedOutException extends Exception {
    public LoggedOutException(String message) {
        super(message);
    }
}

// 新增权限不足异常
class PermissionDeniedException extends Exception {
    public PermissionDeniedException(String message) {
        super(message);
    }
}

public class External{

    public static HashMap<String, String> accountLookup(String accountId, String jwt) throws Exception{

        if (jwt == null) {
            throw new LoggedOutException("User is not logged in");
        }
        Claims claims = Jwts.parser()
                .setSigningKey("Key".getBytes("UTF-8"))
                .parseClaimsJws(jwt).getBody();

        // 校验登录状态
        if (!"true".equals(claims.get("logged_in").toString())) {
            throw new LoggedOutException("User is not logged in");
        }

        // 核心访问控制校验:取出JWT中存储的登录用户ID,和请求的accountId比对
        String loginUserId = claims.get("login_user_id").toString();
        if (!accountId.equals(loginUserId)) {
            throw new PermissionDeniedException("You have no permission to access this account");
        }

        Class.forName("com.mysql.jdbc.Driver");
        Connection con = DriverManager.getConnection("jdbc:mysql://mysql:3306/BankApp?useSSL=false", "root", "letmein");

        // 替换Statement为PreparedStatement修复SQL注入
        PreparedStatement userStmt = con.prepareStatement("SELECT username FROM tbl_user WHERE id = ?");
        userStmt.setString(1, accountId);
        ResultSet rs = userStmt.executeQuery();

        if (!rs.next()) {
            con.close();
            throw new Exception("Account not found");
        }

        String user = rs.getString("username");
        PreparedStatement accountStmt = con.prepareStatement("SELECT balance, dob FROM tbl_account WHERE user_id = ?");
        accountStmt.setString(1, accountId);
        rs = accountStmt.executeQuery();
        HashMap<String, String> results = new HashMap<>();

        if(rs.next()){
            results.put("balance", rs.getString("balance"));
            results.put("dob", rs.getString("dob"));
            results.put("username", user);
        }
        con.close();

        return results;
    }
}

额外说明

如果业务存在管理员可查询所有用户信息的场景,可在JWT中额外存入user_role字段,校验时如果是管理员角色则跳过accountId比对逻辑即可。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 22:09:04