登录增加最后登录时间地点,登录失败增加重试间隔

This commit is contained in:
hanhh 2021-08-22 01:22:23 +08:00
parent 61e41269ba
commit 54bb13aad0
9 changed files with 365 additions and 69 deletions

View File

@ -3,66 +3,28 @@ import { Container } from 'typedi';
import { Logger } from 'winston'; import { Logger } from 'winston';
import * as fs from 'fs'; import * as fs from 'fs';
import config from '../config'; import config from '../config';
import jwt from 'jsonwebtoken'; import { getNetIp } from '../config/util';
import { createRandomString } from '../config/util'; import AuthService from '../services/auth';
import crypto from 'crypto'; import { celebrate, Joi } from 'celebrate';
const route = Router(); const route = Router();
export default (app: Router) => { export default (app: Router) => {
app.use('/', route); app.use('/', route);
route.post( route.post(
'/login', '/login',
celebrate({
body: Joi.object({
username: Joi.string().required(),
password: Joi.string().required(),
}),
}),
async (req: Request, res: Response, next: NextFunction) => { async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger'); const logger: Logger = Container.get('logger');
try { try {
let username = req.body.username; const authService = Container.get(AuthService);
let password = req.body.password; const ipInfo = await getNetIp(req);
fs.readFile(config.authConfigFile, 'utf8', function (err, data) { const data = await authService.login({ ...req.body, ...ipInfo });
if (err) console.log(err); return res.send(data);
const authInfo = JSON.parse(data);
if (username && password) {
if (
authInfo.username === 'admin' &&
authInfo.password === 'adminadmin'
) {
const newPassword = createRandomString(16, 22);
fs.writeFileSync(
config.authConfigFile,
JSON.stringify({
username: authInfo.username,
password: newPassword,
}),
);
return res.send({
code: 100,
message: '已初始化密码请前往auth.json查看并重新登录',
});
}
if (
username == authInfo.username &&
password == authInfo.password
) {
const data = createRandomString(50, 100);
let token = jwt.sign({ data }, config.secret as any, {
expiresIn: 60 * 60 * 24 * 3,
algorithm: 'HS384',
});
fs.writeFileSync(
config.authConfigFile,
JSON.stringify({
username: authInfo.username,
password: authInfo.password,
token,
}),
);
res.send({ code: 200, token });
} else {
res.send({ code: 400, message: config.authError });
}
} else {
res.send({ err: 400, message: '请输入用户名密码!' });
}
});
} catch (e) { } catch (e) {
logger.error('🔥 error: %o', e); logger.error('🔥 error: %o', e);
return next(e); return next(e);
@ -81,8 +43,8 @@ export default (app: Router) => {
fs.writeFileSync( fs.writeFileSync(
config.authConfigFile, config.authConfigFile,
JSON.stringify({ JSON.stringify({
username: authInfo.username, ...authInfo,
password: authInfo.password, token: '',
}), }),
); );
res.send({ code: 200 }); res.send({ code: 200 });
@ -99,10 +61,15 @@ export default (app: Router) => {
async (req: Request, res: Response, next: NextFunction) => { async (req: Request, res: Response, next: NextFunction) => {
const logger: Logger = Container.get('logger'); const logger: Logger = Container.get('logger');
try { try {
fs.writeFile(config.authConfigFile, JSON.stringify(req.body), (err) => { const content = fs.readFileSync(config.authConfigFile, 'utf8');
if (err) console.log(err); fs.writeFile(
res.send({ code: 200, message: '更新成功' }); config.authConfigFile,
}); JSON.stringify({ ...JSON.parse(content || '{}'), ...req.body }),
(err) => {
if (err) console.log(err);
res.send({ code: 200, message: '更新成功' });
},
);
} catch (e) { } catch (e) {
logger.error('🔥 error: %o', e); logger.error('🔥 error: %o', e);
return next(e); return next(e);

View File

@ -1,5 +1,6 @@
import * as fs from 'fs'; import * as fs from 'fs';
import * as path from 'path'; import * as path from 'path';
import got from 'got';
export function getFileContentByName(fileName: string) { export function getFileContentByName(fileName: string) {
if (fs.existsSync(fileName)) { if (fs.existsSync(fileName)) {
@ -119,3 +120,52 @@ export function getToken(req: any) {
} }
return ''; return '';
} }
export async function getNetIp(req: any) {
const ipArray = [
...new Set([
...(req.headers['x-real-ip'] || '').split(','),
...(req.headers['x-forwarded-for'] || '').split(','),
req.ip,
...req.ips,
req.socket.remoteAddress,
]),
];
let ip = ipArray[0];
console.log(ipArray);
if (ipArray.length > 1) {
for (let i = 0; i < ipArray.length; i++) {
const ipNumArray = ipArray[i].split('.');
const tmp = ipNumArray[0] + '.' + ipNumArray[1];
if (
tmp === '192.168' ||
(ipNumArray[0] === '172' &&
ipNumArray[1] >= 16 &&
ipNumArray[1] <= 32) ||
tmp === '10.7' ||
tmp === '127.0'
) {
continue;
}
ip = ipArray[i];
}
}
ip = ip.substr(ip.lastIndexOf(':') + 1, ip.length);
if (ip.includes('127.0') || ip.includes('192.168') || ip.includes('10.7')) {
ip = '';
}
try {
const { data } = await got
.get(
`https://sp0.baidu.com/8aQDcjqpAAV3otqbppnN2DJv/api.php?query=${ip}&co=&resource_id=6006&t=1555898284898&ie=utf8&oe=utf8&format=json&tn=baidu`,
)
.json();
return { address: data[0].location, ip };
} catch (error) {
const { country, regionName, city } = await got
.get(`http://ip-api.com/json/${ip}?lang=zh-CN`)
.json();
return { address: `${country} ${regionName} ${city}`, ip };
}
}

103
back/services/auth.ts Normal file
View File

@ -0,0 +1,103 @@
import { Service, Inject } from 'typedi';
import winston from 'winston';
import { createRandomString, getFileContentByName } from '../config/util';
import config from '../config';
import * as fs from 'fs';
import _ from 'lodash';
import jwt from 'jsonwebtoken';
@Service()
export default class AuthService {
constructor(@Inject('logger') private logger: winston.Logger) {}
public async login(payloads: {
username: string;
password: string;
ip: string;
address: string;
}): Promise<any> {
if (!fs.existsSync(config.authConfigFile)) {
return this.initAuthInfo();
}
let { username, password, ip, address } = payloads;
const content = fs.readFileSync(config.authConfigFile, 'utf8');
const timestamp = Date.now();
if (content) {
const {
username: cUsername,
password: cPassword,
retries = 0,
lastlogon,
lastip,
lastaddr,
} = JSON.parse(content);
if (
(cUsername === 'admin' && cPassword === 'adminadmin') ||
!cUsername ||
!cPassword
) {
return this.initAuthInfo();
}
if (username === cUsername && password === cPassword) {
const data = createRandomString(50, 100);
let token = jwt.sign({ data }, config.secret as any, {
expiresIn: 60 * 60 * 24 * 3,
algorithm: 'HS384',
});
fs.writeFileSync(
config.authConfigFile,
JSON.stringify({
...JSON.parse(content),
token,
lastlogon: timestamp,
retries: 0,
lastip: ip,
lastaddr: address,
}),
);
return { code: 200, data: { token, lastip, lastaddr, lastlogon } };
} else {
if (
retries > 2 &&
Date.now() - lastlogon < Math.pow(3, retries) * 1000
) {
return {
code: 400,
message: `失败次数过多,请${Math.round(
(Math.pow(3, retries) * 1000 - Date.now() + lastlogon) / 1000,
)}`,
};
}
fs.writeFileSync(
config.authConfigFile,
JSON.stringify({
...JSON.parse(content),
retries: retries + 1,
lastlogon: timestamp,
ip,
address,
}),
);
return { code: 400, message: config.authError };
}
} else {
return this.initAuthInfo();
}
}
private initAuthInfo() {
const newPassword = createRandomString(16, 22);
fs.writeFileSync(
config.authConfigFile,
JSON.stringify({
username: 'admin',
password: newPassword,
}),
);
return {
code: 100,
message: '已初始化密码请前往auth.json查看并重新登录',
};
}
}

View File

@ -8,6 +8,9 @@ server {
ssl_session_timeout 5m; ssl_session_timeout 5m;
location /api { location /api {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://api; proxy_pass http://api;
} }

View File

@ -31,6 +31,7 @@
"dotenv": "^8.2.0", "dotenv": "^8.2.0",
"express": "^4.17.1", "express": "^4.17.1",
"express-jwt": "^6.0.0", "express-jwt": "^6.0.0",
"got": "^11.8.2",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"nedb": "^1.8.0", "nedb": "^1.8.0",

View File

@ -17,6 +17,7 @@ specifiers:
'@types/react-dom': ^17.0.0 '@types/react-dom': ^17.0.0
'@umijs/plugin-antd': ^0.9.1 '@umijs/plugin-antd': ^0.9.1
'@umijs/test': ^3.3.9 '@umijs/test': ^3.3.9
axios: ^0.21.1
body-parser: ^1.19.0 body-parser: ^1.19.0
celebrate: ^13.0.3 celebrate: ^13.0.3
codemirror: ^5.62.2 codemirror: ^5.62.2
@ -27,6 +28,7 @@ specifiers:
dotenv: ^8.2.0 dotenv: ^8.2.0
express: ^4.17.1 express: ^4.17.1
express-jwt: ^6.0.0 express-jwt: ^6.0.0
got: ^11.8.2
jsonwebtoken: ^8.5.1 jsonwebtoken: ^8.5.1
lint-staged: ^10.0.7 lint-staged: ^10.0.7
lodash: ^4.17.21 lodash: ^4.17.21
@ -56,6 +58,7 @@ specifiers:
yorkie: ^2.0.0 yorkie: ^2.0.0
dependencies: dependencies:
axios: 0.21.1
body-parser: 1.19.0 body-parser: 1.19.0
celebrate: 13.0.4 celebrate: 13.0.4
cors: 2.8.5 cors: 2.8.5
@ -63,6 +66,7 @@ dependencies:
dotenv: 8.6.0 dotenv: 8.6.0
express: 4.17.1 express: 4.17.1
express-jwt: 6.0.0 express-jwt: 6.0.0
got: 11.8.2
jsonwebtoken: 8.5.1 jsonwebtoken: 8.5.1
lodash: 4.17.21 lodash: 4.17.21
nedb: 1.8.0 nedb: 1.8.0
@ -935,6 +939,11 @@ packages:
engines: {node: '>=6'} engines: {node: '>=6'}
dev: true dev: true
/@sindresorhus/is/4.0.1:
resolution: {integrity: sha512-Qm9hBEBu18wt1PO2flE7LPb30BHMQt1eQgbV76YntdNk73XZGpn3izvGTYxbGgzXKgbCjiia0uxTd3aTNQrY/g==}
engines: {node: '>=10'}
dev: false
/@sinonjs/commons/1.8.3: /@sinonjs/commons/1.8.3:
resolution: {integrity: sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==} resolution: {integrity: sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ==}
dependencies: dependencies:
@ -954,6 +963,13 @@ packages:
defer-to-connect: 1.1.3 defer-to-connect: 1.1.3
dev: true dev: true
/@szmarczak/http-timer/4.0.6:
resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==}
engines: {node: '>=10'}
dependencies:
defer-to-connect: 2.0.1
dev: false
/@types/babel__core/7.1.14: /@types/babel__core/7.1.14:
resolution: {integrity: sha512-zGZJzzBUVDo/eV6KgbE0f0ZI7dInEYvo12Rb70uNQDshC3SkRMb67ja0GgRHZgAX3Za6rhaWlvbDO8rrGyAb1g==} resolution: {integrity: sha512-zGZJzzBUVDo/eV6KgbE0f0ZI7dInEYvo12Rb70uNQDshC3SkRMb67ja0GgRHZgAX3Za6rhaWlvbDO8rrGyAb1g==}
dependencies: dependencies:
@ -990,6 +1006,15 @@ packages:
'@types/node': 14.14.45 '@types/node': 14.14.45
dev: true dev: true
/@types/cacheable-request/6.0.2:
resolution: {integrity: sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA==}
dependencies:
'@types/http-cache-semantics': 4.0.1
'@types/keyv': 3.1.2
'@types/node': 14.17.11
'@types/responselike': 1.0.0
dev: false
/@types/connect/3.4.34: /@types/connect/3.4.34:
resolution: {integrity: sha512-ePPA/JuI+X0vb+gSWlPKOY0NdNAie/rPUqX2GUPpbZwiKTkSPhjXWuee47E4MtE54QVzGCQMQkAL6JhV2E1+cQ==} resolution: {integrity: sha512-ePPA/JuI+X0vb+gSWlPKOY0NdNAie/rPUqX2GUPpbZwiKTkSPhjXWuee47E4MtE54QVzGCQMQkAL6JhV2E1+cQ==}
dependencies: dependencies:
@ -1058,6 +1083,10 @@ packages:
resolution: {integrity: sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA==} resolution: {integrity: sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA==}
dev: true dev: true
/@types/http-cache-semantics/4.0.1:
resolution: {integrity: sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==}
dev: false
/@types/istanbul-lib-coverage/2.0.3: /@types/istanbul-lib-coverage/2.0.3:
resolution: {integrity: sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==} resolution: {integrity: sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==}
dev: true dev: true
@ -1091,6 +1120,12 @@ packages:
'@types/node': 14.14.45 '@types/node': 14.14.45
dev: true dev: true
/@types/keyv/3.1.2:
resolution: {integrity: sha512-/FvAK2p4jQOaJ6CGDHJTqZcUtbZe820qIeTg7o0Shg7drB4JHeL+V/dhSaly7NXx6u8eSee+r7coT+yuJEvDLg==}
dependencies:
'@types/node': 14.17.11
dev: false
/@types/lodash/4.14.170: /@types/lodash/4.14.170:
resolution: {integrity: sha512-bpcvu/MKHHeYX+qeEN8GE7DIravODWdACVA1ctevD8CN24RhPZIKMn9ntfAsrvLfSX3cR5RrBKAbYm9bGs0A+Q==} resolution: {integrity: sha512-bpcvu/MKHHeYX+qeEN8GE7DIravODWdACVA1ctevD8CN24RhPZIKMn9ntfAsrvLfSX3cR5RrBKAbYm9bGs0A+Q==}
dev: true dev: true
@ -1116,6 +1151,10 @@ packages:
resolution: {integrity: sha512-DssMqTV9UnnoxDWu959sDLZzfvqCF0qDNRjaWeYSui9xkFe61kKo4l1TWNTQONpuXEm+gLMRvdlzvNHBamzmEw==} resolution: {integrity: sha512-DssMqTV9UnnoxDWu959sDLZzfvqCF0qDNRjaWeYSui9xkFe61kKo4l1TWNTQONpuXEm+gLMRvdlzvNHBamzmEw==}
dev: true dev: true
/@types/node/14.17.11:
resolution: {integrity: sha512-n2OQ+0Bz6WEsUjrvcHD1xZ8K+Kgo4cn9/w94s1bJS690QMUWfJPW/m7CCb7gPkA1fcYwL2UpjXP/rq/Eo41m6w==}
dev: false
/@types/normalize-package-data/2.4.0: /@types/normalize-package-data/2.4.0:
resolution: {integrity: sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==} resolution: {integrity: sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==}
dev: true dev: true
@ -1204,6 +1243,12 @@ packages:
csstype: 3.0.8 csstype: 3.0.8
dev: true dev: true
/@types/responselike/1.0.0:
resolution: {integrity: sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA==}
dependencies:
'@types/node': 14.17.11
dev: false
/@types/scheduler/0.16.1: /@types/scheduler/0.16.1:
resolution: {integrity: sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA==} resolution: {integrity: sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA==}
dev: true dev: true
@ -1963,6 +2008,14 @@ packages:
resolution: {integrity: sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==} resolution: {integrity: sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==}
dev: true dev: true
/axios/0.21.1:
resolution: {integrity: sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==}
dependencies:
follow-redirects: 1.14.2
transitivePeerDependencies:
- debug
dev: false
/babel-core/7.0.0-bridge.0_@babel+core@7.12.10: /babel-core/7.0.0-bridge.0_@babel+core@7.12.10:
resolution: {integrity: sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==} resolution: {integrity: sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==}
peerDependencies: peerDependencies:
@ -2355,6 +2408,11 @@ packages:
unset-value: 1.0.0 unset-value: 1.0.0
dev: true dev: true
/cacheable-lookup/5.0.4:
resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==}
engines: {node: '>=10.6.0'}
dev: false
/cacheable-request/6.1.0: /cacheable-request/6.1.0:
resolution: {integrity: sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==} resolution: {integrity: sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -2368,6 +2426,19 @@ packages:
responselike: 1.0.2 responselike: 1.0.2
dev: true dev: true
/cacheable-request/7.0.2:
resolution: {integrity: sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==}
engines: {node: '>=8'}
dependencies:
clone-response: 1.0.2
get-stream: 5.2.0
http-cache-semantics: 4.1.0
keyv: 4.0.3
lowercase-keys: 2.0.0
normalize-url: 6.1.0
responselike: 2.0.0
dev: false
/call-bind/1.0.2: /call-bind/1.0.2:
resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==}
dependencies: dependencies:
@ -2565,7 +2636,6 @@ packages:
resolution: {integrity: sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=} resolution: {integrity: sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=}
dependencies: dependencies:
mimic-response: 1.0.1 mimic-response: 1.0.1
dev: true
/co/4.6.0: /co/4.6.0:
resolution: {integrity: sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=} resolution: {integrity: sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=}
@ -3073,6 +3143,13 @@ packages:
mimic-response: 1.0.1 mimic-response: 1.0.1
dev: true dev: true
/decompress-response/6.0.0:
resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==}
engines: {node: '>=10'}
dependencies:
mimic-response: 3.1.0
dev: false
/dedent/0.7.0: /dedent/0.7.0:
resolution: {integrity: sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=} resolution: {integrity: sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=}
dev: true dev: true
@ -3100,6 +3177,11 @@ packages:
resolution: {integrity: sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==} resolution: {integrity: sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==}
dev: true dev: true
/defer-to-connect/2.0.1:
resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==}
engines: {node: '>=10'}
dev: false
/define-properties/1.1.3: /define-properties/1.1.3:
resolution: {integrity: sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==} resolution: {integrity: sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
@ -3300,7 +3382,6 @@ packages:
resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==}
dependencies: dependencies:
once: 1.4.0 once: 1.4.0
dev: true
/enhanced-resolve/5.8.2: /enhanced-resolve/5.8.2:
resolution: {integrity: sha512-F27oB3WuHDzvR2DOGNTaYy0D5o0cnrv8TeI482VM4kYgQd/FT9lUQwuNsJ0oOHtBUq7eiW5ytqzp7nBFknL+GA==} resolution: {integrity: sha512-F27oB3WuHDzvR2DOGNTaYy0D5o0cnrv8TeI482VM4kYgQd/FT9lUQwuNsJ0oOHtBUq7eiW5ytqzp7nBFknL+GA==}
@ -3757,6 +3838,16 @@ packages:
resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==}
dev: false dev: false
/follow-redirects/1.14.2:
resolution: {integrity: sha512-yLR6WaE2lbF0x4K2qE2p9PEXKLDjUjnR/xmjS3wHAYxtlsI9MLLBJUZirAHKzUZDGLxje7w/cXR49WOUo4rbsA==}
engines: {node: '>=4.0'}
peerDependencies:
debug: '*'
peerDependenciesMeta:
debug:
optional: true
dev: false
/for-each/0.3.3: /for-each/0.3.3:
resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
dependencies: dependencies:
@ -3883,7 +3974,6 @@ packages:
engines: {node: '>=8'} engines: {node: '>=8'}
dependencies: dependencies:
pump: 3.0.0 pump: 3.0.0
dev: true
/get-value/2.0.6: /get-value/2.0.6:
resolution: {integrity: sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=} resolution: {integrity: sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=}
@ -3930,6 +4020,23 @@ packages:
engines: {node: '>=4'} engines: {node: '>=4'}
dev: true dev: true
/got/11.8.2:
resolution: {integrity: sha512-D0QywKgIe30ODs+fm8wMZiAcZjypcCodPNuMz5H9Mny7RJ+IjJ10BdmGW7OM7fHXP+O7r6ZwapQ/YQmMSvB0UQ==}
engines: {node: '>=10.19.0'}
dependencies:
'@sindresorhus/is': 4.0.1
'@szmarczak/http-timer': 4.0.6
'@types/cacheable-request': 6.0.2
'@types/responselike': 1.0.0
cacheable-lookup: 5.0.4
cacheable-request: 7.0.2
decompress-response: 6.0.0
http2-wrapper: 1.0.3
lowercase-keys: 2.0.0
p-cancelable: 2.1.1
responselike: 2.0.0
dev: false
/got/9.6.0: /got/9.6.0:
resolution: {integrity: sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==} resolution: {integrity: sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==}
engines: {node: '>=8.6'} engines: {node: '>=8.6'}
@ -4110,7 +4217,6 @@ packages:
/http-cache-semantics/4.1.0: /http-cache-semantics/4.1.0:
resolution: {integrity: sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==} resolution: {integrity: sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==}
dev: true
/http-errors/1.7.2: /http-errors/1.7.2:
resolution: {integrity: sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==} resolution: {integrity: sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==}
@ -4143,6 +4249,14 @@ packages:
sshpk: 1.16.1 sshpk: 1.16.1
dev: true dev: true
/http2-wrapper/1.0.3:
resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==}
engines: {node: '>=10.19.0'}
dependencies:
quick-lru: 5.1.1
resolve-alpn: 1.2.0
dev: false
/https-browserify/1.0.0: /https-browserify/1.0.0:
resolution: {integrity: sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=} resolution: {integrity: sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=}
dev: true dev: true
@ -5299,6 +5413,10 @@ packages:
resolution: {integrity: sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=} resolution: {integrity: sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=}
dev: true dev: true
/json-buffer/3.0.1:
resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
dev: false
/json-parse-better-errors/1.0.2: /json-parse-better-errors/1.0.2:
resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==} resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==}
dev: true dev: true
@ -5387,6 +5505,12 @@ packages:
json-buffer: 3.0.0 json-buffer: 3.0.0
dev: true dev: true
/keyv/4.0.3:
resolution: {integrity: sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA==}
dependencies:
json-buffer: 3.0.1
dev: false
/kind-of/3.2.2: /kind-of/3.2.2:
resolution: {integrity: sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=} resolution: {integrity: sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@ -5626,7 +5750,6 @@ packages:
/lowercase-keys/2.0.0: /lowercase-keys/2.0.0:
resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==}
engines: {node: '>=8'} engines: {node: '>=8'}
dev: true
/lru-cache/4.1.5: /lru-cache/4.1.5:
resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==} resolution: {integrity: sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==}
@ -5764,7 +5887,11 @@ packages:
/mimic-response/1.0.1: /mimic-response/1.0.1:
resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==}
engines: {node: '>=4'} engines: {node: '>=4'}
dev: true
/mimic-response/3.1.0:
resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==}
engines: {node: '>=10'}
dev: false
/mini-create-react-context/0.4.1_prop-types@15.7.2+react@16.14.0: /mini-create-react-context/0.4.1_prop-types@15.7.2+react@16.14.0:
resolution: {integrity: sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==} resolution: {integrity: sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ==}
@ -6075,6 +6202,11 @@ packages:
engines: {node: '>=8'} engines: {node: '>=8'}
dev: true dev: true
/normalize-url/6.1.0:
resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==}
engines: {node: '>=10'}
dev: false
/normalize.css/7.0.0: /normalize.css/7.0.0:
resolution: {integrity: sha1-q/sd2CRwZ04DIrU86xqvQSk45L8=} resolution: {integrity: sha1-q/sd2CRwZ04DIrU86xqvQSk45L8=}
dev: true dev: true
@ -6174,7 +6306,6 @@ packages:
resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=} resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=}
dependencies: dependencies:
wrappy: 1.0.2 wrappy: 1.0.2
dev: true
/one-time/1.0.0: /one-time/1.0.0:
resolution: {integrity: sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==} resolution: {integrity: sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==}
@ -6210,6 +6341,11 @@ packages:
engines: {node: '>=6'} engines: {node: '>=6'}
dev: true dev: true
/p-cancelable/2.1.1:
resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==}
engines: {node: '>=8'}
dev: false
/p-each-series/2.2.0: /p-each-series/2.2.0:
resolution: {integrity: sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==} resolution: {integrity: sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -6890,7 +7026,6 @@ packages:
dependencies: dependencies:
end-of-stream: 1.4.4 end-of-stream: 1.4.4
once: 1.4.0 once: 1.4.0
dev: true
/punycode/1.3.2: /punycode/1.3.2:
resolution: {integrity: sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=} resolution: {integrity: sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=}
@ -6972,6 +7107,11 @@ packages:
engines: {node: '>=0.4.x'} engines: {node: '>=0.4.x'}
dev: true dev: true
/quick-lru/5.1.1:
resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==}
engines: {node: '>=10'}
dev: false
/raf/3.4.1: /raf/3.4.1:
resolution: {integrity: sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==} resolution: {integrity: sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==}
dependencies: dependencies:
@ -8002,6 +8142,10 @@ packages:
resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==} resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==}
dev: true dev: true
/resolve-alpn/1.2.0:
resolution: {integrity: sha512-e4FNQs+9cINYMO5NMFc6kOUCdohjqFPSgMuwuZAOUWqrfWsen+Yjy5qZFkV5K7VO7tFSLKcUL97olkED7sCBHA==}
dev: false
/resolve-cwd/3.0.0: /resolve-cwd/3.0.0:
resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -8046,6 +8190,12 @@ packages:
lowercase-keys: 1.0.1 lowercase-keys: 1.0.1
dev: true dev: true
/responselike/2.0.0:
resolution: {integrity: sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw==}
dependencies:
lowercase-keys: 2.0.0
dev: false
/restore-cursor/3.1.0: /restore-cursor/3.1.0:
resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -9639,7 +9789,6 @@ packages:
/wrappy/1.0.2: /wrappy/1.0.2:
resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=} resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=}
dev: true
/write-file-atomic/2.4.1: /write-file-atomic/2.4.1:
resolution: {integrity: sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==} resolution: {integrity: sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg==}

