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', }); };