1
0
mirror of https://github.com/1Panel-dev/1Panel.git synced 2025-01-19 08:19:15 +08:00

feat: 增加URL黑白名单

This commit is contained in:
zhengkunwang223 2022-12-06 16:50:32 +08:00 committed by zhengkunwang223
parent c3cb41748b
commit 3f52c079af
5 changed files with 175 additions and 43 deletions

View File

@ -856,7 +856,9 @@ export default {
ccHelper: '{0} 秒内累计请求同一URL超过 {1} ,触发CC防御,封锁此IP', ccHelper: '{0} 秒内累计请求同一URL超过 {1} ,触发CC防御,封锁此IP',
seconds: '秒', seconds: '秒',
count: '次', count: '次',
mustSave: '修改之后需要保存才能生效,不合法的IP不会保存', mustSave: '修改之后需要保存才能生效',
fileExt: '文件扩展名',
fileExtBlock: '文件扩展名黑名单',
}, },
nginx: { nginx: {
serverNamesHashBucketSizeHelper: '服务器名字的hash表大小', serverNamesHashBucketSizeHelper: '服务器名字的hash表大小',

View File

@ -7,18 +7,18 @@
{{ $t('commons.button.add') }} {{ $t('commons.button.add') }}
</el-button> </el-button>
</template> </template>
<el-table-column label="IP" prop="ip"> <el-table-column :label="$t('website.fileExt')">
<template #default="{ row }"> <template #default="{ row }">
<fu-read-write-switch :data="row.ip" v-model="row.edit" write-trigger="onDblclick"> <fu-read-write-switch :data="row.file" v-model="row.edit" write-trigger="onDblclick">
<el-form-item :error="row.error"> <el-form-item :error="row.error">
<el-input v-model="row.ip" @blur="row.edit = false" @input="checkIpRule(row)" /> <el-input v-model="row.file" @blur="row.edit = false" />
</el-form-item> </el-form-item>
</fu-read-write-switch> </fu-read-write-switch>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="$t('commons.table.operate')"> <el-table-column :label="$t('commons.table.operate')">
<template #default="{ $index }"> <template #default="{ $index }">
<el-button link type="primary" @click="removeIp($index)"> <el-button link type="primary" @click="remove($index)">
{{ $t('commons.button.delete') }} {{ $t('commons.button.delete') }}
</el-button> </el-button>
</template> </template>
@ -41,7 +41,6 @@ import ComplexTable from '@/components/complex-table/index.vue';
import { SaveFileContent } from '@/api/modules/files'; import { SaveFileContent } from '@/api/modules/files';
import { ElMessage } from 'element-plus'; import { ElMessage } from 'element-plus';
import i18n from '@/lang'; import i18n from '@/lang';
import { checkIp } from '@/utils/util';
const props = defineProps({ const props = defineProps({
id: { id: {
@ -58,7 +57,7 @@ let data = ref([]);
let req = ref<WebSite.WafReq>({ let req = ref<WebSite.WafReq>({
websiteId: 0, websiteId: 0,
key: '', key: '',
rule: 'ipBlocklist', rule: 'blackfileExt',
}); });
let fileUpdate = reactive({ let fileUpdate = reactive({
path: '', path: '',
@ -75,7 +74,7 @@ const get = async () => {
const ipList = JSON.parse(res.data.content); const ipList = JSON.parse(res.data.content);
ipList.forEach((value) => { ipList.forEach((value) => {
data.value.push({ data.value.push({
ip: value, file: value,
eidt: false, eidt: false,
error: '', error: '',
}); });
@ -85,51 +84,34 @@ const get = async () => {
fileUpdate.path = res.data.filePath; fileUpdate.path = res.data.filePath;
}; };
const removeIp = (index: number) => { const remove = (index: number) => {
data.value.splice(index, 1); data.value.splice(index, 1);
}; };
const openCreate = () => { const openCreate = () => {
data.value.unshift({ id: '', edit: true, error: '' }); data.value.unshift({ file: '', edit: true, error: '' });
}; };
const submit = async () => { const submit = async () => {
let canCommit = true; let fileArray = [];
for (const row of data.value) {
console.log(row.ip);
console.log(row.error);
if (row.ip != '' && row.error != '') {
row.edit = true;
canCommit = false;
}
}
if (!canCommit) {
return;
}
let ipArray = [];
data.value.forEach((row) => { data.value.forEach((row) => {
ipArray.push(row.ip); if (row.file != '') {
fileArray.push(row.file);
}
}); });
fileUpdate.content = JSON.stringify(ipArray); fileUpdate.content = JSON.stringify(fileArray);
loading.value = true; loading.value = true;
SaveFileContent(fileUpdate) SaveFileContent(fileUpdate)
.then(() => { .then(() => {
ElMessage.success(i18n.global.t('commons.msg.updateSuccess')); ElMessage.success(i18n.global.t('commons.msg.updateSuccess'));
get();
}) })
.finally(() => { .finally(() => {
loading.value = false; loading.value = false;
}); });
}; };
const checkIpRule = (row: any) => {
if (checkIp(row.ip)) {
row.error = i18n.global.t('commons.rule.ip');
} else {
row.error = '';
}
};
onMounted(() => { onMounted(() => {
req.value.websiteId = id.value; req.value.websiteId = id.value;
get(); get();

View File

@ -3,22 +3,30 @@
<el-tab-pane :label="'CC 防护'" name="cc"> <el-tab-pane :label="'CC 防护'" name="cc">
<CCDeny :id="id" v-if="index == 'cc'"></CCDeny> <CCDeny :id="id" v-if="index == 'cc'"></CCDeny>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="'IP白名单'" name="ipWhiteList"> <el-tab-pane :label="'IP 白名单'" name="ipWhiteList">
<IpWhiteList :id="id" v-if="index == 'ipWhiteList'"></IpWhiteList> <IpList :id="id" :rule="'ipWhitelist'" v-if="index == 'ipWhiteList'"></IpList>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="'IP 黑名单'" name="ipBlockList"> <el-tab-pane :label="'IP 黑名单'" name="ipBlockList">
<IpBlockList :id="id" v-if="index == 'ipBlockList'"></IpBlockList> <IpList :id="id" :rule="'ipBlockList'" v-if="index == 'ipBlockList'"></IpList>
</el-tab-pane>
<el-tab-pane :label="'文件扩展名黑名单'" name="FileBlockList">
<FileBlockList :id="id" v-if="index == 'FileBlockList'"></FileBlockList>
</el-tab-pane>
<el-tab-pane :label="'URL黑名单'" name="urlBlockList">
<UrlList :id="id" :rule="'url'" v-if="index == 'urlBlockList'"></UrlList>
</el-tab-pane>
<el-tab-pane :label="'URL白名单'" name="urlWhiteList">
<UrlList :id="id" :rule="'whiteurl'" v-if="index == 'urlWhiteList'"></UrlList>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="'并发限制'"></el-tab-pane>
<el-tab-pane :label="'请求限制'"></el-tab-pane>
<el-tab-pane :label="'禁止爬虫'"></el-tab-pane> <el-tab-pane :label="'禁止爬虫'"></el-tab-pane>
</el-tabs> </el-tabs>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { computed, ref } from 'vue'; import { computed, ref } from 'vue';
import CCDeny from './ccdeny/index.vue'; import CCDeny from './ccdeny/index.vue';
import IpWhiteList from './ip-white-list/index.vue'; import IpList from './ip-list/index.vue';
import IpBlockList from './ip-block-list/index.vue'; import FileBlockList from './file-block-list/index.vue';
import UrlList from './url-list/index.vue';
const props = defineProps({ const props = defineProps({
id: { id: {

View File

@ -48,10 +48,17 @@ const props = defineProps({
type: Number, type: Number,
default: 0, default: 0,
}, },
rule: {
type: String,
default: 'ipWhitelist',
},
}); });
const id = computed(() => { const id = computed(() => {
return props.id; return props.id;
}); });
const rule = computed(() => {
return props.rule;
});
let loading = ref(false); let loading = ref(false);
let data = ref([]); let data = ref([]);
@ -90,14 +97,12 @@ const removeIp = (index: number) => {
}; };
const openCreate = () => { const openCreate = () => {
data.value.unshift({ id: '', edit: true, error: '' }); data.value.unshift({ ip: '', edit: true, error: '' });
}; };
const submit = async () => { const submit = async () => {
let canCommit = true; let canCommit = true;
for (const row of data.value) { for (const row of data.value) {
console.log(row.ip);
console.log(row.error);
if (row.ip != '' && row.error != '') { if (row.ip != '' && row.error != '') {
row.edit = true; row.edit = true;
canCommit = false; canCommit = false;
@ -132,6 +137,7 @@ const checkIpRule = (row: any) => {
onMounted(() => { onMounted(() => {
req.value.websiteId = id.value; req.value.websiteId = id.value;
req.value.rule = rule.value;
get(); get();
}); });
</script> </script>

View File

@ -0,0 +1,134 @@
<template>
<el-row>
<el-col :span="10" :offset="2">
<ComplexTable :data="data" v-loading="loading">
<template #toolbar>
<el-button type="primary" icon="Plus" @click="openCreate">
{{ $t('commons.button.add') }}
</el-button>
</template>
<el-table-column :label="'URL'">
<template #default="{ row }">
<fu-read-write-switch :data="row.value" v-model="row.edit" write-trigger="onDblclick">
<el-form-item :error="row.error">
<el-input
type="textarea"
:autosize="{ minRows: 2, maxRows: 8 }"
v-model="row.value"
@blur="row.edit = false"
/>
</el-form-item>
</fu-read-write-switch>
</template>
</el-table-column>
<el-table-column :label="$t('commons.table.operate')">
<template #default="{ $index }">
<el-button link type="primary" @click="remove($index)">
{{ $t('commons.button.delete') }}
</el-button>
</template>
</el-table-column>
</ComplexTable>
<br />
<el-alert :title="$t('website.mustSave')" type="info" :closable="false"></el-alert>
<br />
<el-button type="primary" :loading="loading" @click="submit">
{{ $t('commons.button.save') }}
</el-button>
</el-col>
</el-row>
</template>
<script lang="ts" setup>
import { WebSite } from '@/api/interface/website';
import { GetWafConfig } from '@/api/modules/website';
import { computed, onMounted, reactive, ref } from 'vue';
import ComplexTable from '@/components/complex-table/index.vue';
import { SaveFileContent } from '@/api/modules/files';
import { ElMessage } from 'element-plus';
import i18n from '@/lang';
const props = defineProps({
id: {
type: Number,
default: 0,
},
rule: {
type: String,
default: 'url',
},
});
const id = computed(() => {
return props.id;
});
const rule = computed(() => {
return props.rule;
});
let loading = ref(false);
let data = ref([]);
let req = ref<WebSite.WafReq>({
websiteId: 0,
key: '',
rule: 'url',
});
let fileUpdate = reactive({
path: '',
content: '',
});
const get = async () => {
data.value = [];
loading.value = true;
const res = await GetWafConfig(req.value);
loading.value = false;
if (res.data.content != '') {
const urlList = res.data.content.split('\n');
urlList.forEach((value) => {
if (value != '') {
data.value.push({
value: value,
eidt: false,
error: '',
});
}
});
}
fileUpdate.path = res.data.filePath;
};
const remove = (index: number) => {
data.value.splice(index, 1);
};
const openCreate = () => {
data.value.unshift({ value: '', edit: true, error: '' });
};
const submit = async () => {
let urlList = '';
data.value.forEach((row) => {
if (row.value != '') {
urlList = urlList + row.value + '\n';
}
});
fileUpdate.content = urlList;
loading.value = true;
SaveFileContent(fileUpdate)
.then(() => {
ElMessage.success(i18n.global.t('commons.msg.updateSuccess'));
get();
})
.finally(() => {
loading.value = false;
});
};
onMounted(() => {
req.value.websiteId = id.value;
req.value.rule = rule.value;
get();
});
</script>