View File

@ -18,14 +18,20 @@ reset_env() {
cp -f $dir_sample/package.json $dir_scripts/package.json cp -f $dir_sample/package.json $dir_scripts/package.json
npm_install_2 $dir_scripts npm_install_2 $dir_scripts
echo -e "---> 脚本依赖安装完成\n" echo -e "---> 脚本依赖安装完成\n"
}
echo -e "---> 4. 复制通知文件\n" copy_dep() {
echo -e "---> 1. 复制通知文件\n"
echo -e "---> 复制一份 $file_notify_py_sample$file_notify_py\n" echo -e "---> 复制一份 $file_notify_py_sample$file_notify_py\n"
cp -fv $file_notify_py_sample $file_notify_py cp -fv $file_notify_py_sample $file_notify_py
echo echo
echo -e "---> 复制一份 $file_notify_js_sample$file_notify_js\n" echo -e "---> 复制一份 $file_notify_js_sample$file_notify_js\n"
cp -fv $file_notify_js_sample $file_notify_js cp -fv $file_notify_js_sample $file_notify_js
echo -e "---> 通知文件复制完成\n" echo -e "---> 通知文件复制完成\n"
echo -e "---> 2. 复制nginx配置文件\n"
cp -fv $nginx_conf /etc/nginx/conf.d/front.conf
echo -e "---> 配置文件复制完成\n"
} }
reload_pm2() { reload_pm2() {
@ -57,6 +63,7 @@ check_nginx() {
echo -e "=====> 检测nginx服务\n$nginxPid" echo -e "=====> 检测nginx服务\n$nginxPid"
if [[ $nginxPid ]]; then if [[ $nginxPid ]]; then
echo -e "\n=====> nginx服务正常\n" echo -e "\n=====> nginx服务正常\n"
nginx -s reload
else else
echo -e "\n=====> nginx服务异常重新启动nginx\n" echo -e "\n=====> nginx服务异常重新启动nginx\n"
nginx -c /etc/nginx/nginx.conf nginx -c /etc/nginx/nginx.conf
@ -109,6 +116,7 @@ init_git() {
main() { main() {
echo -e "=====> 开始检测" echo -e "=====> 开始检测"
init_git init_git
copy_dep
check_ql check_ql
check_nginx check_nginx
check_pm2 check_pm2

View File

@ -32,6 +32,7 @@ file_notify_py_sample=$dir_sample/notify.py
file_notify_py=$dir_scripts/notify.py file_notify_py=$dir_scripts/notify.py
file_notify_js=$dir_scripts/sendNotify.js file_notify_js=$dir_scripts/sendNotify.js
task_error_log_path=$dir_log/task_error.log task_error_log_path=$dir_log/task_error.log
nginx_conf=$dir_root/docker/front.conf
## 清单文件 ## 清单文件
list_crontab_user=$dir_config/crontab.list list_crontab_user=$dir_config/crontab.list

View File

@ -1,5 +1,5 @@
import React, { Fragment, useEffect } from 'react'; import React, { Fragment, useEffect } from 'react';
import { Button, Row, Input, Form, message } from 'antd'; import { Button, Row, Input, Form, message, notification } from 'antd';
import config from '@/utils/config'; import config from '@/utils/config';
import { history, Link } from 'umi'; import { history, Link } from 'umi';
import styles from './index.less'; import styles from './index.less';
@ -18,7 +18,21 @@ const Login = () => {
}) })
.then((data) => { .then((data) => {
if (data.code === 200) { if (data.code === 200) {
localStorage.setItem(config.authKey, data.token); const { token, lastip, lastaddr, lastlogon } = data.data;
localStorage.setItem(config.authKey, token);
notification.success({
message: '登录成功!',
description: (
<div>
<div>
{new Date(lastlogon).toLocaleString() || '-'}
</div>
<div>{lastaddr || '-'}</div>
<div>IP{lastip || '-'}</div>
</div>
),
duration: 5,
});
history.push('/crontab'); history.push('/crontab');
} else if (data.code === 100) { } else if (data.code === 100) {
message.warn(data.message); message.warn(data.message);