197 lines
5.2 KiB
JavaScript
197 lines
5.2 KiB
JavaScript
const db = uniCloud.database();
|
||
const _ = db.command;
|
||
const crypto = require('crypto');
|
||
let obj = {
|
||
isValidIP(ip) {
|
||
// ------------------------- IPv4 验证 -------------------------
|
||
if (ip.includes('.')) {
|
||
const ipv4Regex = /^(?:(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$/;
|
||
return ipv4Regex.test(ip); // 直接通过正则匹配[1,5](@ref)
|
||
}
|
||
|
||
// ------------------------- IPv6 验证 -------------------------
|
||
if (ip.includes(':')) {
|
||
const parts = ip.split(':');
|
||
// 处理压缩的::符号(如::1或2001:db8::1)
|
||
const hasDoubleColon = ip.includes('::');
|
||
if (hasDoubleColon && ip.indexOf('::') !== ip.lastIndexOf('::')) return false; // 禁止多个::[6](@ref)
|
||
|
||
// 分割后的段数应在1到8之间(允许压缩)
|
||
if (parts.length < 3 || parts.length > 8) return false;
|
||
|
||
// 展开压缩段(如将::替换为填充段)
|
||
let expandedParts = [];
|
||
let fillZeros = 8 - parts.filter(p => p !== '').length;
|
||
for (let part of parts) {
|
||
if (part === '') {
|
||
while (fillZeros-- > 0) expandedParts.push('0');
|
||
} else {
|
||
expandedParts.push(part);
|
||
}
|
||
}
|
||
if (expandedParts.length !== 8) return false;
|
||
|
||
// 验证每段是否为1-4位十六进制字符
|
||
const hexRegex = /^[0-9a-fA-F]{1,4}$/;
|
||
return expandedParts.every(p => hexRegex.test(p)); // 每段必须符合规则[6,7](@ref)
|
||
}
|
||
|
||
return false;
|
||
},
|
||
isReservedOrLocalIP(ip) {
|
||
if (ip.includes('.')) {
|
||
const parts = ip.split('.').map(Number);
|
||
if (parts.length !== 4 || parts.some(n => n < 0 || n > 255)) return false;
|
||
|
||
if (
|
||
parts[0] === 10 ||
|
||
(parts[0] === 172 && parts[1] >= 16 && parts[1] <= 31) ||
|
||
(parts[0] === 192 && parts[1] === 168)
|
||
) return true;
|
||
|
||
return (
|
||
parts[0] === 127 ||
|
||
(parts[0] === 169 && parts[1] === 254) ||
|
||
(parts[0] >= 224 && parts[0] <= 239) ||
|
||
ip === '0.0.0.0' ||
|
||
ip === '255.255.255.255'
|
||
);
|
||
}
|
||
|
||
// IPv6 处理逻辑
|
||
if (ip.includes(':')) {
|
||
const normalized = ip.replace(/(^:|:$)/g, '::').replace(/::/g, ':0:').split(':')
|
||
.map(seg => seg.padStart(4, '0')).join(':').padStart(39, '0:');
|
||
|
||
if (normalized.startsWith('fc00:') || normalized.startsWith('fd00:')) return true;
|
||
return (
|
||
normalized === '0000:0000:0000:0000:0000:0000:0000:0001' ||
|
||
normalized.startsWith('fe80:') ||
|
||
normalized.startsWith('ff00:') ||
|
||
normalized.startsWith('2001:0db8:') ||
|
||
normalized === '0000:0000:0000:0000:0000:0000:0000:0000'
|
||
);
|
||
}
|
||
|
||
return false;
|
||
},
|
||
async getIPAddress(ip) {
|
||
if (!obj.isValidIP(ip)) return "未知";
|
||
if (obj.isReservedOrLocalIP(ip)) return "未知";
|
||
|
||
|
||
|
||
let address = "";
|
||
|
||
const res = await db.collection("ip").where({
|
||
ip: ip
|
||
})
|
||
.field({
|
||
ip:true,
|
||
country: true,
|
||
economize: true,
|
||
market: true,
|
||
})
|
||
.get();
|
||
|
||
console.log(res);
|
||
|
||
if (res.data.length > 0) {
|
||
address = res.data.city;
|
||
}
|
||
|
||
|
||
let key = "IPUBZ-ZWF6I-PQ4GR-56NKD-BLZYJ-YHFIY";
|
||
let requests = "/ws/location/v1/ip?ip=" + ip + "&key="+ key+ "&output=json";
|
||
let sk = "1YTD18oU9wjLtVTVJWYupigJjuTPGvae";
|
||
const sig = crypto.createHash('md5')
|
||
.update(requests+sk)
|
||
.digest("hex");
|
||
console.log(sig)
|
||
|
||
let url= "https://apis.map.qq.com"+ requests + "&sig=" + sig;
|
||
console.log(url);
|
||
const response = await uniCloud.httpclient.request(url, {
|
||
method: 'GET',
|
||
});
|
||
console.log(response);
|
||
console.log(response.data)
|
||
if (response.status === 200) {
|
||
|
||
let json = JSON.parse(response.data.toString('utf8'));
|
||
if (json.message==="Success") {
|
||
await db.collection("ip").add({...json.result});
|
||
address = json.result.ad_info.province + " " + json.result.ad_info.city;
|
||
|
||
console.log(address)
|
||
return address;
|
||
}
|
||
|
||
}
|
||
return "未知";
|
||
|
||
}
|
||
}
|
||
module.exports = {
|
||
_before: function () { // 通用预处理器
|
||
|
||
},
|
||
async getIP(query) {
|
||
try {
|
||
let { uid } = query;
|
||
let res = await db.collection("uni-id-users")
|
||
.doc(uid)
|
||
.field({
|
||
_id: 1,
|
||
last_login_ip: 1
|
||
})
|
||
.get();
|
||
console.log(res.data[0]);
|
||
return {
|
||
code: 200,
|
||
data: res.data[0]
|
||
}
|
||
} catch(e) {
|
||
return {
|
||
code: 500,
|
||
msg: e.message
|
||
}
|
||
}
|
||
},
|
||
async get_user_info(query) {
|
||
try {
|
||
let uid = query.uid;
|
||
console.log(uid);
|
||
if (!uid) throw new Error("uid不存在");
|
||
console.log(uid);
|
||
let res = await db.collection("uni-id-users")
|
||
.doc(uid)
|
||
.field({
|
||
_id: 1,
|
||
nickname: 1,
|
||
avatar_file: 1,
|
||
last_login_ip:1,
|
||
register_date: 1,
|
||
last_login_date:1,
|
||
personal_profile: 1,
|
||
gender: 1
|
||
})
|
||
.get();
|
||
console.log(res.data[0].last_login_ip)
|
||
res.data[0].last_login_ip = await obj.getIPAddress(res.data[0].last_login_ip);
|
||
console.log(res)
|
||
|
||
return {
|
||
code: 200,
|
||
data: res.data[0]
|
||
}
|
||
} catch (e) {
|
||
console.log(e);
|
||
return {
|
||
code: 500,
|
||
msg: e.message
|
||
}
|
||
}
|
||
}
|
||
}
|