整体登录流程概览
1.1 后端组件总览
PreAuthLoginEndpoint 预登录端点:
处理
GET /login请求。调用
CryptoService.readPublicKey()读取 RSA 公钥。调用
AuthProviderService查询启用的登录方式(本地表单、社交登录等)。获取全局站点信息,最后渲染 Thymeleaf 模板(登录页 HTML)。
对前端的意义:
/login页面是我们能看到的唯一“官方视角”,公钥、CSRF、登录方式等信息都在这里以 HTML/JS 的形式暴露出来。
CryptoService(接口) / RsaKeyService(实现)
管理 RSA 公私钥对。
readPublicKey():给PreAuthLoginEndpoint用,把公钥塞到前端页面。decrypt(byte[]):给登录链路用,解密前端传来的密文密码。
对前端的意义:
如果站点启用了“前端加密 + 后端解密”的模式,我们必须用与后端一致的公钥和算法才能登录成功。
AuthProviderService
负责登录方式(本地用户名密码、第三方 OAuth 等)的查询与过滤。
结果在
/login页面中以按钮、链接的形式体现。
LoginSecurityConfigurer + AuthenticationWebFilter
在 Spring Security 过滤器链中注册表单登录过滤器
AuthenticationWebFilter。统一处理
POST /login请求,进入认证流程。对前端的意义:
不管是原始表单提交,还是我们自定义的
fetch('/login'),最终都会走到这个过滤器链上。
LoginAuthenticationConverter
从请求(表单或 JSON)中读取:
username;password(明文或密文);_csrf等字段。如果启用了前端加密:
先调用
CryptoService.decrypt()把密文解密成明文密码;然后把用户名和明文密码交给认证管理器。
对前端的意义:
决定了“密码字段到底是明文还是密文”这件事怎么处理——只要我们按照它接受的格式提交,就不需要改任何后端代码。
DefaultUserDetailService / UserService / RoleService
加载用户信息和角色列表;
封装为
HaloUserDetails,支持标记是否启用 2FA。对前端的意义:
走到这一步,说明我们的请求已经成功通过了表单解析与密码解密这一关。
UsernamePasswordHandler
处理登录成功或失败;
可以选择:
返回 JSON;
或者重定向到某个页面;
配合
RememberMeRequestCache等组件做“记住我”之类的增强。对前端的意义:
决定了我们的
fetch('/login')最终会得到 JSON 还是重定向,直接影响弹窗里怎么展示结果。1.2 模块关系图
1.3 总结
/login 页面:
不只是一个普通 HTML,而是后端"打包好的登录环境快照";
里面**可能**包含
publicKey变量_csrf、可选的社交登录按钮等。
POST /login:
不关心请求是从弹窗还是原生页面发出的;
只关心字段名和格式是否符合
LoginAuthenticationConverter的预期;密码既可以是明文(由后端直接校验),也可以是密文(由后端用私钥解密)。
这意味着:
只要我们在前端构造出一份“看起来像
/login表单提交”的请求,就可以无侵入地接入整条登录链路。
提供一个截图:
默认评论
Halo系统提供的评论