Files
XCDesktop/remote/src/services/auth/AuthService.js
2026-03-08 01:34:54 +08:00

102 lines
2.4 KiB
JavaScript

const bcrypt = require('bcryptjs');
const logger = require('../../utils/logger');
const BCRYPT_COST = 12;
const BCRYPT_HASH_PREFIX = '$2b$';
let instance = null;
class AuthService {
constructor() {
if (instance) {
return instance;
}
this.passwordHash = null;
this.isHashed = false;
this._initializePassword();
instance = this;
}
_initializePassword() {
const config = require('../../utils/config');
const securityConfig = config.getSecurityConfig();
const password = securityConfig.password;
if (!password) {
logger.warn('No password configured. Authentication will be disabled.');
return;
}
if (password.startsWith(BCRYPT_HASH_PREFIX)) {
this.passwordHash = password;
this.isHashed = true;
logger.info('AuthService initialized with bcrypt hash password');
} else {
this.passwordHash = password;
this.isHashed = false;
logger.info('AuthService initialized with plaintext password');
}
}
async hashPassword(password) {
return bcrypt.hash(password, BCRYPT_COST);
}
async verifyPassword(password, hash) {
return bcrypt.compare(password, hash);
}
async authenticate(password) {
if (!this.passwordHash) {
logger.debug('Authentication skipped: no password configured');
return true;
}
if (!password) {
logger.warn('Authentication failed: no password provided');
return false;
}
try {
if (this.isHashed) {
const isValid = await this.verifyPassword(password, this.passwordHash);
if (isValid) {
logger.debug('Authentication successful');
} else {
logger.warn('Authentication failed: invalid password');
}
return isValid;
} else {
const hashedInput = await this.hashPassword(password);
const isValid = await this.verifyPassword(password, hashedInput);
if (password === this.passwordHash) {
logger.debug('Authentication successful');
return true;
} else {
logger.warn('Authentication failed: invalid password');
return false;
}
}
} catch (error) {
logger.error('Authentication error', { error: error.message });
return false;
}
}
hasPassword() {
return !!this.passwordHash;
}
static getInstance() {
if (!instance) {
instance = new AuthService();
}
return instance;
}
}
module.exports = AuthService;