java安全问题源于开发疏忽而非语言缺陷,需在关键节点写对代码:sql注入用preparedstatement、xss输出前html编码、禁用不安全反序列化、密码盐值哈希存储。

Java 开发中常见的安全性问题,大多不是由语言本身引起,而是源于开发过程中的疏忽或对安全机制理解不足。真正有效的预防,不靠理论堆砌,而靠在关键节点写对代码——比如参数化查询、输出编码、禁用危险反序列化、盐值哈希密码等。下面直接列出最常踩坑的几类问题及对应可落地的代码级应对方式。
SQL注入:别拼字符串,用 PreparedStatement
拼接 SQL 是高危操作,哪怕只有一处漏掉校验,攻击者就能用 ' OR '1'='1 绕过登录。PreparedStatement 不仅能隔离输入,还能提升执行效率。
- ❌ 错误写法:
String sql = "SELECT * FROM users WHERE name = '" + name + "'"; - ✅ 正确写法:
String sql = "SELECT * FROM users WHERE name = ?";<br>try (PreparedStatement ps = conn.prepareStatement(sql)) {<br> ps.setString(1, name);<br> ResultSet rs = ps.executeQuery();<br>} - 额外建议:ORM 框架(如 MyBatis 的 #{}、Hibernate 的 JPQL)默认参数化,也比 ${} 或原生 SQL 更安全
XSS 攻击:输出前必须 HTML 编码
用户提交的 <script>alert(1)</script> 如果原样输出到页面,就会在别人浏览器里执行。防御核心不是“过滤输入”,而是“编码输出”——因为同一段数据可能被渲染在 HTML、JS、URL 等不同上下文中。
- ✅ 推荐使用 OWASP Java Encoder:
import org.owasp.encoder.Encode;<br>String safeOutput = Encode.forHtml(userInput); // 用于 HTML 内容<br>String safeJs = Encode.forJavaScript(userInput); // 用于 JS 字符串
- ⚠️ 注意:JSP 的
<out value="${param.input}"></out>或 Thymeleaf 的th:text="${input}"默认已做 HTML 编码;但手动拼接response.getWriter().write(...)时务必自行编码
不安全反序列化:默认禁用,必要时加白名单
Java 原生 ObjectInputStream 反序列化任意字节流,可能触发链式 gadget(如 Commons Collections)执行任意代码。Spring Boot 2.3+ 已默认禁用,但老项目或自定义通信仍需警惕。
- ❌ 避免:
ObjectInputStream ois = new ObjectInputStream(inputStream);<br>Object obj = ois.readObject(); // 危险!
- ✅ 安全替代方案:
• 用 JSON(Jackson/Gson)代替二进制序列化;
• 若必须反序列化,使用ValidatingObjectInputStream并注册允许的类:ValidatingObjectInputStream vois = new ValidatingObjectInputStream(inputStream);<br>vois.accept(MySafeClass.class);
敏感信息泄露:日志不打明文,密码必须加盐哈希
生产环境打印异常堆栈或日志里记录 password=123456,等于把钥匙放在门垫下。密码更不能明文存库,也不该用 MD5/SHA-1 这类无盐、无迭代的弱哈希。
- ✅ 密码存储示例(使用 PBKDF2):
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");<br>KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, 65536, 128);<br>byte[] hash = factory.generateSecret(spec).getEncoded(); - ✅ 日志处理建议:
• 使用 Logback/Log4j2 的%replace或自定义 converter 脱敏字段;
• Spring Boot 中配置logging.pattern.console=%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %replace{%msg}{'password=\S+', 'password=***'}%n
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











