如何手搓一个Spring Security

"手搓"一个 Security 框架,实际上是为了透彻理解 Spring Security 等成熟框架背后的底层原理(如认证、授权、拦截机制)。基于现有的技术分析和实战案例,我们可以将这个过程简化为一个"极简版权限控制框架"的开发。这通常被称为"造轮子"或"徒手写安全框架"。

以下是结合 Java Web 技术栈,教你如何一步步"手搓"一个简易 Security 框架的核心步骤:

🧱 第一阶段:核心组件设计 (搭架子)

在 Spring Security 中,有 UserDetailsUserDetailsService 等概念。我们要先定义自己的核心模型。

  1. 定义用户实体 (User)

模拟框架中的 UserDetails

包含属性:用户名、密码、权限列表(例如 ["admin", "user"])。

  1. 定义认证服务 (AuthenticationService)

模拟框架中的 UserDetailsService

逻辑: 接收前端传来的用户名密码,与数据库(初期可用 Map 模拟)中的数据比对。

功能: 如果匹配成功,生成一个"登录凭证"(可以是 SessionId 或者简单的 Token 对象)。

🚧 第二阶段:拦截机制 (立屏障)

这是安全框架的"大门",所有请求必须先经过这里。

  1. 使用过滤器 (Filter) 或 拦截器 (Interceptor)

在请求到达 Controller 之前进行拦截。

排除路径: 放行登录页(/login)、静态资源、注册接口。

拦截路径: 拦截所有需要权限的接口(如 /admin/**, `/user/**)。

  1. 实现"认证"逻辑 (Authentication)

检查请求中是否携带了凭证(Cookie 中的 SessionId 或 Header 中的 Token)。

如果没有凭证,返回 401 Unauthorized 或重定向到登录页。

如果有凭证,去 Redis 或内存中校验该凭证是否有效(是否过期、是否被注销)。

🔑 第三阶段:授权逻辑 (分权限)

认证通过后,还要看用户有没有资格执行这个操作。

  1. 权限匹配

从凭证中获取当前用户的权限列表。

获取当前请求的 URL 或 方法名。

逻辑判断: 比如,请求 /admin/delete 需要 ROLE_ADMIN 权限。如果用户权限列表中包含该角色,则放行;否则返回 403 Forbidden

  1. 模拟注解功能

你可以通过 Java 反射机制,读取 Controller 方法上的自定义注解(例如 @RequireRole("ADMIN")),然后进行逻辑判断。

💻 第四阶段:代码实战 (极简版伪代码)

这里参考了常见的"徒手写 Security"教学案例,给出一个简化的逻辑流程:

1. 模拟用户登录 (认证)
java 复制代码
// 简化的伪代码
@PostMapping("/login")
public String login(String username, String password, HttpSession session) {
    // 1. 校验用户名密码 (模拟数据库查询)
    if ("admin".equals(username) && "123456".equals(password)) {
        // 2. 登录成功,将用户信息存入 Session
        session.setAttribute("user", new User("admin", Arrays.asList("admin", "user")));
        return "login success";
    }
    throw new RuntimeException("用户名或密码错误");
}
2. 拦截器进行权限校验 (授权)
java 复制代码
// 实现 HandlerInterceptor 接口
public class AuthInterceptor implements HandlerInterceptor {
    
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        
        // 1. 获取 Session
        HttpSession session = request.getSession();
        User user = (User) session.getAttribute("user");
        
        // 2. 如果用户未登录
        if (user == null) {
            response.sendRedirect("/login"); 
            return false;
        }
        
        // 3. 权限校验逻辑 (例如:如果是访问 /admin 路径,需要 admin 角色)
        String uri = request.getRequestURI();
        if (uri.startsWith("/admin") && !user.getRoles().contains("admin")) {
            response.sendError(403, "权限不足");
            return false;
        }
        
        // 4. 校验通过,放行
        return true;
    }
}

🚀 第五阶段:进阶功能 (对标 Spring Security)

当你完成了上述基础流程,可以尝试添加以下功能来提升"逼格":

集成 Redis: 将 Session 存储在 Redis 中,实现分布式环境下的统一登录状态管理。

实现 JWT: 不使用 Session,改为生成 JWT Token,实现无状态认证。

方法级安全: 使用 AOP 切面,拦截带有特定注解(如@PreAuthorize),实现细粒度的控制。

CSRF 防护: 增加 Token 校验,防止跨站请求伪造攻击。

📌 注意点

1、密码存储必须加盐哈希

2、必须合理配置空闲超时和绝对超时时间

3、必须添加默认拒绝规则,必须防止越权访问

4、使用AOP必须主要拦截器失效的情况

5、注意路径匹配漏洞

6、记录审计、防止SQL注入

📌 总结

"手搓" Security 框架的核心在于理解 "过滤器链" 和 "领域模型"。

Spring Security 很复杂,因为它考虑了各种企业级场景(LDAP、OAuth2、RememberMe )。

你自己写的很简单,但只要包含了 "拦截请求 -> 校验身份 -> 校验权限 -> 放行/拒绝" 这一流程,你就已经掌握了其最核心的原理。

相关推荐
csdn_aspnet4 分钟前
ASP.NET Core 中的依赖注入
后端·asp.net·di·.net core
sheji526114 分钟前
JSP基于信息安全的读书网站79f9s--程序+源码+数据库+调试部署+开发环境
java·开发语言·数据库·算法
毕设源码-邱学长15 分钟前
【开题答辩全过程】以 基于Java Web的电子商务网站的用户行为分析与个性化推荐系统为例,包含答辩的问题和答案
java·开发语言
摇滚侠30 分钟前
Java项目教程《尚庭公寓》java项目从开发到部署,技术储备,MybatisPlus、MybatisX
java·开发语言
€81142 分钟前
Java入门级教程24——Vert.x的学习
java·开发语言·学习·thymeleaf·数据库操作·vert.x的路由处理机制·datadex实战
Mr_star_galaxy1 小时前
【JAVA】经典图书管理系统的实现
java
昊坤说不出的梦1 小时前
【实战】监控上下文切换及其优化方案
java·后端
疯狂踩坑人1 小时前
【Python版 2026 从零学Langchain 1.x】(二)结构化输出和工具调用
后端·python·langchain
今天_也很困2 小时前
LeetCode热题100-560. 和为 K 的子数组
java·算法·leetcode
在繁华处2 小时前
线程进阶: 无人机自动防空平台开发教程V2
java·无人机