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
相关产品推荐
相关产品推荐

