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:
parent
c3cb41748b
commit
3f52c079af
@ -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表大小',
|
||||||
|
@ -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();
|
@ -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: {
|
||||||
|
@ -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>
|
@ -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>
|
Loading…
x
Reference in New Issue
Block a user