mirror of
https://github.com/whyour/qinglong.git
synced 2025-05-23 14:56:07 +08:00
添加cookie管理页
This commit is contained in:
parent
99a8dc78db
commit
7f7d4d4f24
|
@ -1,7 +1,7 @@
|
||||||
|
import { getFileContentByName, getLastModifyFilePath } from '../config/util';
|
||||||
import { Router, Request, Response, NextFunction } from 'express';
|
import { Router, Request, Response, NextFunction } from 'express';
|
||||||
import { Container } from 'typedi';
|
import { Container } from 'typedi';
|
||||||
import { Logger } from 'winston';
|
import { Logger } from 'winston';
|
||||||
import * as fs from 'fs';
|
|
||||||
import config from '../config';
|
import config from '../config';
|
||||||
const route = Router();
|
const route = Router();
|
||||||
|
|
||||||
|
@ -41,30 +41,3 @@ export default (app: Router) => {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
function getFileContentByName(fileName) {
|
|
||||||
if (fs.existsSync(fileName)) {
|
|
||||||
return fs.readFileSync(fileName, 'utf8');
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
function getLastModifyFilePath(dir) {
|
|
||||||
var filePath = '';
|
|
||||||
|
|
||||||
if (fs.existsSync(dir)) {
|
|
||||||
var lastmtime = 0;
|
|
||||||
|
|
||||||
var arr = fs.readdirSync(dir);
|
|
||||||
|
|
||||||
arr.forEach(function (item) {
|
|
||||||
var fullpath = path.join(dir, item);
|
|
||||||
var stats = fs.statSync(fullpath);
|
|
||||||
if (stats.isFile()) {
|
|
||||||
if (stats.mtimeMs >= lastmtime) {
|
|
||||||
filePath = fullpath;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return filePath;
|
|
||||||
}
|
|
||||||
|
|
|
@ -3,6 +3,8 @@ import { Container } from 'typedi';
|
||||||
import CookieService from '../services/cookie';
|
import CookieService from '../services/cookie';
|
||||||
import { celebrate, Joi } from 'celebrate';
|
import { celebrate, Joi } from 'celebrate';
|
||||||
import { Logger } from 'winston';
|
import { Logger } from 'winston';
|
||||||
|
import { getFileContentByName } from '../config/util';
|
||||||
|
import config from '../config';
|
||||||
const route = Router();
|
const route = Router();
|
||||||
|
|
||||||
export default (app: Router) => {
|
export default (app: Router) => {
|
||||||
|
@ -25,4 +27,34 @@ export default (app: Router) => {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
route.get(
|
||||||
|
'/cookies',
|
||||||
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
const logger: Logger = Container.get('logger');
|
||||||
|
try {
|
||||||
|
const cookieService = Container.get(CookieService);
|
||||||
|
const data = await cookieService.getCookies();
|
||||||
|
return res.send({ code: 200, data });
|
||||||
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
|
return next(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
route.get(
|
||||||
|
'/cookie',
|
||||||
|
async (req: Request, res: Response, next: NextFunction) => {
|
||||||
|
const logger: Logger = Container.get('logger');
|
||||||
|
try {
|
||||||
|
const cookieService = Container.get(CookieService);
|
||||||
|
const data = await cookieService.addCookie();
|
||||||
|
return res.send({ code: 200, data });
|
||||||
|
} catch (e) {
|
||||||
|
logger.error('🔥 error: %o', e);
|
||||||
|
return next(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
28
back/config/util.ts
Normal file
28
back/config/util.ts
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import * as fs from 'fs';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
|
export function getFileContentByName(fileName: string) {
|
||||||
|
if (fs.existsSync(fileName)) {
|
||||||
|
return fs.readFileSync(fileName, 'utf8');
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getLastModifyFilePath(dir: string) {
|
||||||
|
let filePath = '';
|
||||||
|
|
||||||
|
if (fs.existsSync(dir)) {
|
||||||
|
const arr = fs.readdirSync(dir);
|
||||||
|
|
||||||
|
arr.forEach((item) => {
|
||||||
|
var fullpath = path.join(dir, item);
|
||||||
|
var stats = fs.statSync(fullpath);
|
||||||
|
if (stats.isFile()) {
|
||||||
|
if (stats.mtimeMs >= 0) {
|
||||||
|
filePath = fullpath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return filePath;
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ export default ({ app }: { app: Application }) => {
|
||||||
app.use(cors());
|
app.use(cors());
|
||||||
|
|
||||||
app.use(bodyParser.json());
|
app.use(bodyParser.json());
|
||||||
|
app.use(bodyParser.urlencoded({ extended: true }));
|
||||||
app.use(
|
app.use(
|
||||||
jwt({ secret: config.secret as string, algorithms: ['HS384'] }).unless({
|
jwt({ secret: config.secret as string, algorithms: ['HS384'] }).unless({
|
||||||
path: ['/api/auth'],
|
path: ['/api/auth'],
|
||||||
|
|
|
@ -1,6 +1,15 @@
|
||||||
import { Service, Inject } from 'typedi';
|
import { Service, Inject } from 'typedi';
|
||||||
import winston from 'winston';
|
import winston from 'winston';
|
||||||
import fetch from 'node-fetch';
|
import fetch from 'node-fetch';
|
||||||
|
import { getFileContentByName } from '../config/util';
|
||||||
|
import config from '../config';
|
||||||
|
import FormData from 'form-data';
|
||||||
|
|
||||||
|
enum Status {
|
||||||
|
'正常',
|
||||||
|
'失效',
|
||||||
|
'状态异常',
|
||||||
|
}
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
export default class CookieService {
|
export default class CookieService {
|
||||||
|
@ -122,4 +131,165 @@ export default class CookieService {
|
||||||
this.lstoken +
|
this.lstoken +
|
||||||
'; ';
|
'; ';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getCookie(response: any) {
|
||||||
|
var TrackerID = response.headers['set-cookie'][0];
|
||||||
|
TrackerID = TrackerID.substring(
|
||||||
|
TrackerID.indexOf('=') + 1,
|
||||||
|
TrackerID.indexOf(';'),
|
||||||
|
);
|
||||||
|
var pt_key = response.headers['set-cookie'][1];
|
||||||
|
pt_key = pt_key.substring(pt_key.indexOf('=') + 1, pt_key.indexOf(';'));
|
||||||
|
var pt_pin = response.headers['set-cookie'][2];
|
||||||
|
pt_pin = pt_pin.substring(pt_pin.indexOf('=') + 1, pt_pin.indexOf(';'));
|
||||||
|
var pt_token = response.headers['set-cookie'][3];
|
||||||
|
pt_token = pt_token.substring(
|
||||||
|
pt_token.indexOf('=') + 1,
|
||||||
|
pt_token.indexOf(';'),
|
||||||
|
);
|
||||||
|
var pwdt_id = response.headers['set-cookie'][4];
|
||||||
|
pwdt_id = pwdt_id.substring(pwdt_id.indexOf('=') + 1, pwdt_id.indexOf(';'));
|
||||||
|
var s_key = response.headers['set-cookie'][5];
|
||||||
|
s_key = s_key.substring(s_key.indexOf('=') + 1, s_key.indexOf(';'));
|
||||||
|
var s_pin = response.headers['set-cookie'][6];
|
||||||
|
s_pin = s_pin.substring(s_pin.indexOf('=') + 1, s_pin.indexOf(';'));
|
||||||
|
this.cookies =
|
||||||
|
'TrackerID=' +
|
||||||
|
TrackerID +
|
||||||
|
'; pt_key=' +
|
||||||
|
pt_key +
|
||||||
|
'; pt_pin=' +
|
||||||
|
pt_pin +
|
||||||
|
'; pt_token=' +
|
||||||
|
pt_token +
|
||||||
|
'; pwdt_id=' +
|
||||||
|
pwdt_id +
|
||||||
|
'; s_key=' +
|
||||||
|
s_key +
|
||||||
|
'; s_pin=' +
|
||||||
|
s_pin +
|
||||||
|
'; wq_skey=';
|
||||||
|
var userCookie = 'pt_key=' + pt_key + ';pt_pin=' + pt_pin + ';';
|
||||||
|
console.log('\n############ 登录成功,获取到 Cookie #############\n\n');
|
||||||
|
console.log('Cookie1="' + userCookie + '"\n');
|
||||||
|
console.log('\n####################################################\n\n');
|
||||||
|
return userCookie;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async addCookie() {
|
||||||
|
const cookie: any = await this.checkLogin();
|
||||||
|
if (cookie.body.errcode == 0) {
|
||||||
|
let ucookie = this.getCookie(cookie);
|
||||||
|
return ucookie;
|
||||||
|
} else {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async checkLogin() {
|
||||||
|
try {
|
||||||
|
if (this.cookies == '') {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
let timeStamp = new Date().getTime();
|
||||||
|
let url =
|
||||||
|
'https://plogin.m.jd.com/cgi-bin/m/tmauthchecktoken?&token=' +
|
||||||
|
this.token +
|
||||||
|
'&ou_state=0&okl_token=' +
|
||||||
|
this.okl_token;
|
||||||
|
let payload = {
|
||||||
|
lang: 'chs',
|
||||||
|
appid: 300,
|
||||||
|
returnurl:
|
||||||
|
'https://wqlogin2.jd.com/passport/LoginRedirect?state=1100399130787&returnurl=//home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&/myJd/home.action',
|
||||||
|
source: 'wq_passport',
|
||||||
|
};
|
||||||
|
let form = new FormData();
|
||||||
|
for (const key in payload) {
|
||||||
|
form.append(key, (payload as any)[key] as any);
|
||||||
|
}
|
||||||
|
const response = await fetch(url, {
|
||||||
|
method: 'post',
|
||||||
|
body: form,
|
||||||
|
headers: {
|
||||||
|
Referer:
|
||||||
|
'https://plogin.m.jd.com/login/login?appid=300&returnurl=https://wqlogin2.jd.com/passport/LoginRedirect?state=' +
|
||||||
|
timeStamp +
|
||||||
|
'&returnurl=//home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&/myJd/home.action&source=wq_passport',
|
||||||
|
Cookie: this.cookies,
|
||||||
|
Connection: 'Keep-Alive',
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded; Charset=UTF-8',
|
||||||
|
Accept: 'application/json, text/plain, */*',
|
||||||
|
'User-Agent':
|
||||||
|
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return response;
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error.response.body);
|
||||||
|
let res: any = {};
|
||||||
|
res.body = { check_ip: 0, errcode: 222, message: '出错' };
|
||||||
|
res.headers = {};
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getCookies() {
|
||||||
|
const content = getFileContentByName(config.confFile);
|
||||||
|
const regx = /Cookie[0-9]{1}\=\"(.+?)\"/g;
|
||||||
|
let m,
|
||||||
|
data = [];
|
||||||
|
while ((m = regx.exec(content)) !== null) {
|
||||||
|
data.push(m[1]);
|
||||||
|
}
|
||||||
|
return this.formatCookie(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async formatCookie(data: any[]) {
|
||||||
|
const result = [];
|
||||||
|
for (const x of data) {
|
||||||
|
const { nickname, status } = await this.getJdInfo(x);
|
||||||
|
result.push({
|
||||||
|
pin: x.match(/pt_pin=(.+?);/)[1],
|
||||||
|
cookie: x,
|
||||||
|
status,
|
||||||
|
nickname: nickname,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private getJdInfo(cookie: string) {
|
||||||
|
return fetch(
|
||||||
|
`https://me-api.jd.com/user_new/info/GetJDUserInfoUnion?orgFlag=JD_PinGou_New&callSource=mainorder&channel=4&isHomewhite=0&sceneval=2&_=${Date.now()}&sceneval=2&g_login_type=1&g_ty=ls`,
|
||||||
|
{
|
||||||
|
method: 'get',
|
||||||
|
headers: {
|
||||||
|
Accept: '*/*',
|
||||||
|
'Accept-Encoding': 'gzip, deflate, br',
|
||||||
|
'Accept-Language': 'zh-cn',
|
||||||
|
Connection: 'keep-alive',
|
||||||
|
Cookie: cookie,
|
||||||
|
Referer: 'https://home.m.jd.com/myJd/newhome.action',
|
||||||
|
'User-Agent':
|
||||||
|
'Mozilla/5.0 (iPhone; CPU iPhone OS 14_4_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Mobile/15E148 Safari/604.1',
|
||||||
|
Host: 'me-api.jd.com',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.then((x) => {
|
||||||
|
console.log(x);
|
||||||
|
return x.json();
|
||||||
|
})
|
||||||
|
.then((x) => {
|
||||||
|
console.log(x.data.userInfo);
|
||||||
|
if (x.retcode === '0' && x.data && x.data.userInfo) {
|
||||||
|
return { nickname: x.data.userInfo.baseInfo.nickname, status: 0 };
|
||||||
|
} else if (x.retcode === 13) {
|
||||||
|
return { status: 1, nickname: '-' };
|
||||||
|
}
|
||||||
|
return { status: 2, nickname: '-' };
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"express-basic-auth": "^1.2.0",
|
"express-basic-auth": "^1.2.0",
|
||||||
"express-jwt": "^6.0.0",
|
"express-jwt": "^6.0.0",
|
||||||
|
"form-data": "^4.0.0",
|
||||||
"jsonwebtoken": "^8.5.1",
|
"jsonwebtoken": "^8.5.1",
|
||||||
"lodash": "^4.17.20",
|
"lodash": "^4.17.20",
|
||||||
"mailgun-js": "^0.22.0",
|
"mailgun-js": "^0.22.0",
|
||||||
|
|
|
@ -5,27 +5,64 @@ import { PageContainer } from '@ant-design/pro-layout';
|
||||||
import { request } from '@/utils/http';
|
import { request } from '@/utils/http';
|
||||||
import QRCode from 'qrcode.react';
|
import QRCode from 'qrcode.react';
|
||||||
|
|
||||||
|
enum Status {
|
||||||
|
'正常',
|
||||||
|
'失效',
|
||||||
|
'状态异常',
|
||||||
|
}
|
||||||
|
enum StatusColor {
|
||||||
|
'success',
|
||||||
|
'error',
|
||||||
|
'warning',
|
||||||
|
}
|
||||||
|
|
||||||
const columns = [
|
const columns = [
|
||||||
{
|
{
|
||||||
title: '用户名',
|
title: '用户名',
|
||||||
dataIndex: 'pin',
|
dataIndex: 'pin',
|
||||||
key: 'pin',
|
key: 'pin',
|
||||||
|
align: 'center',
|
||||||
|
render: (text: string, record: any) => {
|
||||||
|
return <span>{decodeURIComponent(text)}</span>;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '昵称',
|
title: '昵称',
|
||||||
dataIndex: 'nickname',
|
dataIndex: 'nickname',
|
||||||
key: 'nickname',
|
key: 'nickname',
|
||||||
|
align: 'center',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '值',
|
title: '值',
|
||||||
dataIndex: 'cookie',
|
dataIndex: 'cookie',
|
||||||
key: 'cookie',
|
key: 'cookie',
|
||||||
|
align: 'center',
|
||||||
|
render: (text: string, record: any) => {
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
textAlign: 'left',
|
||||||
|
display: 'inline-block',
|
||||||
|
wordBreak: 'break-all',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{text}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '状态',
|
title: '状态',
|
||||||
key: 'status',
|
key: 'status',
|
||||||
dataIndex: 'status',
|
dataIndex: 'status',
|
||||||
render: (text: string, record: any) => <Tag color="success">success</Tag>,
|
align: 'center',
|
||||||
|
render: (text: string, record: any) => {
|
||||||
|
return (
|
||||||
|
<Space size="middle">
|
||||||
|
<Tag color={StatusColor[record.status]}>{Status[record.status]}</Tag>
|
||||||
|
</Space>
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '操作',
|
title: '操作',
|
||||||
|
@ -39,43 +76,19 @@ const columns = [
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const data = [
|
|
||||||
{
|
|
||||||
key: '1',
|
|
||||||
name: 'John Brown',
|
|
||||||
age: 32,
|
|
||||||
address: 'New York No. 1 Lake Park',
|
|
||||||
tags: ['nice', 'developer'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: '2',
|
|
||||||
name: 'Jim Green',
|
|
||||||
age: 42,
|
|
||||||
address: 'London No. 1 Lake Park',
|
|
||||||
tags: ['loser'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: '3',
|
|
||||||
name: 'Joe Black',
|
|
||||||
age: 32,
|
|
||||||
address: 'Sidney No. 1 Lake Park',
|
|
||||||
tags: ['cool', 'teacher'],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const Config = () => {
|
const Config = () => {
|
||||||
const [width, setWdith] = useState('100%');
|
const [width, setWdith] = useState('100%');
|
||||||
const [marginLeft, setMarginLeft] = useState(0);
|
const [marginLeft, setMarginLeft] = useState(0);
|
||||||
const [marginTop, setMarginTop] = useState(-72);
|
const [marginTop, setMarginTop] = useState(-72);
|
||||||
const [value, setValue] = useState('');
|
const [value, setValue] = useState();
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
|
|
||||||
const getConfig = () => {
|
const getConfig = () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
request
|
request
|
||||||
.get(`${config.apiPrefix}config/config`)
|
.get(`${config.apiPrefix}cookies`)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
setValue(data.content);
|
setValue(data.data);
|
||||||
})
|
})
|
||||||
.finally(() => setLoading(false));
|
.finally(() => setLoading(false));
|
||||||
};
|
};
|
||||||
|
@ -128,7 +141,6 @@ const Config = () => {
|
||||||
const getCookie = async (modal: { destroy: () => void }) => {
|
const getCookie = async (modal: { destroy: () => void }) => {
|
||||||
for (let i = 0; i < 50; i++) {
|
for (let i = 0; i < 50; i++) {
|
||||||
const result = await request.get(`${config.apiPrefix}cookie`);
|
const result = await request.get(`${config.apiPrefix}cookie`);
|
||||||
console.log(i, result);
|
|
||||||
if (result && result.cookie) {
|
if (result && result.cookie) {
|
||||||
notification.success({
|
notification.success({
|
||||||
message: 'Cookie获取成功',
|
message: 'Cookie获取成功',
|
||||||
|
@ -164,7 +176,7 @@ const Config = () => {
|
||||||
loading={loading}
|
loading={loading}
|
||||||
extra={[
|
extra={[
|
||||||
<Button key="2" type="primary" onClick={showQrCode}>
|
<Button key="2" type="primary" onClick={showQrCode}>
|
||||||
扫码获取Cookie
|
添加Cookie
|
||||||
</Button>,
|
</Button>,
|
||||||
]}
|
]}
|
||||||
header={{
|
header={{
|
||||||
|
@ -186,7 +198,10 @@ const Config = () => {
|
||||||
<Table
|
<Table
|
||||||
columns={columns}
|
columns={columns}
|
||||||
pagination={{ hideOnSinglePage: true }}
|
pagination={{ hideOnSinglePage: true }}
|
||||||
dataSource={data}
|
dataSource={value}
|
||||||
|
rowKey="value"
|
||||||
|
size="middle"
|
||||||
|
bordered
|
||||||
/>
|
/>
|
||||||
</PageContainer>
|
</PageContainer>
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user