SurrealDB用户Scope无重复注册校验、登录鉴权失效问题咨询
问题
我创建了如下Scope:
DEFINE SCOPE user SESSION 1d SIGNUP ( CREATE user SET user = $user, pass = crypto::argon2::generate($pass) ) SIGNIN ( SELECT * FROM user WHERE user = $user AND crypto::argon2::compare(pass, $pass));
随后执行注册操作,请求体如下:
{ "ns": "test", "db": "test", "sc": "user", "email": "tobie@surrealdb.com", "pass": "some password", "marketing": true, "tags": [ "rust", "golang", "javascript" ] }
返回结果:
{ "code": 200, "details": "Authentication succeeded", "token": "eyJ0eXAiOiJKV1QiLCJhbGciOEQiI6InRlc3QiLCJTQyI6InVzZXIiLCJJRCI6InVzZXI6czFiN3JzcnlxNW9jdDVmM2FrdHEifQ.oy7ox2QCqNDAyZnvRmGPoU2t3QmzB38J67ynpRVPfd8nXfRw0RQPunQ04KTrtzfQeNHB5Zv8-nN0HrOuqxG78w" }
之后尝试登录,请求体:
{ "ns": "test", "db": "test", "sc": "user", "email": "tobie@surrealdb.com", "pass": "some password" }
登录成功返回200。但使用未注册的邮箱tobiedsfds2@surrealdb.com登录时,仍返回200成功响应;同时使用已注册的邮箱重复注册时,也能成功完成。请问这是什么原因?
分析与解决
核心问题1:请求参数与Scope变量不匹配
你的Scope定义里,SIGNUP和SIGNIN逻辑都用了$user变量,但实际注册、登录请求传递的是email字段,而非user字段。这会导致:
- 注册时,
$user取不到有效值,最终创建的user记录中user字段为空(或NULL) - 登录时,
$user同样无有效值,查询条件变成WHERE user = NULL AND ...,SurrealDB中NULL = NULL的判断会匹配所有user字段为空的记录,只要你传的密码和这些记录的哈希值匹配(你每次都用some password),就会返回登录成功。
核心问题2:缺少唯一约束允许重复注册
你的SIGNUP逻辑只是简单执行CREATE user,没有对用户标识字段(比如email)添加唯一约束,所以即使使用同一个邮箱,也能重复创建新的user记录。
修复方案
- 统一参数与字段名:把Scope中的
$user改为$email,和请求字段对应,同时调整存储字段:
DEFINE SCOPE user SESSION 1d SIGNUP ( CREATE user SET email = $email, pass = crypto::argon2::generate($pass) ) SIGNIN ( SELECT * FROM user WHERE email = $email AND crypto::argon2::compare(pass, $pass));
- 添加唯一约束:创建
user表时给email字段加唯一约束,从根源防止重复注册:
DEFINE TABLE user SCHEMAFULL; DEFINE FIELD email ON TABLE user TYPE string ASSERT $value IS UNIQUE; DEFINE FIELD pass ON TABLE user TYPE string;
也可以在SIGNUP逻辑中用CREATE IF NOT EXISTS临时规避,但表约束的方式更严谨:
SIGNUP ( CREATE IF NOT EXISTS user SET email = $email, pass = crypto::argon2::generate($pass) )
内容的提问来源于stack exchange,提问作者Shivam Sahil
相关产品推荐
相关产品推荐

