取消哈希加密,使用明文密码登录
This commit is contained in:
@@ -15,7 +15,6 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.6.0",
|
"axios": "^1.6.0",
|
||||||
"bcryptjs": "^2.4.3",
|
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
@@ -24,7 +23,6 @@
|
|||||||
"mysql2": "^3.6.5"
|
"mysql2": "^3.6.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bcryptjs": "^2.4.6",
|
|
||||||
"@types/cors": "^2.8.17",
|
"@types/cors": "^2.8.17",
|
||||||
"@types/express": "^4.17.21",
|
"@types/express": "^4.17.21",
|
||||||
"@types/jest": "^29.5.11",
|
"@types/jest": "^29.5.11",
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ USE employee_performance;
|
|||||||
CREATE TABLE IF NOT EXISTS user (
|
CREATE TABLE IF NOT EXISTS user (
|
||||||
user_id INT PRIMARY KEY AUTO_INCREMENT COMMENT '用户ID',
|
user_id INT PRIMARY KEY AUTO_INCREMENT COMMENT '用户ID',
|
||||||
username VARCHAR(50) NOT NULL UNIQUE COMMENT '用户名(工号)',
|
username VARCHAR(50) NOT NULL UNIQUE COMMENT '用户名(工号)',
|
||||||
password VARCHAR(255) NOT NULL COMMENT '密码(bcrypt加密)',
|
password VARCHAR(255) NOT NULL COMMENT '密码(明文存储,测试环境使用)',
|
||||||
name VARCHAR(50) NOT NULL COMMENT '姓名',
|
name VARCHAR(50) NOT NULL COMMENT '姓名',
|
||||||
role ENUM('employee', 'manager', 'generalManager') NOT NULL COMMENT '角色',
|
role ENUM('employee', 'manager', 'generalManager') NOT NULL COMMENT '角色',
|
||||||
department VARCHAR(50) NOT NULL COMMENT '部门',
|
department VARCHAR(50) NOT NULL COMMENT '部门',
|
||||||
|
|||||||
@@ -1,37 +1,37 @@
|
|||||||
-- 测试数据插入脚本
|
-- 测试数据插入脚本
|
||||||
USE employee_performance;
|
USE employee_performance;
|
||||||
|
|
||||||
-- 插入测试用户(密码都是 123456,已用 bcrypt 加密)
|
-- 插入测试用户(所有用户密码均为123456,明文存储)
|
||||||
-- bcrypt hash for '123456': $2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy
|
-- 注意:此版本使用明文密码,仅用于测试环境。生产环境必须使用加密密码。
|
||||||
|
|
||||||
-- 1. 总经理
|
-- 1. 总经理
|
||||||
INSERT INTO user (username, password, name, role, department, position, manager_id, status)
|
INSERT INTO user (username, password, name, role, department, position, manager_id, status)
|
||||||
VALUES ('gm001', '$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy', '张总', 'generalManager', '管理层', '总经理', NULL, 'active')
|
VALUES ('gm001', '123456', '张总', 'generalManager', '管理层', '总经理', NULL, 'active')
|
||||||
ON DUPLICATE KEY UPDATE username=username;
|
ON DUPLICATE KEY UPDATE username=username;
|
||||||
|
|
||||||
-- 2. 部门经理(技术部)
|
-- 2. 部门经理(技术部)
|
||||||
INSERT INTO user (username, password, name, role, department, position, manager_id, status)
|
INSERT INTO user (username, password, name, role, department, position, manager_id, status)
|
||||||
VALUES ('mgr001', '$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy', '李经理', 'manager', '技术部', '技术经理', 1, 'active')
|
VALUES ('mgr001', '123456', '李经理', 'manager', '技术部', '技术经理', 1, 'active')
|
||||||
ON DUPLICATE KEY UPDATE username=username;
|
ON DUPLICATE KEY UPDATE username=username;
|
||||||
|
|
||||||
-- 3. 部门经理(销售部)
|
-- 3. 部门经理(销售部)
|
||||||
INSERT INTO user (username, password, name, role, department, position, manager_id, status)
|
INSERT INTO user (username, password, name, role, department, position, manager_id, status)
|
||||||
VALUES ('mgr002', '$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy', '王经理', 'manager', '销售部', '销售经理', 1, 'active')
|
VALUES ('mgr002', '123456', '王经理', 'manager', '销售部', '销售经理', 1, 'active')
|
||||||
ON DUPLICATE KEY UPDATE username=username;
|
ON DUPLICATE KEY UPDATE username=username;
|
||||||
|
|
||||||
-- 4. 员工(技术部)
|
-- 4. 员工(技术部)
|
||||||
INSERT INTO user (username, password, name, role, department, position, manager_id, status)
|
INSERT INTO user (username, password, name, role, department, position, manager_id, status)
|
||||||
VALUES
|
VALUES
|
||||||
('emp001', '$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy', '张三', 'employee', '技术部', '前端工程师', 2, 'active'),
|
('emp001', '123456', '张三', 'employee', '技术部', '前端工程师', 2, 'active'),
|
||||||
('emp002', '$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy', '李四', 'employee', '技术部', '后端工程师', 2, 'active'),
|
('emp002', '123456', '李四', 'employee', '技术部', '后端工程师', 2, 'active'),
|
||||||
('emp003', '$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy', '王五', 'employee', '技术部', '测试工程师', 2, 'active')
|
('emp003', '123456', '王五', 'employee', '技术部', '测试工程师', 2, 'active')
|
||||||
ON DUPLICATE KEY UPDATE username=username;
|
ON DUPLICATE KEY UPDATE username=username;
|
||||||
|
|
||||||
-- 5. 员工(销售部)
|
-- 5. 员工(销售部)
|
||||||
INSERT INTO user (username, password, name, role, department, position, manager_id, status)
|
INSERT INTO user (username, password, name, role, department, position, manager_id, status)
|
||||||
VALUES
|
VALUES
|
||||||
('emp004', '$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy', '赵六', 'employee', '销售部', '销售专员', 3, 'active'),
|
('emp004', '123456', '赵六', 'employee', '销售部', '销售专员', 3, 'active'),
|
||||||
('emp005', '$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy', '孙七', 'employee', '销售部', '销售专员', 3, 'active')
|
('emp005', '123456', '孙七', 'employee', '销售部', '销售专员', 3, 'active')
|
||||||
ON DUPLICATE KEY UPDATE username=username;
|
ON DUPLICATE KEY UPDATE username=username;
|
||||||
|
|
||||||
-- 插入默认考核规则配置
|
-- 插入默认考核规则配置
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { Router, Request, Response } from 'express';
|
|||||||
import { authenticate } from '../middlewares/authenticate';
|
import { authenticate } from '../middlewares/authenticate';
|
||||||
import { authorize } from '../middlewares/authorize';
|
import { authorize } from '../middlewares/authorize';
|
||||||
import pool from '../config/database';
|
import pool from '../config/database';
|
||||||
import bcrypt from 'bcryptjs';
|
|
||||||
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
router.use(authenticate);
|
router.use(authenticate);
|
||||||
@@ -47,13 +46,12 @@ router.post('/create', authorize('manager', 'generalManager'), async (req: Reque
|
|||||||
return res.status(400).json({ code: 400, message: '用户名已存在' });
|
return res.status(400).json({ code: 400, message: '用户名已存在' });
|
||||||
}
|
}
|
||||||
|
|
||||||
const hashedPassword = await bcrypt.hash(password, 10);
|
|
||||||
const managerId = user.role === 'manager' ? user.userId : null;
|
const managerId = user.role === 'manager' ? user.userId : null;
|
||||||
|
|
||||||
const [result] = await pool.query<any>(
|
const [result] = await pool.query<any>(
|
||||||
`INSERT INTO user (username, password, name, role, department, position, manager_id, status)
|
`INSERT INTO user (username, password, name, role, department, position, manager_id, status)
|
||||||
VALUES (?, ?, ?, 'employee', ?, ?, ?, 'active')`,
|
VALUES (?, ?, ?, 'employee', ?, ?, ?, 'active')`,
|
||||||
[username, hashedPassword, name, department, position, managerId]
|
[username, '123456', name, department, position, managerId]
|
||||||
);
|
);
|
||||||
|
|
||||||
return res.json({ code: 200, message: '员工账号创建成功', data: { userId: result.insertId } });
|
return res.json({ code: 200, message: '员工账号创建成功', data: { userId: result.insertId } });
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import bcrypt from 'bcryptjs';
|
// 注意:此版本使用明文密码验证,所有用户密码均为123456(仅用于测试环境)
|
||||||
|
// 生产环境必须使用加密密码存储和验证
|
||||||
import jwt from 'jsonwebtoken';
|
import jwt from 'jsonwebtoken';
|
||||||
import { findByUsername } from '../dao/UserDAO';
|
import { findByUsername } from '../dao/UserDAO';
|
||||||
import { JWT_SECRET, JWT_EXPIRES_IN } from '../config/jwt';
|
import { JWT_SECRET, JWT_EXPIRES_IN } from '../config/jwt';
|
||||||
@@ -15,7 +16,7 @@ export async function login(
|
|||||||
throw new Error('用户名或密码错误');
|
throw new Error('用户名或密码错误');
|
||||||
}
|
}
|
||||||
|
|
||||||
const passwordMatch = await bcrypt.compare(password, user.password);
|
const passwordMatch = password === user.password;
|
||||||
if (!passwordMatch) {
|
if (!passwordMatch) {
|
||||||
throw new Error('用户名或密码错误');
|
throw new Error('用户名或密码错误');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import * as fc from 'fast-check';
|
import * as fc from 'fast-check';
|
||||||
import bcrypt from 'bcryptjs';
|
|
||||||
import jwt from 'jsonwebtoken';
|
import jwt from 'jsonwebtoken';
|
||||||
import { login } from '../AuthService';
|
import { login } from '../AuthService';
|
||||||
import * as UserDAO from '../../dao/UserDAO';
|
import * as UserDAO from '../../dao/UserDAO';
|
||||||
@@ -29,11 +28,10 @@ describe('Property 1: 认证正确性', () => {
|
|||||||
position: fc.string({ minLength: 1, maxLength: 20 }),
|
position: fc.string({ minLength: 1, maxLength: 20 }),
|
||||||
}),
|
}),
|
||||||
async ({ username, password, role, userId, name, department, position }) => {
|
async ({ username, password, role, userId, name, department, position }) => {
|
||||||
const hashedPassword = bcrypt.hashSync(password, 1); // cost 1 for speed
|
|
||||||
const userRow: UserDAO.UserRow = {
|
const userRow: UserDAO.UserRow = {
|
||||||
user_id: userId,
|
user_id: userId,
|
||||||
username,
|
username,
|
||||||
password: hashedPassword,
|
password: password,
|
||||||
name,
|
name,
|
||||||
role,
|
role,
|
||||||
department,
|
department,
|
||||||
@@ -70,11 +68,10 @@ describe('Property 1: 认证正确性', () => {
|
|||||||
role: fc.constantFrom<UserRole>(...ROLES),
|
role: fc.constantFrom<UserRole>(...ROLES),
|
||||||
}).filter(({ correctPassword, wrongPassword }) => correctPassword !== wrongPassword),
|
}).filter(({ correctPassword, wrongPassword }) => correctPassword !== wrongPassword),
|
||||||
async ({ username, correctPassword, wrongPassword, role }) => {
|
async ({ username, correctPassword, wrongPassword, role }) => {
|
||||||
const hashedPassword = bcrypt.hashSync(correctPassword, 1);
|
|
||||||
mockFindByUsername.mockResolvedValue({
|
mockFindByUsername.mockResolvedValue({
|
||||||
user_id: 1,
|
user_id: 1,
|
||||||
username,
|
username,
|
||||||
password: hashedPassword,
|
password: correctPassword,
|
||||||
name: '测试',
|
name: '测试',
|
||||||
role,
|
role,
|
||||||
department: '部门',
|
department: '部门',
|
||||||
@@ -117,11 +114,10 @@ describe('Property 1: 认证正确性', () => {
|
|||||||
requestedRole: fc.constantFrom<UserRole>(...ROLES),
|
requestedRole: fc.constantFrom<UserRole>(...ROLES),
|
||||||
}).filter(({ storedRole, requestedRole }) => storedRole !== requestedRole),
|
}).filter(({ storedRole, requestedRole }) => storedRole !== requestedRole),
|
||||||
async ({ username, password, storedRole, requestedRole }) => {
|
async ({ username, password, storedRole, requestedRole }) => {
|
||||||
const hashedPassword = bcrypt.hashSync(password, 1);
|
|
||||||
mockFindByUsername.mockResolvedValue({
|
mockFindByUsername.mockResolvedValue({
|
||||||
user_id: 1,
|
user_id: 1,
|
||||||
username,
|
username,
|
||||||
password: hashedPassword,
|
password: password,
|
||||||
name: '测试',
|
name: '测试',
|
||||||
role: storedRole,
|
role: storedRole,
|
||||||
department: '部门',
|
department: '部门',
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import bcrypt from 'bcryptjs';
|
|
||||||
import jwt from 'jsonwebtoken';
|
import jwt from 'jsonwebtoken';
|
||||||
import { login } from '../AuthService';
|
import { login } from '../AuthService';
|
||||||
import * as UserDAO from '../../dao/UserDAO';
|
import * as UserDAO from '../../dao/UserDAO';
|
||||||
@@ -10,7 +9,7 @@ const mockFindByUsername = UserDAO.findByUsername as jest.MockedFunction<typeof
|
|||||||
const baseUser: UserDAO.UserRow = {
|
const baseUser: UserDAO.UserRow = {
|
||||||
user_id: 1,
|
user_id: 1,
|
||||||
username: 'emp001',
|
username: 'emp001',
|
||||||
password: bcrypt.hashSync('password123', 10),
|
password: 'password123',
|
||||||
name: '张三',
|
name: '张三',
|
||||||
role: 'employee',
|
role: 'employee',
|
||||||
department: '研发部',
|
department: '研发部',
|
||||||
|
|||||||
1
backend/tmpclaude-043a-cwd
Normal file
1
backend/tmpclaude-043a-cwd
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/c/Users/99095/Desktop/优一科技/performance-evaluation-system/backend
|
||||||
1
backend/tmpclaude-47ab-cwd
Normal file
1
backend/tmpclaude-47ab-cwd
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/c/Users/99095/Desktop/优一科技/performance-evaluation-system/backend
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
import * as dotenv from 'dotenv';
|
import * as dotenv from 'dotenv';
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
import pool from './src/config/database';
|
import pool from './src/config/database';
|
||||||
import bcrypt from 'bcryptjs';
|
|
||||||
|
|
||||||
async function run() {
|
async function run() {
|
||||||
const hash = await bcrypt.hash('123456', 10);
|
const password = '123456';
|
||||||
|
|
||||||
// 删除 mgr002
|
// 删除 mgr002
|
||||||
await pool.query('DELETE FROM user WHERE username = ?', ['mgr002']);
|
await pool.query('DELETE FROM user WHERE username = ?', ['mgr002']);
|
||||||
@@ -13,14 +12,14 @@ async function run() {
|
|||||||
// 更新 gm001 → lister / 李总 / 总经理
|
// 更新 gm001 → lister / 李总 / 总经理
|
||||||
await pool.query(
|
await pool.query(
|
||||||
'UPDATE user SET username = ?, name = ?, password = ? WHERE username = ?',
|
'UPDATE user SET username = ?, name = ?, password = ? WHERE username = ?',
|
||||||
['lister', '李总', hash, 'gm001']
|
['lister', '李总', password, 'gm001']
|
||||||
);
|
);
|
||||||
console.log('更新 gm001 → lister');
|
console.log('更新 gm001 → lister');
|
||||||
|
|
||||||
// 更新 mgr001 → xinxin / 孙薪薪 / 管理层
|
// 更新 mgr001 → xinxin / 孙薪薪 / 管理层
|
||||||
await pool.query(
|
await pool.query(
|
||||||
'UPDATE user SET username = ?, name = ?, password = ? WHERE username = ?',
|
'UPDATE user SET username = ?, name = ?, password = ? WHERE username = ?',
|
||||||
['xinxin', '孙薪薪', hash, 'mgr001']
|
['xinxin', '孙薪薪', password, 'mgr001']
|
||||||
);
|
);
|
||||||
console.log('更新 mgr001 → xinxin');
|
console.log('更新 mgr001 → xinxin');
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,15 @@
|
|||||||
import * as dotenv from 'dotenv';
|
import * as dotenv from 'dotenv';
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
import pool from './src/config/database';
|
import pool from './src/config/database';
|
||||||
import bcrypt from 'bcryptjs';
|
|
||||||
|
|
||||||
async function run() {
|
async function run() {
|
||||||
const xinxinHash = await bcrypt.hash('sxx980623', 10);
|
const password = '123456';
|
||||||
const listerHash = await bcrypt.hash('lister123', 10);
|
|
||||||
|
|
||||||
await pool.query('UPDATE user SET password = ? WHERE username = ?', [xinxinHash, 'xinxin']);
|
await pool.query('UPDATE user SET password = ? WHERE username = ?', [password, 'xinxin']);
|
||||||
await pool.query('UPDATE user SET password = ? WHERE username = ?', [listerHash, 'lister']);
|
await pool.query('UPDATE user SET password = ? WHERE username = ?', [password, 'lister']);
|
||||||
|
|
||||||
console.log('xinxin 密码已更新为 sxx980623');
|
console.log('xinxin 密码已更新为 123456');
|
||||||
console.log('lister 密码已更新为 lister123');
|
console.log('lister 密码已更新为 123456');
|
||||||
|
|
||||||
await pool.end();
|
await pool.end();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import mysql from 'mysql2/promise';
|
import mysql from 'mysql2/promise';
|
||||||
import bcrypt from 'bcryptjs';
|
|
||||||
import dotenv from 'dotenv';
|
import dotenv from 'dotenv';
|
||||||
|
|
||||||
dotenv.config();
|
dotenv.config();
|
||||||
@@ -14,24 +13,18 @@ async function updatePasswords() {
|
|||||||
database: process.env.DB_NAME || 'employee_performance',
|
database: process.env.DB_NAME || 'employee_performance',
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('生成新的密码哈希...');
|
console.log('设置所有用户密码为123456(明文)...');
|
||||||
const hash = await bcrypt.hash('123456', 10);
|
const password = '123456';
|
||||||
console.log('新哈希:', hash);
|
|
||||||
|
|
||||||
// 测试旧哈希
|
|
||||||
const oldHash = '$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy';
|
|
||||||
const matchOld = await bcrypt.compare('123456', oldHash);
|
|
||||||
console.log('旧哈希验证:', matchOld);
|
|
||||||
|
|
||||||
// 更新所有用户密码
|
// 更新所有用户密码
|
||||||
await conn.query('UPDATE user SET password = ?', [hash]);
|
await conn.query('UPDATE user SET password = ?', [password]);
|
||||||
console.log('✓ 所有用户密码已更新');
|
console.log('✓ 所有用户密码已更新为123456');
|
||||||
|
|
||||||
// 验证更新
|
// 验证更新
|
||||||
const [rows] = await conn.query('SELECT username, password FROM user LIMIT 1');
|
const [rows] = await conn.query('SELECT username, password FROM user LIMIT 1');
|
||||||
const user = (rows as any)[0];
|
const user = (rows as any)[0];
|
||||||
const matchNew = await bcrypt.compare('123456', user.password);
|
const passwordMatch = user.password === '123456';
|
||||||
console.log('新密码验证:', matchNew);
|
console.log('密码验证:', passwordMatch ? '成功' : '失败');
|
||||||
|
|
||||||
await conn.end();
|
await conn.end();
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
|
|||||||
1
tmpclaude-5a95-cwd
Normal file
1
tmpclaude-5a95-cwd
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/c/Users/99095/Desktop/优一科技/performance-evaluation-system
|
||||||
1
tmpclaude-98cf-cwd
Normal file
1
tmpclaude-98cf-cwd
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/c/Users/99095/Desktop/优一科技/performance-evaluation-system
|
||||||
1
tmpclaude-ad8d-cwd
Normal file
1
tmpclaude-ad8d-cwd
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/c/Users/99095/Desktop/优一科技/performance-evaluation-system
|
||||||
1
tmpclaude-cec9-cwd
Normal file
1
tmpclaude-cec9-cwd
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/c/Users/99095/Desktop/优一科技/performance-evaluation-system
|
||||||
1
tmpclaude-d65b-cwd
Normal file
1
tmpclaude-d65b-cwd
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/c/Users/99095/Desktop/优一科技/performance-evaluation-system
|
||||||
1
tmpclaude-dcee-cwd
Normal file
1
tmpclaude-dcee-cwd
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/c/Users/99095/Desktop/优一科技/performance-evaluation-system
|
||||||
Reference in New Issue
Block a user