feat: fix login encrypt and prettier .vscode (#1481)

Co-authored-by: yikai <yikai@didiglobal.com>
pull/1483/head
bobowiki 1 year ago committed by GitHub
parent f8832afa87
commit 89c049dd62
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,35 +1,41 @@
{
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"[html]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnPaste": true,
"editor.formatOnSave": true
},
"[javascriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[jsonc]": {
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
},
"[html]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnPaste": true,
"editor.formatOnSave": true
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnPaste": true,
"editor.formatOnSave": true
},
"typescript.tsdk":"./node_modules/typescript/lib"
}
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnPaste": true,
"editor.formatOnSave": true
},
"[javascriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
},
"[jsonc]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true
},
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnPaste": true,
"editor.formatOnSave": true
},
"[typescriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnPaste": true,
"editor.formatOnSave": true
},
"[less]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnPaste": true,
"editor.formatOnSave": true
},
"typescript.tsdk": "./node_modules/typescript/lib"
}

@ -12,6 +12,7 @@
"@testing-library/user-event": "^13.5.0",
"ahooks": "^3.7.8",
"antd": "^5.4.7",
"buffer": "^6.0.3",
"classnames": "^2.3.2",
"dayjs": "^1.11.9",
"echarts": "^5.4.3",
@ -32,7 +33,8 @@
"build": "craco build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"lint": "eslint -c .eslintrc.js src --ext .ts,.tsx,.js,.jsx --fix"
"lint": "eslint -c .eslintrc.js src --ext .ts,.tsx,.js,.jsx --fix",
"format": "prettier --write src/"
},
"eslintConfig": {
"extends": [

@ -1,14 +1,14 @@
.header-wrapper {
display: flex;
width: 100%;
justify-content: space-between;
.logo {
display: flex;
width: 100%;
justify-content: space-between;
.logo {
display: flex;
flex-direction: column;
width: 50px;
img {
flex: 1;
object-fit: contain;
}
flex-direction: column;
width: 50px;
img {
flex: 1;
object-fit: contain;
}
}
}
}

@ -1,3 +0,0 @@
// .custom-icon {
// color: red !important;
// }

@ -1,6 +1,5 @@
import { createFromIconfontCN } from '@ant-design/icons';
import React from 'react';
import style from './index.module.less';
const MyIcon = createFromIconfontCN({
scriptUrl: '//at.alicdn.com/t/c/font_4254722_vw34zn7su2.js', // 在 iconfont.cn 上生成
@ -9,7 +8,7 @@ const MyIcon = createFromIconfontCN({
type MyComponentProps = React.HTMLProps<HTMLDivElement> & { type: string };
const IconFont: React.FC<MyComponentProps> = props => {
return <MyIcon className={style['custom-icon']} {...props}></MyIcon>;
return <MyIcon {...props}></MyIcon>;
};
export default IconFont;

@ -52,7 +52,7 @@ const LayoutCom = (props: ILayoutCom) => {
style={{
backgroundColor: myThemes.backgroundColor.bg1,
height: `calc(100vh - ${isHeader ? '64px' : '0px'})`,
margin: isHeader ? '10px 10px 0px' : '0px',
margin: isHeader ? '10px 10px 0px 0px' : '0px',
}}
>
{isSider && (

@ -1,5 +1,5 @@
.tenant_wrapper {
.opreate_btn {
padding: 0px;
padding: 0px;
}
}
}

@ -1,5 +1,5 @@
.tenant_wrapper {
.opreate_btn {
padding: 0px;
padding: 0px;
}
}
}

@ -1,37 +1,37 @@
.login-wrapper {
display: grid;
grid-template-columns: 1fr 550px;
grid-template-rows: 1fr;
height: 100%;
.login-bgi {
background: url('https://gw.alipayobjects.com/zos/rmsportal/FfdJeJRQWjEeGTpqgBKj.png') no-repeat fixed center center;
background-size: contain;
display: grid;
grid-template-columns: 1fr 550px;
grid-template-rows: 1fr;
height: 100%;
.login-bgi {
background: url('https://gw.alipayobjects.com/zos/rmsportal/FfdJeJRQWjEeGTpqgBKj.png') no-repeat fixed center center;
background-size: contain;
}
.login-form-wrapper {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.img-wrapper {
width: 50px;
display: flex;
flex-direction: column;
img {
flex: 1;
object-fit: contain;
}
}
.login-form-wrapper {
.tip {
margin-block-start: 12px;
margin-block-end: 36px;
}
.form-content {
width: 330px;
.login-edit {
display: flex;
flex-direction: column;
justify-content: center;
justify-content: space-between;
align-items: center;
.img-wrapper {
width: 50px;
display: flex;
flex-direction: column;
img {
flex: 1;
object-fit: contain;
}
}
.tip {
margin-block-start: 12px;
margin-block-end: 36px;
}
.form-content {
width: 330px;
.login-edit {
display: flex;
justify-content: space-between;
align-items: center;
}
}
}
}
}
}

@ -4,7 +4,7 @@ import service from './service';
import { LockOutlined, UserOutlined } from '@ant-design/icons';
import style from './index.module.less';
import { useRequest } from 'ahooks';
import { setToken } from '@/utils';
import { encrypt, genKey, setToken } from '@/utils';
import { useNavigate } from 'react-router-dom';
import { STR_MAP } from '@/config/i18n/locales/constants';
import { useTranslation } from 'react-i18next';
@ -20,7 +20,7 @@ const Login = () => {
const [form] = Form.useForm();
const navigate = useNavigate();
const { validateFields } = form;
const [remenberMe, setRemenberMe] = useState(0);
const [rememberMe, setRememberMe] = useState(1);
const { t } = useTranslation();
const { run, loading } = useRequest(service.fetchLogin, {
@ -36,17 +36,20 @@ const Login = () => {
const handleLogin = useCallback(() => {
validateFields()
.then(values => {
console.log('value:::', values, remenberMe);
.then(async values => {
const { password, username } = values;
let key = genKey();
let encodePassword = await encrypt(password, key);
key = key.split('').reverse().join('');
run({
password: '1BsL68bUgS52alKirqFprU1QfWJyPFlb3dA2AzEMc6kMTpTHN1doEN4=',
rememberMe: 1,
tag: 'lw4xNmj6QuamOFsy',
username: 'baoxinyi_user',
password: encodePassword,
tag: key,
username,
rememberMe,
});
})
.catch(err => console.log('err:::', err));
}, [remenberMe, validateFields, run]);
}, [validateFields, run, rememberMe]);
const formNode = useMemo(
() => (
@ -88,10 +91,9 @@ const Login = () => {
<Form.Item name="rememberMe">
<div className={style['login-edit']}>
<Checkbox
value={1}
checked
checked={Boolean(rememberMe)}
onChange={e => {
setRemenberMe(e.target.checked ? 1 : 0);
setRememberMe(Number(e.target.checked));
}}
>
{t(STR_MAP.REMERBER_PASSWORD)}
@ -113,7 +115,7 @@ const Login = () => {
</Form.Item>
</Form>
),
[form, loading, handleLogin, t]
[form, loading, rememberMe, handleLogin, t]
);
const items: TabsProps['items'] = [

@ -1,5 +1,5 @@
.tenant_wrapper {
.opreate_btn {
padding: 0px;
padding: 0px;
}
}
}

@ -1,5 +1,5 @@
.tenant_wrapper {
.opreate_btn {
padding: 0px;
padding: 0px;
}
}
}

@ -1,3 +1,3 @@
/// <reference types="react-scripts" />
declare module '*.less';
declare module 'crypto-browserify' {}
declare module 'crypto-js';

@ -1,40 +1,5 @@
import Cookie from 'js-cookie';
// import { Buffer } from 'buffer';
// import crypto from 'crypto-browserify';
// /**
// * generate key
// * @returns {string} key(length 16)
// */
// export function genKey() {
// let chars = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
// let result = '';
// for (let i = 16; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)];
// return result;
// }
// /**
// * encode message
// * @param msg message
// * @param key key
// * @returns {string} encoded message
// */
// export function encrypt(msg: string, key: string) {
// try {
// let pwd = Buffer.from(key);
// let iv = (crypto as any).randomBytes(12);
// let cipher = (crypto as any).createCipheriv('aes-128-gcm', pwd, iv);
// let enc = cipher.update(msg, 'utf8', 'base64');
// enc += cipher.final('base64');
// let tags = cipher.getAuthTag();
// enc = Buffer.from(enc, 'base64') as any;
// let totalLength = iv.length + enc.length + tags.length;
// let bufferMsg = Buffer.concat([iv, enc as any, tags], totalLength);
// return bufferMsg.toString('base64');
// } catch (e) {
// console.log('Encrypt is error', e);
// return null;
// }
// }
import { Buffer } from 'buffer';
import _ from 'lodash';
// is plain object
@ -89,4 +54,36 @@ const isEmpty = (value: any) => {
return typeof value === 'object' ? _.isEmpty(value) : isNilValue(value);
};
export { isPlainObject, isEmpty, filterEmptyField, setToken, removeToken, getToken };
function genKey() {
let chars = 'abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
let result = '';
for (let i = 16; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)];
return result;
}
async function encrypt(msg: string, key: any) {
try {
let pwd = Buffer.from(key);
const cryptoKey = await window.crypto.subtle.importKey('raw', pwd, { name: 'AES-GCM' }, false, ['encrypt']);
const iv = window.crypto.getRandomValues(new Uint8Array(12));
const encodedMsg = new TextEncoder().encode(msg);
const encryptedData = await window.crypto.subtle.encrypt(
{
name: 'AES-GCM',
iv: iv,
},
cryptoKey,
encodedMsg
);
const encryptedArray = new Uint8Array(encryptedData);
const totalLength = iv.length + encryptedArray.length;
const combinedArray = new Uint8Array(totalLength);
combinedArray.set(iv);
combinedArray.set(encryptedArray, iv.length);
return btoa(String.fromCharCode(...combinedArray));
} catch (e) {
return null;
}
}
export { isPlainObject, isEmpty, filterEmptyField, setToken, removeToken, getToken, genKey, encrypt };

@ -124,7 +124,6 @@ function request<T>(url: string, config: RequestOptions): Promise<Response<T>> {
return fetch(url, config as any).then(function onfulfilled(response) {
let { status, statusText } = response;
console.log('status:::', status, response);
if (status >= 200 && status < 400) {
let result;
switch (responseType) {
@ -141,10 +140,11 @@ function request<T>(url: string, config: RequestOptions): Promise<Response<T>> {
result = response.arrayBuffer();
break;
}
// business code
result?.then(res => {
if (res?.code === 200) {
// console.log(':::');
if (!res?.success) {
notification.error({
message: res.message,
});
}
});
return result;

@ -1,11 +1,8 @@
{
"compilerOptions": {
"target": "es5",
"target": "es2015",
"lib": ["dom", "dom.iterable", "esnext"],
"typeRoots": [
"node_modules/@types",
"src/typings"
],
"typeRoots": ["node_modules/@types", "src/typings"],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
@ -22,8 +19,8 @@
"baseUrl": "./",
"paths": {
// baseUrl
"@/*": ["src/*"],
},
"@/*": ["src/*"]
}
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx"]
}

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save