2

我有一个存储登录数据的 Mysql 数据库。密码和盐保存为 sha512 哈希。现在,如果更改密码列中的值,我想实现一个条件,即盐必须更改,否则 mysql 命令无效。

CREATE TABLE loginData(
id int UNSIGNED SERIAL DEFAULT VALUE,
email varchar(64) NOT NULL,
password binary(64) NOT NULL,
salt binary(64) NOT NULL,
PRIMARY KEY(id))
ENGINE=InnoDB;

现在,我在考虑类似外键的完整性约束,但显然我不应该将密码和盐列连接为外键。有什么方法可以防止在Mysql端更新密码列 - 所以必须提供新的盐?仅在访问代码的一侧阻止它感觉不完整。

4

2 回答 2

0

除非您有多个系统访问数据库,否则我不会说仅在访问代码上阻止它是不完整的。您可以通过不授予管理员对表的适当写入权限来阻止管理员手动更新数据。

但是如果你必须在 MySQL 中强制执行,你可以考虑添加一个触发器(更新记录后运行的代码),但如果盐来自你的应用程序,这可能是不可行的。那么最好的选择是只通过存储过程(驻留在数据库中的代码)提供对表的访问,这会强制表的完整性。

http://dev.mysql.com/doc/refman/5.6/en/stored-programs-views.html

于 2012-12-04T19:33:33.820 回答
0

您可以做到的一种方法是不实际更新您的登录记录以更改密码,而是插入新记录。您需要更改架构以添加名为active或类似名称的 tinyint 字段名,以存储指示哪个是活动登录的标志。

然后,您可以在电子邮件/盐和电子邮件/密码上添加唯一索引,以强制这些组合具有唯一性,这意味着您永远不会输入相同盐的相同电子邮件,也永远不会输入相同的电子邮件/密码组合。任何具有相同电子邮件/盐或电子邮件/密码的插入都会失败。如果您不需要密码唯一性(您显然可以不添加电子邮件/密码唯一索引)。

当您查找登录以实际执行凭据检查时,您只需添加WHERE active = 1到查询过滤器中。

您可能还希望将插入新盐和密码记录并将旧行更新到active = 0事务中的操作包装起来,以便整个事务成功或失败,从而防止用户在没有登录的情况下卡住的情况。

于 2012-12-04T19:09:10.247 回答