反向代理可以轻松地镜像一个网站,但像是博客这种知识产权很重要的网站,我们不希望有人建立镜像站,如何处理呢?
其实很简单,前端js检测当前的域名,不符合我们的网站就跳转回来,这样镜像站反而帮我们引流了。
下面就是一个这样的js的示例。
/**
* 域名跳转脚本
* 功能:如果当前访问的hostname不在允许的域名数组中,则随机跳转到数组中的一个域名并保留URL参数
* 避免回环地址和局域网地址跳转
*/
// 允许的域名数组
const allowedDomains = [
'example.com',
'domain1.com',
'domain2.com',
'yourwebsite.com'
];
/**
* 检查是否为回环地址或局域网地址
* @param {string} hostname - 要检查的主机名
* @returns {boolean} - 如果是回环或局域网地址返回true,否则返回false
*/
function isLoopbackOrLocalNetwork(hostname) {
// 回环地址
const loopbackPatterns = [
/^localhost$/,
/^127(\.\d{1,3}){3}$/
];
// 局域网地址
const localNetworkPatterns = [
/^10(\.\d{1,3}){3}$/, // 10.0.0.0/8
/^172\.(?:1[6-9]|2[0-9]|3[01])(\.\d{1,3}){2}$/, // 172.16.0.0/12
/^192\.168(\.\d{1,3}){2}$/, // 192.168.0.0/16
/^169\.254(\.\d{1,3}){2}$/, // 169.254.0.0/16 (链路本地地址)
/^fc00:/, // IPv6唯一本地地址
/^fe80:/ // IPv6链路本地地址
];
// 检查是否匹配回环地址模式
for (const pattern of loopbackPatterns) {
if (pattern.test(hostname)) {
return true;
}
}
// 检查是否匹配局域网地址模式
for (const pattern of localNetworkPatterns) {
if (pattern.test(hostname)) {
return true;
}
}
return false;
}
/**
* 从URL中提取主机名(这种处理方法得到的URL不包含端口号)
* @param {string} url - 完整URL
* @returns {string} - 主机名
*/
function extractHostname(url) {
// 创建一个临时元素来解析URL
const a = document.createElement('a');
a.href = url;
return a.hostname;
}
/**
* 从允许的域名数组中随机选择一个域名(不包括当前域名)
* @param {string} currentHostname - 当前主机名
* @returns {string|null} - 选中的域名或null(如果没有其他可用域名)
*/
function getRandomAllowedDomain(currentHostname) {
// 过滤出不等于当前主机名且不是回环/局域网地址的域名
const availableDomains = allowedDomains.filter(domain =>
domain !== currentHostname && !isLoopbackOrLocalNetwork(domain)
);
if (availableDomains.length === 0) {
return null;
}
// 随机选择一个域名
const randomIndex = Math.floor(Math.random() * availableDomains.length);
return availableDomains[randomIndex];
}
/**
* 执行域名跳转逻辑
*/
function handleDomainRedirect() {
const currentUrl = window.location.href;
const currentHostname = extractHostname(currentUrl);
// 检查当前主机名是否在允许的域名数组中
if (!allowedDomains.includes(currentHostname)) {
// 检查是否为回环或局域网地址(这些地址不执行跳转)
if (isLoopbackOrLocalNetwork(currentHostname)) {
console.log('在回环地址或局域网地址上,不执行跳转');
return;
}
// 获取一个随机的允许域名
const targetDomain = getRandomAllowedDomain(currentHostname);
if (targetDomain) {
// 构建新的URL,保留协议、路径和查询参数
const protocol = window.location.protocol;
const path = window.location.pathname;
const search = window.location.search;
const hash = window.location.hash;
const newUrl = `${protocol}//${targetDomain}${path}${search}${hash}`;
console.log(`从 ${currentHostname} 跳转到 ${targetDomain}`);
window.location.href = newUrl;
} else {
console.log('没有可用的目标域名进行跳转');
}
} else {
console.log('当前域名在允许列表中,无需跳转');
}
}
// 执行跳转逻辑
// 可以根据需要调整执行时机,这里直接执行
// 为了避免页面闪烁,可以考虑在DOMContentLoaded之前执行
if (typeof window !== 'undefined') {
handleDomainRedirect();
}
当然,如果搭建镜像的人设置了文本替换,我们的引用js文件的地址、js内的地址都可能被替换,真正在使用时候需要进行混淆加密、以文本形式加在页面上
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END


暂无评论内容