破茧成蝶:Java后端从0到资深工程师的进阶之路(九)安全篇——构筑坚不可摧的后端防线

安全是系统的生命线。一个微小的漏洞,可能导致用户数据泄露、服务器被入侵、业务遭受重创。很多开发者关注功能实现,却忽视了安全防护,直到被攻击才追悔莫及。本篇将带你全面了解后端安全的常见威胁与防御手段,从认证授权、数据加密到漏洞防护,为你的系统穿上“铠甲”。


写在前面

我曾经接手过一个项目,用户的密码以明文存储在数据库中;另一个项目,接口没有做任何权限校验,任意用户都能调用管理员接口删除数据。这些看似低级的错误,却真实存在于不少生产系统中。安全不是“可选项”,而是每个后端开发者的必备素养。

本篇文章核心内容:

  • 认证与授权:从 Session 到 JWT,OAuth2 与 RBAC 模型。
  • 数据安全:密码加密、传输加密、敏感数据脱敏。
  • 常见漏洞防护:SQL 注入、XSS、CSRF、SSRF、文件上传漏洞。
  • 安全审计与日志:操作日志、异常监控、入侵检测。

掌握这些,你将能构建一个经得起考验的安全系统。


一、认证与授权:把好系统第一关

1.1 认证方案演进:从 Session 到 JWT

1.1.1 基于 Session 的传统认证
  • 流程:用户登录 → 服务端创建 Session 并存入内存/Redis → 返回 SessionId(Cookie)→ 后续请求携带 Cookie 验证。
  • 优点:服务端可主动失效,安全性高。
  • 缺点:分布式环境下需要共享 Session 存储(如 Spring Session + Redis);移动端不友好。
1.1.2 基于 Token 的认证(JWT)

JWT(JSON Web Token)是一种自包含的 Token,由三部分组成:Header.Payload.Signature

优点

  • 无状态,服务端不需要存储 Token,适合分布式系统。
  • 移动端友好,可放在 Header 或 URL 参数中。

缺点

  • Token 一旦签发,服务端无法主动使其失效(除非引入黑名单)。
  • Payload 信息是 Base64 编码,不要存放敏感数据

Spring Boot 集成 JWT 示例

// 生成 JWT
public String generateToken(String userId) {
    return Jwts.builder()
            .setSubject(userId)
            .setIssuedAt(new Date())
            .setExpiration(new Date(System.currentTimeMillis() + 3600000)) // 1小时
            .signWith(SignatureAlgorithm.HS256, secretKey)
            .compact();
}

// 解析 JWT
public Claims parseToken(String token) {
    return Jwts.parser()
            .setSigningKey(secretKey)
            .parseClaimsJws(token)
            .getBody();
}

Token 续期策略

  • 滑动过期:每次请求返回新的 Token。
  • 双 Token 机制:Access Token(短期) + Refresh Token(长期),Refresh Token 存储在 Redis 中,可主动撤销。

1.2 OAuth2 与单点登录(SSO)

场景:允许用户使用微信、GitHub 登录,或企业内部统一认证。

核心角色:资源所有者、客户端、授权服务器、资源服务器。

简化流程(授权码模式):

  1. 用户点击“微信登录”,跳转到微信授权页。
  2. 用户同意授权后,微信回调带上授权码。
  3. 后端用授权码换取 Access Token。
  4. 用 Access Token 获取用户信息,完成登录。

Spring Security OAuth2 已迁移至 Spring Authorization Server,推荐使用。


1.3 RBAC 权限模型

RBAC(Role-Based Access Control)通过“用户 → 角色 → 权限”的映射实现权限管理。

数据库设计

CREATE TABLE `user` (id bigint PRIMARY KEY, username varchar(50));
CREATE TABLE `role` (id bigint PRIMARY KEY, name varchar(50));
CREATE TABLE `permission` (id bigint PRIMARY KEY, code varchar(100), resource varchar(200));
CREATE TABLE `user_role` (user_id bigint, role_id bigint);
CREATE TABLE `role_permission` (role_id bigint, permission_id bigint);

Spring Security 实现

  • 自定义 UserDetailsService 加载用户角色和权限。
  • 使用 @PreAuthorize("hasAuthority('order:create')") 注解方法级权限控制。

二、数据安全:加密与脱敏

2.1 密码加密:永远不要存明文

原则

  • 使用 单向散列函数(如 bcrypt、PBKDF2、argon2),不可逆。
  • 必须加 (salt),且每个用户盐值不同。

Spring Security 推荐 BCryptPasswordEncoder

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder(); // 自动生成盐
}

// 存储:encoder.encode(rawPassword)
// 验证:encoder.matches(rawPassword, encodedPassword)

2.2 传输加密:HTTPS 与 TLS

  • 生产环境必须启用 HTTPS,防止中间人攻击。
  • 使用 Let’s Encrypt 免费证书,或购买商业证书。
  • 配置 HSTS(HTTP Strict Transport Security)强制浏览器使用 HTTPS。

