mysql 8.0 彻底移除了 password() 函数,调用即报 error 1305,因其源码中已物理删除;它不安全(无 salt 双 sha-1),且被插件化认证(如 caching_sha2_password)取代,密码哈希必须由服务端自动完成。

CRYPT函数在MySQL中并不存在
MySQL原生不提供CRYPT()函数,直接写SELECT CRYPT('password', 'salt');会报错FUNCTION CRYPT does not exist。PostgreSQL有crypt()(需加载pgcrypto扩展),SQLite和SQL Server则完全不支持。别在建表或INSERT里硬套这个函数名,它不是SQL标准函数。
MySQL推荐用SHA2 + CONCAT实现加盐哈希
MySQL 5.7+ 支持SHA2(),配合CONCAT()手动拼接盐值是可行且可控的做法。盐必须唯一(如用UUID或用户注册时间+ID生成),不能全局固定。
- 生成盐:
SELECT UUID();或CONCAT(UNIX_TIMESTAMP(), '-', user_id) - 存储时哈希:
INSERT INTO users (username, password_hash, salt) VALUES ('alice', SHA2(CONCAT('mypass123', 'a1b2c3'), 256), 'a1b2c3'); - 验证时重算:
SELECT id FROM users WHERE username = 'alice' AND password_hash = SHA2(CONCAT('input_pass', salt), 256);
注意:SHA2()第二个参数必须显式写256或512,省略会返回NULL;盐值必须和密码一起参与哈希,不能只哈希密码再拼盐。
PostgreSQL中使用pgcrypto的crypt()需手动启用
PostgreSQL默认不加载pgcrypto,执行crypt()前必须先运行CREATE EXTENSION IF NOT EXISTS pgcrypto;,否则报错function crypt(unknown, unknown) does not exist。
- 生成哈希:
INSERT INTO users (username, password_hash) VALUES ('bob', crypt('mypass123', gen_salt('bf')));(bf表示bcrypt) - 验证逻辑由数据库完成:
SELECT * FROM users WHERE username = 'bob' AND password_hash = crypt('input_pass', password_hash); -
gen_salt('bf')每次调用生成不同盐值,但crypt()能从已有哈希串中自动提取盐,所以验证时第二个参数传原password_hash即可
别用gen_salt('md5')——MD5已不安全,且PostgreSQL 14+已弃用该算法标识。
真正安全的方案不在SQL层做哈希
SQL函数缺乏对现代哈希算法(如Argon2、scrypt)的支持,且无法控制迭代次数、内存开销等关键参数。所有主流语言都有成熟库:bcrypt.hashpw()(Python)、password_hash()(PHP)、bcrypt.compare()(Node.js)。把哈希逻辑放在应用层,SQL只负责存取字符串。
如果非要在数据库里处理,至少确保:盐值字段类型为VARCHAR(64)以上(bcrypt哈希串约60字符),密码哈希字段用CHAR(60)或更大;不要用MD5()或SHA1(),它们抗碰撞能力已被攻破;别把盐存在配置文件或常量里——每个用户必须有独立盐值。










