feat(auth): implement secure authentication flow with RSA encryption

- Add jsencrypt and js-base64 dependencies for RSA encryption
- Create AuthGuard component for route protection
- Implement encryption utility for password security
- Refactor login page with tabbed interface and form validation
- Add login hooks for authentication state management
- Update user service to handle encrypted passwords
This commit is contained in:
2025-10-10 18:25:20 +08:00
parent a1282de74f
commit d6ff547f20
10 changed files with 697 additions and 119 deletions

36
src/utils/encryption.ts Normal file
View File

@@ -0,0 +1,36 @@
import JSEncrypt from 'jsencrypt';
import { Base64 } from 'js-base64';
// RSA公钥
let RSA_PUBLIC_KEY = (import.meta.env.VITE_RSA_PUBLIC_KEY as string) || '';
/**
* RSA密码加密函数
* @param password 明文密码
* @returns 加密后的密码
*/
export const rsaPsw = (password: string): string => {
try {
const encrypt = new JSEncrypt();
const publicKey = RSA_PUBLIC_KEY;
console.log('publicKey', publicKey);
encrypt.setPublicKey(publicKey);
const encrypted = encrypt.encrypt(Base64.encode(password));
return encrypted || password;
} catch (error) {
console.error('RSA encryption failed:', error);
return password;
}
};
/**
* 获取RSA公钥
* @returns RSA公钥字符串
*/
export const getRSAPublicKey = (): string => {
return RSA_PUBLIC_KEY;
};
export const setRSAPublicKey = (key: string) => {
RSA_PUBLIC_KEY = key;
};

View File

@@ -120,26 +120,16 @@ request.interceptors.response.use(
if (response.config.responseType === 'blob') {
return response;
}
console.log('interceptors.response ------ response', response);
const data: ResponseType = response.data;
// 处理业务错误码
if (data?.code === 100) {
snackbar.error(data?.message);
} else if (data?.code === 401) {
// notification.error({
// message: data?.message,
// description: data?.message,
// duration: 3,
// });
notification.error(data?.message);
redirectToLogin();
} else if (data?.code !== 0) {
// notification.error({
// message: `${i18n.t('message.hint')} : ${data?.code}`,
// description: data?.message,
// duration: 3,
// });
notification.error(`${i18n.t('message.hint')} : ${data?.code}`, data?.message);
}
@@ -148,19 +138,10 @@ request.interceptors.response.use(
(error) => {
// 处理网络错误
if (error.message === FAILED_TO_FETCH || !error.response) {
// notification.error({
// description: i18n.t('message.networkAnomalyDescription'),
// message: i18n.t('message.networkAnomaly'),
// });
notification.error(i18n.t('message.networkAnomaly'), i18n.t('message.networkAnomalyDescription'));
} else if (error.response) {
const { status, statusText } = error.response;
const errorText = RetcodeMessage[status as ResultCode] || statusText;
// notification.error({
// message: `${i18n.t('message.requestError')} ${status}`,
// description: errorText,
// });
notification.error(`${i18n.t('message.requestError')} ${status}`, errorText);
}