2.3 敏感数据脱敏

已在第四篇详细讲解,核心是通过 Jackson 注解自定义序列化,对手机号、身份证、邮箱等进行脱敏。

补充:日志中也要脱敏。使用 Logback 的 replace 功能:

<pattern>%msg%n</pattern>
<replace>
    <from>(\d{3})\d{4}(\d{4})</from>
    <to>$1****$2</to>
</replace>

三、常见 Web 漏洞与防护

3.1 SQL 注入

原理:拼接用户输入到 SQL 语句中,导致恶意代码执行。

示例"select * from user where name = '" + name + "'",若 name 传入 ' or '1'='1,则查询所有用户。

防护

  • 使用 预编译语句PreparedStatement)或 ORM(MyBatis 使用 #{} 而非 ${})。
  • 对输入做白名单校验,如排序字段只能为 idname 等。

3.2 XSS(跨站脚本攻击)

原理:攻击者注入恶意脚本,当其他用户浏览时执行。

示例:评论框输入 <script>alert('xss')</script>,其他用户查看评论时弹出窗口。

防护

  • 输出时转义 HTML 实体(<&lt;)。
  • Spring 中可使用 HtmlUtils.htmlEscape(text)
  • 设置 HTTP 响应头 X-XSS-Protection: 1; mode=block

3.3 CSRF(跨站请求伪造)

原理:诱导用户点击恶意链接,利用用户的登录态发起非预期请求。

示例:用户在银行网站登录后,访问恶意网站,恶意网站自动提交转账请求。

防护

  • 使用 CSRF Token:服务端生成随机 Token 嵌入表单,请求时校验。
  • 同源检查:校验 Referer 或 Origin 头。
  • Spring Security 默认开启 CSRF 防护(对 PUT/POST/DELETE 生效)。

3.4 SSRF(服务端请求伪造)

原理:攻击者利用服务端发起请求的功能,访问内网资源或绕过防火墙。

示例:接口 fetch?url=http://internal-admin/delete,可删除内部数据。

防护

  • 限制请求的 IP 为公网地址,禁止访问内网段(如 127.0.0.1、10.0.0.0/8)。
  • 白名单校验 URL 的域名。

3.5 文件上传漏洞

风险:上传可执行脚本(JSP、PHP)到 Web 目录,导致远程代码执行。

防护

  • 校验文件类型:使用 Files.probeContentType 获取 MIME 类型,不要信任文件扩展名。
  • 将文件存储到 Web 目录之外,通过接口读取并设置响应头。
  • 限制文件大小(如 10MB)。
  • 重命名文件,避免路径遍历攻击(如 ../../config/application.yml)。

四、安全审计与日志

4.1 操作日志记录

记录关键操作(登录、权限变更、删除数据)的审计日志,包含:时间、操作人、IP、操作内容、结果。

实现:使用 AOP(第二篇)或事件监听机制。

4.2 异常监控与告警

  • 安全相关异常(多次登录失败、越权访问)应触发告警。
  • 使用 ELK 或 Splunk 集中分析日志,设置规则检测可疑行为(如短时间内大量请求)。

4.3 入侵检测思路

  • 异常地理登录:同一账户短时间内从不同城市登录。
  • 暴力破解:同一 IP 登录失败超过阈值,临时封禁。
  • 爬虫识别:通过 User-Agent、访问频率、验证码等手段。

总结

本篇我们构建了后端安全的完整防线:

  1. 认证授权:从 Session 到 JWT,OAuth2 集成第三方登录,RBAC 权限模型。
  2. 数据安全:密码 bcrypt 加密,HTTPS 传输,敏感数据脱敏。
  3. 漏洞防护:SQL 注入、XSS、CSRF、SSRF、文件上传的防御措施。
  4. 审计监控:操作日志、异常告警、入侵检测。

安全没有终点,需要持续关注新型漏洞并定期进行渗透测试。将安全编码规范融入日常开发,才能防患于未然。

全系列回顾

  • 第一篇:筑基篇——工程骨架与配置管理。
  • 第二篇:内功篇——Spring 原理与 AOP。
  • 第三篇:数据库篇——索引优化与事务。
  • 第四篇:接口篇——高可用 API 设计。
  • 第五篇:并发篇——线程池与 JUC。
  • 第六篇:中间件篇——缓存与消息队列。
  • 第七篇:架构篇——可观测性、质量、云原生。
  • 第八篇:性能篇——性能优化与线上故障排查。
  • 第九篇:安全篇——后端安全防护。

最后一篇(第十篇)将作为 总结与职业发展篇,为整个系列画上圆满句号。


如果觉得本文对你有帮助,欢迎点赞、收藏、评论,你的支持是我持续创作的动力!

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