Error: SASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a string
我在堆栈溢出中寻找了一些解决方案,许多人说这将是一个dotenv问题,但在我的情况下,应用程序在没有对dotenv进行任何修改之前正常工作,我已经尝试过以其他方式导入,错误仍在继续,所以我相信这是一个typeORM错误。
数据库配置
import { DataSource } from "typeorm"
import { User } from "../entities/User"
export const AppDataSource = new DataSource({
type: "postgres",
host: process.env.DATABASE_HOST,
port: 5432,
username: process.env.DATABASE_USERNAME,
password: process.env.DATABASE_PASSWORD,
database: process.env.DATABASE_NAME,
synchronize: true,
logging: true,
entities: [User],
subscribers: [],
migrations: [],
})
实体用户
import { BeforeInsert, BeforeUpdate, Column, Entity, PrimaryGeneratedColumn } from "typeorm";
import bcrypt from 'bcryptjs';
@Entity('users')
export class User {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column()
username: string;
@Column()
email: string;
@Column()
password: string;
@BeforeInsert()
@BeforeUpdate()
hashPassword() {
this.password = bcrypt.hashSync(this.password, 8);
}
}
应用
import express from 'express';
import cors from 'cors';
import bodyParser from 'body-parser';
import dotenv from 'dotenv';
import 'reflect-metadata';
import userRoutes from './src/routes/UserRoutes';
dotenv.config();
const app = express();
app.use(express.json());
app.use(cors());
app.use(bodyParser());
app.use('/user', userRoutes)
export default app;
服务器
import app from './app';
import { AppDataSource } from './src/database/Config';
async function connection() {
const port = process.env.PORT;
try {
await AppDataSource.initialize();
console.log('Database connected! ');
app.listen(port);
console.log(`Listening on port ${port}`)
} catch (error) {
console.log(error);
}
}
connection();
在网上搜索了几天的解决方案后(没有…直到现在),我通过反复试验找到了自己的。
为什么会这样
尽管有些人说dotenv或者你的.env文件是问题,根本原因不是客户端而是服务器端,本地配置疏忽与postgres。
Postgres默认使用本地连接的对等认证方法,同时Node的pg软件包使用sam -sha-256(错误地假设您正在连接到远程服务器)。
这会导致错误,因为Node尝试向服务器发送临时身份验证请求,尽管服务器已经通过peer方法验证了应用程序。
这也是为什么你可以连接到数据库,但仍然得到错误。
Node发送一个scram请求,该请求被消耗,但未被服务器使用,Node看到响应并假设消耗的密码为空,引发上面的错误。
解决方案是什么?
首先,确保设置了postgres帐户密码。如果您的postgres帐户密码为空,也会导致相同的错误。如果您在第一次配置postgres时执行了此操作,则可以跳过此操作。
请切换到您的postgres帐户,访问数据库"postgres"然后将密码更改为非null
sudo su postgres
psql postgres
password
密码设置完成后,需要修改postgres的服务端认证方式。
编辑pg_hba.conf文件
/etc/postgresql/15/主/pg_hba.conf
使所有本地/主机连接都使用sam -sha-256认证方法。
默认情况下,
local all postgres peer
和
local all all peer
将具有peer身份验证方法。
对于其他本地和主机策略默认设置相同的方法。这个peer方法是导致错误的原因。
通过将方法从peer更改为sam -sha-256来修复此问题
# Database administrative login by Unix domain socket
local all postgres scram-sha-256
# TYPE DATABASE USER ADDRESS METHOD
# "local" is for Unix domain socket connections only
local all all scram-sha-256
# IPv4 local connections:
host all all 127.0.0.1/32 scram-sha-256
# IPv6 local connections:
host all all ::1/128 scram-sha-256
# Allow replication connections from localhost, by a user with the
# replication privilege.
local replication all scram-sha-256
host replication all 127.0.0.1/32 scram-sha-256
host replication all ::1/128 scram-sha-256`
如果是peer,将其改为sam -sha-256
设置完成后,退出postgres帐户,重新启动postgresql进程,重新加载配置
exit
sudo systemctl restart postgresql
现在,在你的Node应用中,使用一个连接对象或者你的环境变量来连接。
对于.env,确保您的变量名称与这里列出的默认Postgres名称一致。
例如,默认密码环境变量应为PGPASSWORD. 在。env文件中,密码应该是
PGPASSWORD = "MyPassword"
对于连接对象方法,创建一个对象并将其提供给您的新客户端(ObjectHere)const ConObj = {
user: "postgres", // default process.env.PGUSER || process.env.USER
password: "password", //default process.env.PGPASSWORD
host: "localhost", // default process.env.PGHOST
database: "my_test_database", // default process.env.PGDATABASE || user
port: 5432, // default process.env.PGPORT
application_name: "My Application Name", // The name of the application that created this Client instance
}
const dbConnection = new Client(ConObj)
dbConnection.connect()
一旦所有这些都完成了,错误应该解决。
希望这有助于那里的人,我拔我的头发与这个错误。真高兴它走了……