feat: add configurable stealth download security policies
This commit is contained in:
@@ -3396,6 +3396,63 @@
|
||||
<span style="color: var(--text-secondary); font-size: 13px;">修改后需要重启服务才能生效</span>
|
||||
</div>
|
||||
|
||||
<hr style="margin: 20px 0;">
|
||||
<h4 style="margin-bottom: 12px;"><i class="fas fa-shield-alt"></i> 下载安全策略(无感防刷)</h4>
|
||||
<div class="alert alert-info" style="margin-bottom: 15px;">
|
||||
触发策略时对用户返回“当前网络繁忙,请稍后再试”,避免暴露具体风控规则。
|
||||
</div>
|
||||
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 14px;">
|
||||
<div style="padding: 12px; border: 1px solid var(--glass-border); border-radius: 10px;">
|
||||
<div style="display: flex; align-items: center; gap: 8px; margin-bottom: 10px;">
|
||||
<input type="checkbox" id="ds-enabled" v-model="systemSettings.downloadSecurity.enabled">
|
||||
<label for="ds-enabled" style="margin: 0; font-weight: 600;">启用下载安全策略总开关</label>
|
||||
</div>
|
||||
<div style="font-size: 12px; color: var(--text-secondary);">
|
||||
关闭后不做下载频率限制。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="padding: 12px; border: 1px solid var(--glass-border); border-radius: 10px;">
|
||||
<div style="display: flex; align-items: center; gap: 8px; margin-bottom: 10px;">
|
||||
<input type="checkbox" id="ds-same-file" v-model="systemSettings.downloadSecurity.same_ip_same_file.enabled">
|
||||
<label for="ds-same-file" style="margin: 0; font-weight: 600;">同IP + 同文件限频</label>
|
||||
</div>
|
||||
<div style="display: flex; gap: 8px; align-items: center; flex-wrap: wrap;">
|
||||
<span style="font-size: 12px; color: var(--text-secondary);">5分钟</span>
|
||||
<input type="number" class="form-input" v-model.number="systemSettings.downloadSecurity.same_ip_same_file.limit_5m" min="1" style="width: 80px;">
|
||||
<span style="font-size: 12px; color: var(--text-secondary);">1小时</span>
|
||||
<input type="number" class="form-input" v-model.number="systemSettings.downloadSecurity.same_ip_same_file.limit_1h" min="1" style="width: 80px;">
|
||||
<span style="font-size: 12px; color: var(--text-secondary);">1天</span>
|
||||
<input type="number" class="form-input" v-model.number="systemSettings.downloadSecurity.same_ip_same_file.limit_1d" min="1" style="width: 80px;">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="padding: 12px; border: 1px solid var(--glass-border); border-radius: 10px;">
|
||||
<div style="display: flex; align-items: center; gap: 8px; margin-bottom: 10px;">
|
||||
<input type="checkbox" id="ds-same-user" v-model="systemSettings.downloadSecurity.same_ip_same_user.enabled">
|
||||
<label for="ds-same-user" style="margin: 0; font-weight: 600;">扩展:同IP + 同用户总限频</label>
|
||||
</div>
|
||||
<div style="display: flex; gap: 8px; align-items: center; flex-wrap: wrap;">
|
||||
<span style="font-size: 12px; color: var(--text-secondary);">1小时</span>
|
||||
<input type="number" class="form-input" v-model.number="systemSettings.downloadSecurity.same_ip_same_user.limit_1h" min="1" style="width: 90px;">
|
||||
<span style="font-size: 12px; color: var(--text-secondary);">1天</span>
|
||||
<input type="number" class="form-input" v-model.number="systemSettings.downloadSecurity.same_ip_same_user.limit_1d" min="1" style="width: 90px;">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="padding: 12px; border: 1px solid var(--glass-border); border-radius: 10px;">
|
||||
<div style="display: flex; align-items: center; gap: 8px; margin-bottom: 10px;">
|
||||
<input type="checkbox" id="ds-min-interval" v-model="systemSettings.downloadSecurity.same_ip_same_file_min_interval.enabled">
|
||||
<label for="ds-min-interval" style="margin: 0; font-weight: 600;">扩展:同IP + 同文件最小间隔</label>
|
||||
</div>
|
||||
<div style="display: flex; gap: 8px; align-items: center;">
|
||||
<span style="font-size: 12px; color: var(--text-secondary);">间隔秒数</span>
|
||||
<input type="number" class="form-input" v-model.number="systemSettings.downloadSecurity.same_ip_same_file_min_interval.seconds" min="1" style="width: 90px;">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr style="margin: 20px 0;">
|
||||
<h4 style="margin-bottom: 12px;"><i class="fas fa-palette"></i> 全局主题设置</h4>
|
||||
<div style="margin-bottom: 15px;">
|
||||
|
||||
@@ -228,6 +228,24 @@ createApp({
|
||||
// 系统设置
|
||||
systemSettings: {
|
||||
maxUploadSizeMB: 100,
|
||||
downloadSecurity: {
|
||||
enabled: true,
|
||||
same_ip_same_file: {
|
||||
enabled: true,
|
||||
limit_5m: 3,
|
||||
limit_1h: 10,
|
||||
limit_1d: 20
|
||||
},
|
||||
same_ip_same_user: {
|
||||
enabled: false,
|
||||
limit_1h: 80,
|
||||
limit_1d: 300
|
||||
},
|
||||
same_ip_same_file_min_interval: {
|
||||
enabled: false,
|
||||
seconds: 2
|
||||
}
|
||||
},
|
||||
smtp: {
|
||||
host: '',
|
||||
port: 465,
|
||||
@@ -4216,6 +4234,19 @@ handleDragLeave(e) {
|
||||
this.globalTheme = settings.global_theme;
|
||||
console.log('[主题] globalTheme已设置为:', this.globalTheme);
|
||||
}
|
||||
if (settings.download_security && typeof settings.download_security === 'object') {
|
||||
const ds = settings.download_security;
|
||||
this.systemSettings.downloadSecurity.enabled = !!ds.enabled;
|
||||
this.systemSettings.downloadSecurity.same_ip_same_file.enabled = !!ds.same_ip_same_file?.enabled;
|
||||
this.systemSettings.downloadSecurity.same_ip_same_file.limit_5m = Math.max(1, Number(ds.same_ip_same_file?.limit_5m || 3));
|
||||
this.systemSettings.downloadSecurity.same_ip_same_file.limit_1h = Math.max(1, Number(ds.same_ip_same_file?.limit_1h || 10));
|
||||
this.systemSettings.downloadSecurity.same_ip_same_file.limit_1d = Math.max(1, Number(ds.same_ip_same_file?.limit_1d || 20));
|
||||
this.systemSettings.downloadSecurity.same_ip_same_user.enabled = !!ds.same_ip_same_user?.enabled;
|
||||
this.systemSettings.downloadSecurity.same_ip_same_user.limit_1h = Math.max(1, Number(ds.same_ip_same_user?.limit_1h || 80));
|
||||
this.systemSettings.downloadSecurity.same_ip_same_user.limit_1d = Math.max(1, Number(ds.same_ip_same_user?.limit_1d || 300));
|
||||
this.systemSettings.downloadSecurity.same_ip_same_file_min_interval.enabled = !!ds.same_ip_same_file_min_interval?.enabled;
|
||||
this.systemSettings.downloadSecurity.same_ip_same_file_min_interval.seconds = Math.max(1, Number(ds.same_ip_same_file_min_interval?.seconds || 2));
|
||||
}
|
||||
if (settings.smtp) {
|
||||
this.systemSettings.smtp.host = settings.smtp.host || '';
|
||||
this.systemSettings.smtp.port = settings.smtp.port || 465;
|
||||
@@ -4251,6 +4282,24 @@ handleDragLeave(e) {
|
||||
|
||||
const payload = {
|
||||
max_upload_size: maxUploadSize,
|
||||
download_security: {
|
||||
enabled: !!this.systemSettings.downloadSecurity.enabled,
|
||||
same_ip_same_file: {
|
||||
enabled: !!this.systemSettings.downloadSecurity.same_ip_same_file.enabled,
|
||||
limit_5m: Math.max(1, Math.floor(Number(this.systemSettings.downloadSecurity.same_ip_same_file.limit_5m) || 3)),
|
||||
limit_1h: Math.max(1, Math.floor(Number(this.systemSettings.downloadSecurity.same_ip_same_file.limit_1h) || 10)),
|
||||
limit_1d: Math.max(1, Math.floor(Number(this.systemSettings.downloadSecurity.same_ip_same_file.limit_1d) || 20))
|
||||
},
|
||||
same_ip_same_user: {
|
||||
enabled: !!this.systemSettings.downloadSecurity.same_ip_same_user.enabled,
|
||||
limit_1h: Math.max(1, Math.floor(Number(this.systemSettings.downloadSecurity.same_ip_same_user.limit_1h) || 80)),
|
||||
limit_1d: Math.max(1, Math.floor(Number(this.systemSettings.downloadSecurity.same_ip_same_user.limit_1d) || 300))
|
||||
},
|
||||
same_ip_same_file_min_interval: {
|
||||
enabled: !!this.systemSettings.downloadSecurity.same_ip_same_file_min_interval.enabled,
|
||||
seconds: Math.max(1, Math.floor(Number(this.systemSettings.downloadSecurity.same_ip_same_file_min_interval.seconds) || 2))
|
||||
}
|
||||
},
|
||||
smtp: {
|
||||
host: this.systemSettings.smtp.host,
|
||||
port: this.systemSettings.smtp.port,
|
||||
|
||||
Reference in New Issue
Block a user