Files
school-developer/src/api/login/index.ts
zhoutianchi c24432ea9b 1
2026-02-28 18:40:13 +08:00

201 lines
5.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import request from '/@/utils/request';
import { Session } from '/@/utils/storage';
import { validateNull } from '/@/utils/validate';
import { useUserInfo } from '/@/stores/userInfo';
import other, { sm2Encrypt } from '/@/utils/other';
/**
* https://www.ietf.org/rfc/rfc6749.txt
* OAuth 协议 4.3.1 要求格式为 form 而不是 JSON 注意!
*/
const FORM_CONTENT_TYPE = 'application/x-www-form-urlencoded';
/** 登录是否使用 SM2 加密密码(需后端配置 SM2 私钥并支持 Enc-Flag: sm2 */
const LOGIN_SM2_ENABLE = import.meta.env.VITE_LOGIN_SM2_ENABLE === 'true';
/** SM2 公钥(十六进制,与后端私钥成对),用于前端加密密码 */
const SM2_PUBLIC_KEY = import.meta.env.VITE_SM2_PUBLIC_KEY || '';
// 登录方式
export enum LoginTypeEnum {
PASSWORD,
MOBILE,
REGISTER,
EXPIRE,
QRCODE,
}
// 登录错误信息
export enum LoginErrorEnum {
CREDENTIALS_EXPIRED = 'credentials_expired', // 密码过期
}
/**
* 社交登录方式枚举
*/
export enum SocialLoginEnum {
SMS = 'SMS', // 验证码登录
DINGTALK = 'DINGTALK', // 钉钉
WEIXIN_CP = 'WEIXIN_CP', // 企业微信
APP_SMS = 'APP-SMS', // APP验证码登录
QQ = 'QQ', // QQ登录
WECHAT = 'WX', // 微信登录
MINI_APP = 'MINI', // 微信小程序
GITEE = 'GITEE', // 码云登录
OSC = 'OSC', // 开源中国登录
CAS = 'CAS', // CAS 登录
}
/**
* 登录
* @param data
*/
export const login = (data: any) => {
const basicAuth = 'Basic ' + window.btoa(import.meta.env.VITE_OAUTH2_PASSWORD_CLIENT);
Session.set('basicAuth', basicAuth);
let encPassword: string;
let encFlag: string;
if (LOGIN_SM2_ENABLE && SM2_PUBLIC_KEY) {
encPassword = sm2Encrypt(data.password, SM2_PUBLIC_KEY);
encFlag = 'sm2';
} else {
encPassword = other.encryption(data.password, import.meta.env.VITE_PWD_ENC_KEY);
encFlag = 'false';
}
const { username, randomStr, code, grant_type, scope } = data;
return request({
url: '/auth/oauth2/token',
method: 'post',
params: { username, randomStr, code, grant_type, scope },
data: { password: encPassword },
headers: {
skipToken: true,
Authorization: basicAuth,
'Content-Type': FORM_CONTENT_TYPE,
'Enc-Flag': encFlag,
},
});
};
export const loginByMobile = (mobile: any, code: any) => {
const grant_type = 'mobile';
const scope = 'server';
const basicAuth = 'Basic ' + window.btoa(import.meta.env.VITE_OAUTH2_MOBILE_CLIENT);
Session.set('basicAuth', basicAuth);
return request({
url: '/auth/oauth2/token',
headers: {
skipToken: true,
Authorization: basicAuth,
'Content-Type': FORM_CONTENT_TYPE,
},
method: 'post',
params: { mobile: `${SocialLoginEnum.SMS}@${mobile}`, code: code, grant_type, scope },
});
};
export const loginBySocial = (state: SocialLoginEnum, code: string) => {
const grant_type = 'mobile';
const scope = 'server';
const basicAuth = 'Basic ' + window.btoa(import.meta.env.VITE_OAUTH2_SOCIAL_CLIENT);
Session.set('basicAuth', basicAuth);
return request({
url: '/auth/oauth2/token',
headers: {
skipToken: true,
Authorization: basicAuth,
'Content-Type': FORM_CONTENT_TYPE,
},
method: 'post',
params: { mobile: `${state}@${code}`, code: code, grant_type, scope },
});
};
export const sendMobileCode = (mobile: string) => {
return request({
url: '/admin/sysMessage/send/smsCode',
method: 'get',
params: { mobile },
});
};
export const refreshTokenApi = (refresh_token: string) => {
const grant_type = 'refresh_token';
const scope = 'server';
// 获取当前选中的 basic 认证信息
const basicAuth = Session.get('basicAuth');
return request({
url: '/auth/oauth2/token',
headers: {
skipToken: true,
Authorization: basicAuth,
'Content-Type': FORM_CONTENT_TYPE,
},
method: 'post',
params: { refresh_token, grant_type, scope },
});
};
/**
* 校验令牌,若有效期小于半小时自动续期
* @param refreshLock
*/
export const checkToken = (refreshTime: number, refreshLock: boolean) => {
const basicAuth = Session.get('basicAuth');
request({
url: '/auth/token/check_token',
headers: {
skipToken: true,
Authorization: basicAuth,
'Content-Type': FORM_CONTENT_TYPE,
},
method: 'get',
params: { token: Session.getToken() },
})
.then((response) => {
if (validateNull(response) || response.code === 1) {
clearInterval(refreshTime);
return;
}
const expire = Date.parse(response.data.expiresAt);
if (expire) {
const expiredPeriod = expire - new Date().getTime();
//小于半小时自动续约
if (expiredPeriod <= 30 * 60 * 1000) {
if (!refreshLock) {
refreshLock = true;
useUserInfo()
.refreshToken()
.catch(() => {
clearInterval(refreshTime);
});
refreshLock = false;
}
}
}
})
.catch(() => {
// 发生异常关闭定时器
clearInterval(refreshTime);
});
};
/**
* 获取用户信息
*/
export const getUserInfo = () => {
return request({
url: '/admin/user/info',
method: 'get',
});
};
export const logout = () => {
return request({
url: '/auth/token/logout',
method: 'delete',
});
};