mirror of
https://github.com/TeaOSLab/EdgeAdmin.git
synced 2025-11-11 18:30:25 +08:00
优化WAF动作
This commit is contained in:
@@ -49,7 +49,7 @@ Vue.component("http-access-log-box", {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
template: `<div :style="{'color': (accessLog.status >= 400) ? '#dc143c' : ''}" ref="box">
|
template: `<div :style="{'color': (accessLog.status >= 400) ? '#dc143c' : ''}" ref="box">
|
||||||
<span v-if="accessLog.region != null && accessLog.region.length > 0" class="grey">[{{accessLog.region}}]</span> <keyword :v-word="vKeyword">{{accessLog.remoteAddr}}</keyword> [{{accessLog.timeLocal}}] <em>"<keyword :v-word="vKeyword">{{accessLog.requestMethod}}</keyword> {{accessLog.scheme}}://<keyword :v-word="vKeyword">{{accessLog.host}}</keyword><keyword :v-word="vKeyword">{{accessLog.requestURI}}</keyword> <a :href="accessLog.scheme + '://' + accessLog.host + accessLog.requestURI" target="_blank" title="新窗口打开" class="disabled"><i class="external icon tiny"></i> </a> {{accessLog.proto}}" </em> <keyword :v-word="vKeyword">{{accessLog.status}}</keyword> <code-label v-if="accessLog.attrs != null && accessLog.attrs['cache.status'] == 'HIT'">cache hit</code-label> <code-label v-if="accessLog.attrs != null && accessLog.attrs['waf.action'] != null && accessLog.attrs['waf.action'].length > 0">waf {{accessLog.attrs['waf.action']}}</code-label> - 耗时:{{formatCost(accessLog.requestTime)}} ms <span v-if="accessLog.humanTime != null && accessLog.humanTime.length > 0" class="grey small"> ({{accessLog.humanTime}})</span>
|
<span v-if="accessLog.region != null && accessLog.region.length > 0" class="grey">[{{accessLog.region}}]</span> <keyword :v-word="vKeyword">{{accessLog.remoteAddr}}</keyword> [{{accessLog.timeLocal}}] <em>"<keyword :v-word="vKeyword">{{accessLog.requestMethod}}</keyword> {{accessLog.scheme}}://<keyword :v-word="vKeyword">{{accessLog.host}}</keyword><keyword :v-word="vKeyword">{{accessLog.requestURI}}</keyword> <a :href="accessLog.scheme + '://' + accessLog.host + accessLog.requestURI" target="_blank" title="新窗口打开" class="disabled"><i class="external icon tiny"></i> </a> {{accessLog.proto}}" </em> <keyword :v-word="vKeyword">{{accessLog.status}}</keyword> <code-label v-if="accessLog.attrs != null && accessLog.attrs['cache.status'] == 'HIT'">cache hit</code-label> <code-label v-if="accessLog.firewallActions != null && accessLog.firewallActions.length > 0">waf {{accessLog.firewallActions}}</code-label> <span v-if="accessLog.tags != null && accessLog.tags.length > 0">- <code-label v-for="tag in accessLog.tags">{{tag}}</code-label></span> - 耗时:{{formatCost(accessLog.requestTime)}} ms <span v-if="accessLog.humanTime != null && accessLog.humanTime.length > 0" class="grey small"> ({{accessLog.humanTime}})</span>
|
||||||
<a href="" @click.prevent="showLog" title="查看详情"><i class="icon expand"></i></a>
|
<a href="" @click.prevent="showLog" title="查看详情"><i class="icon expand"></i></a>
|
||||||
</div>`
|
</div>`
|
||||||
})
|
})
|
||||||
@@ -62,7 +62,7 @@ Vue.component("http-firewall-actions-box", {
|
|||||||
ipListLevels: [],
|
ipListLevels: [],
|
||||||
|
|
||||||
// 动作参数
|
// 动作参数
|
||||||
blockLife: "",
|
blockTimeout: "",
|
||||||
captchaLife: "",
|
captchaLife: "",
|
||||||
get302Life: "",
|
get302Life: "",
|
||||||
post307Life: "",
|
post307Life: "",
|
||||||
@@ -89,12 +89,12 @@ Vue.component("http-firewall-actions-box", {
|
|||||||
})
|
})
|
||||||
this.actionOptions = {}
|
this.actionOptions = {}
|
||||||
},
|
},
|
||||||
blockLife: function (v) {
|
blockTimeout: function (v) {
|
||||||
v = parseInt(v)
|
v = parseInt(v)
|
||||||
if (isNaN(v)) {
|
if (isNaN(v)) {
|
||||||
this.actionOptions["life"] = 0
|
this.actionOptions["timeout"] = 0
|
||||||
} else {
|
} else {
|
||||||
this.actionOptions["life"] = v
|
this.actionOptions["timeout"] = v
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
captchaLife: function (v) {
|
captchaLife: function (v) {
|
||||||
@@ -121,7 +121,7 @@ Vue.component("http-firewall-actions-box", {
|
|||||||
this.actionOptions["life"] = v
|
this.actionOptions["life"] = v
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
recordIPType: function () {
|
recordIPType: function (v) {
|
||||||
this.recordIPListId = 0
|
this.recordIPListId = 0
|
||||||
},
|
},
|
||||||
recordIPTimeout: function (v) {
|
recordIPTimeout: function (v) {
|
||||||
@@ -168,7 +168,7 @@ Vue.component("http-firewall-actions-box", {
|
|||||||
this.actionOptions = {}
|
this.actionOptions = {}
|
||||||
|
|
||||||
// 动作参数
|
// 动作参数
|
||||||
this.blockLife = ""
|
this.blockTimeout = ""
|
||||||
this.captchaLife = ""
|
this.captchaLife = ""
|
||||||
this.get302Life = ""
|
this.get302Life = ""
|
||||||
this.post307Life = ""
|
this.post307Life = ""
|
||||||
@@ -192,8 +192,13 @@ Vue.component("http-firewall-actions-box", {
|
|||||||
this.action = this.vActions.$find(function (k, v) {
|
this.action = this.vActions.$find(function (k, v) {
|
||||||
return v.code == that.actionCode
|
return v.code == that.actionCode
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 滚到界面底部
|
||||||
|
this.scroll()
|
||||||
},
|
},
|
||||||
remove: function (index) {
|
remove: function (index) {
|
||||||
|
this.isAdding = false
|
||||||
|
this.editingIndex = -1
|
||||||
this.configs.$remove(index)
|
this.configs.$remove(index)
|
||||||
},
|
},
|
||||||
update: function (index, config) {
|
update: function (index, config) {
|
||||||
@@ -211,9 +216,9 @@ Vue.component("http-firewall-actions-box", {
|
|||||||
|
|
||||||
switch (config.code) {
|
switch (config.code) {
|
||||||
case "block":
|
case "block":
|
||||||
this.blockLife = ""
|
this.blockTimeout = ""
|
||||||
if (config.options.life != null || config.options.life > 0) {
|
if (config.options.timeout != null || config.options.timeout > 0) {
|
||||||
this.blockLife = config.options.life.toString()
|
this.blockTimeout = config.options.timeout.toString()
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case "allow":
|
case "allow":
|
||||||
@@ -247,8 +252,13 @@ Vue.component("http-firewall-actions-box", {
|
|||||||
if (config.options.timeout > 0) {
|
if (config.options.timeout > 0) {
|
||||||
this.recordIPTimeout = config.options.timeout.toString()
|
this.recordIPTimeout = config.options.timeout.toString()
|
||||||
}
|
}
|
||||||
this.recordIPListId = config.options.ipListId
|
let that = this
|
||||||
this.recordIPListName = config.options.ipListName
|
|
||||||
|
// VUE需要在函数执行完之后才会调用watch函数,这样会导致设置的值被覆盖,所以这里使用setTimeout
|
||||||
|
setTimeout(function () {
|
||||||
|
that.recordIPListId = config.options.ipListId
|
||||||
|
that.recordIPListName = config.options.ipListName
|
||||||
|
})
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
case "tag":
|
case "tag":
|
||||||
@@ -274,18 +284,25 @@ Vue.component("http-firewall-actions-box", {
|
|||||||
return v.id == config.options.groupId
|
return v.id == config.options.groupId
|
||||||
})
|
})
|
||||||
|
|
||||||
this.goSetId = config.options.setId
|
// VUE需要在函数执行完之后才会调用watch函数,这样会导致设置的值被覆盖,所以这里使用setTimeout
|
||||||
if (this.goGroup != null) {
|
let that = this
|
||||||
let set = this.goGroup.sets.$find(function (k, v) {
|
setTimeout(function () {
|
||||||
|
that.goSetId = config.options.setId
|
||||||
|
if (that.goGroup != null) {
|
||||||
|
let set = that.goGroup.sets.$find(function (k, v) {
|
||||||
return v.id == config.options.setId
|
return v.id == config.options.setId
|
||||||
})
|
})
|
||||||
if (set != null) {
|
if (set != null) {
|
||||||
this.goSetName = set.name
|
that.goSetName = set.name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 滚到界面底部
|
||||||
|
this.scroll()
|
||||||
},
|
},
|
||||||
cancel: function () {
|
cancel: function () {
|
||||||
this.isAdding = false
|
this.isAdding = false
|
||||||
@@ -335,7 +352,7 @@ Vue.component("http-firewall-actions-box", {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.actionOptions = {
|
this.actionOptions = {
|
||||||
groupId: groupId,
|
groupId: groupId.toString(),
|
||||||
groupName: this.goGroupName
|
groupName: this.goGroupName
|
||||||
}
|
}
|
||||||
} else if (this.actionCode == "go_set") { // go_set
|
} else if (this.actionCode == "go_set") { // go_set
|
||||||
@@ -358,9 +375,9 @@ Vue.component("http-firewall-actions-box", {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.actionOptions = {
|
this.actionOptions = {
|
||||||
groupId: groupId,
|
groupId: groupId.toString(),
|
||||||
groupName: this.goGroupName,
|
groupName: this.goGroupName,
|
||||||
setId: setId,
|
setId: setId.toString(),
|
||||||
setName: this.goSetName
|
setName: this.goSetName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -419,6 +436,14 @@ Vue.component("http-firewall-actions-box", {
|
|||||||
callback()
|
callback()
|
||||||
})
|
})
|
||||||
document.head.appendChild(jsFile)
|
document.head.appendChild(jsFile)
|
||||||
|
},
|
||||||
|
scroll: function () {
|
||||||
|
setTimeout(function () {
|
||||||
|
let mainDiv = document.getElementsByClassName("main")
|
||||||
|
if (mainDiv.length > 0) {
|
||||||
|
mainDiv[0].scrollTo(0, 1000)
|
||||||
|
}
|
||||||
|
}, 10)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
template: `<div>
|
template: `<div>
|
||||||
@@ -427,6 +452,18 @@ Vue.component("http-firewall-actions-box", {
|
|||||||
<div v-for="(config, index) in configs" :data-index="index" :key="config.id" class="ui label small basic" :class="{blue: index == editingIndex}" style="margin-bottom: 0.4em">
|
<div v-for="(config, index) in configs" :data-index="index" :key="config.id" class="ui label small basic" :class="{blue: index == editingIndex}" style="margin-bottom: 0.4em">
|
||||||
{{config.name}} ({{config.code.toUpperCase()}})
|
{{config.name}} ({{config.code.toUpperCase()}})
|
||||||
|
|
||||||
|
<!-- block -->
|
||||||
|
<span v-if="config.code == 'block' && config.options.timeout > 0">:有效期{{config.options.timeout}}秒</span>
|
||||||
|
|
||||||
|
<!-- captcha -->
|
||||||
|
<span v-if="config.code == 'captcha' && config.options.life > 0">:有效期{{config.options.life}}秒</span>
|
||||||
|
|
||||||
|
<!-- get 302 -->
|
||||||
|
<span v-if="config.code == 'get_302' && config.options.life > 0">:有效期{{config.options.life}}秒</span>
|
||||||
|
|
||||||
|
<!-- post 307 -->
|
||||||
|
<span v-if="config.code == 'post_307' && config.options.life > 0">:有效期{{config.options.life}}秒</span>
|
||||||
|
|
||||||
<!-- record_ip -->
|
<!-- record_ip -->
|
||||||
<span v-if="config.code == 'record_ip'">:{{config.options.ipListName}}</span>
|
<span v-if="config.code == 'record_ip'">:{{config.options.ipListName}}</span>
|
||||||
|
|
||||||
@@ -461,7 +498,7 @@ Vue.component("http-firewall-actions-box", {
|
|||||||
<td>封锁时间</td>
|
<td>封锁时间</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="ui input right labeled">
|
<div class="ui input right labeled">
|
||||||
<input type="text" style="width: 5em" maxlength="10" v-model="blockLife" @keyup.enter="confirm()" @keypress.enter.prevent="1"/>
|
<input type="text" style="width: 5em" maxlength="10" v-model="blockTimeout" @keyup.enter="confirm()" @keypress.enter.prevent="1"/>
|
||||||
<span class="ui label">秒</span>
|
<span class="ui label">秒</span>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
@@ -475,7 +512,7 @@ Vue.component("http-firewall-actions-box", {
|
|||||||
<input type="text" style="width: 5em" maxlength="10" v-model="captchaLife" @keyup.enter="confirm()" @keypress.enter.prevent="1"/>
|
<input type="text" style="width: 5em" maxlength="10" v-model="captchaLife" @keyup.enter="confirm()" @keypress.enter.prevent="1"/>
|
||||||
<span class="ui label">秒</span>
|
<span class="ui label">秒</span>
|
||||||
</div>
|
</div>
|
||||||
<p class="comment">验证通过后在这个时间内不再验证。</p>
|
<p class="comment">验证通过后在这个时间内不再验证,默认600秒。</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
@@ -514,7 +551,7 @@ Vue.component("http-firewall-actions-box", {
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr v-if="actionCode == 'record_ip'">
|
<tr v-if="actionCode == 'record_ip'">
|
||||||
<td>选择IP名单</td>
|
<td>选择IP名单 *</td>
|
||||||
<td>
|
<td>
|
||||||
<div v-if="recordIPListId > 0" class="ui label basic small">{{recordIPListName}} <a href="" @click.prevent="removeRecordIPList"><i class="icon remove small"></i></a></div>
|
<div v-if="recordIPListId > 0" class="ui label basic small">{{recordIPListName}} <a href="" @click.prevent="removeRecordIPList"><i class="icon remove small"></i></a></div>
|
||||||
<button type="button" class="ui button tiny" @click.prevent="selectRecordIPList">+</button>
|
<button type="button" class="ui button tiny" @click.prevent="selectRecordIPList">+</button>
|
||||||
@@ -533,7 +570,7 @@ Vue.component("http-firewall-actions-box", {
|
|||||||
<td>超时时间</td>
|
<td>超时时间</td>
|
||||||
<td>
|
<td>
|
||||||
<div class="ui input right labeled">
|
<div class="ui input right labeled">
|
||||||
<input type="text" style="width: 5em" maxlength="10" v-model="recordIPTimeout" @keyup.enter="confirm()" @keypress.enter.prevent="1"/>
|
<input type="text" style="width: 6em" maxlength="10" v-model="recordIPTimeout" @keyup.enter="confirm()" @keypress.enter.prevent="1"/>
|
||||||
<span class="ui label">秒</span>
|
<span class="ui label">秒</span>
|
||||||
</div>
|
</div>
|
||||||
<p class="comment">0表示不超时。</p>
|
<p class="comment">0表示不超时。</p>
|
||||||
@@ -585,5 +622,6 @@ Vue.component("http-firewall-actions-box", {
|
|||||||
<div v-if="!isAdding">
|
<div v-if="!isAdding">
|
||||||
<button class="ui button tiny" type="button" @click.prevent="add">+</button>
|
<button class="ui button tiny" type="button" @click.prevent="add">+</button>
|
||||||
</div>
|
</div>
|
||||||
|
<p class="comment">系统总是会先执行记录日志、标签等不会修改请求的动作,再执行阻止、验证码等可能改变请求的动作。</p>
|
||||||
</div>`
|
</div>`
|
||||||
})
|
})
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>规则</td>
|
<td>规则 *</td>
|
||||||
<td>
|
<td>
|
||||||
<http-firewall-rules-box :v-rules="rules" :v-type="type"></http-firewall-rules-box>
|
<http-firewall-rules-box :v-rules="rules" :v-type="type"></http-firewall-rules-box>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
{$layout}
|
{$layout}
|
||||||
|
|
||||||
{$template "waf_menu"}
|
{$template "waf_menu"}
|
||||||
|
|
||||||
<second-menu style="margin-top:-1em">
|
<second-menu style="margin-top:-1em">
|
||||||
<a href="" class="item" @click.prevent="createGroup(type)">[添加分组]</a>
|
<a href="" class="item" @click.prevent="createGroup(type)">[添加分组]</a>
|
||||||
</second-menu>
|
</second-menu>
|
||||||
|
|
||||||
<p class="comment" v-if="groups.length == 0">暂时还没有规则分组。</p>
|
<p class="comment" v-if="groups.length == 0">暂时还没有规则分组。</p>
|
||||||
|
|
||||||
<table class="ui table selectable celled" v-if="groups.length > 0" id="sortable-table">
|
<table class="ui table selectable celled" v-if="groups.length > 0" id="sortable-table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th style="width:3em"></th>
|
<th style="width:3em"></th>
|
||||||
@@ -39,6 +39,6 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<p class="comment" v-if="groups.length > 0">所有规则匹配顺序为从上到下,可以拖动左侧的<i class="icon bars"></i>排序。</p>
|
<p class="comment" v-if="groups.length > 0">所有规则匹配顺序为从上到下,可以拖动左侧的<i class="icon bars"></i>排序。</p>
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>规则</td>
|
<td>规则 *</td>
|
||||||
<td>
|
<td>
|
||||||
<http-firewall-rules-box :v-rules="rules" :v-type="type"></http-firewall-rules-box>
|
<http-firewall-rules-box :v-rules="rules" :v-type="type"></http-firewall-rules-box>
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
<th style="width:3em"></th>
|
<th style="width:3em"></th>
|
||||||
<th nowrap="">规则集名称</th>
|
<th nowrap="">规则集名称</th>
|
||||||
<th nowrap="">规则</th>
|
<th nowrap="">规则</th>
|
||||||
<th nowrap="" class="center">关系</th>
|
<th nowrap="" class="center one wide">关系</th>
|
||||||
<th nowrap="">动作</th>
|
<th nowrap="">动作</th>
|
||||||
<th class="three op">操作</th>
|
<th class="three op">操作</th>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -52,11 +52,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<span class="ui disabled" v-if="set.rules.length == 0">暂时还没有规则</span>
|
<span class="ui disabled" v-if="set.rules.length == 0">暂时还没有规则</span>
|
||||||
</td>
|
</td>
|
||||||
<td class="center">{{set.connector.toUpperCase()}}</td>
|
<td class="center">
|
||||||
<td nowrap=""><span :class="{red:set.action == 'BLOCK' || set.action == 'CAPTCHA', green:set.action != 'BLOCK' && set.action != 'CAPTCHA'}">{{set.actionName}}[{{set.action.toUpperCase()}}]</span>
|
<span v-if="set.connector.toUpperCase() == 'OR'">或</span><span v-else>和</span>
|
||||||
<div v-if="set.actionLinks != null && set.actionLinks.length > 0" style="margin-top:0.3em">
|
<span class="small grey">({{set.connector.toUpperCase()}})</span>
|
||||||
<span class="disabled">-></span> <span v-for="link in set.actionLinks"><a :href="link.url"><span class="disabled">[{{link.name}}]</span></a> </span>
|
</td>
|
||||||
</div>
|
<td nowrap="">
|
||||||
|
<http-firewall-actions-view :v-actions="set.actions"></http-firewall-actions-view>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="" @click.prevent="updateSet(set.id)">修改</a> <a href="" @click.prevent="updateSetOn(set.id, false)" v-if="set.isOn">停用</a><a href="" @click.prevent="updateSetOn(set.id, true)" v-if="!set.isOn">启用</a> <a href="" @click.prevent="deleteSet(set.id)">删除</a>
|
<a href="" @click.prevent="updateSet(set.id)">修改</a> <a href="" @click.prevent="updateSetOn(set.id, false)" v-if="set.isOn">停用</a><a href="" @click.prevent="updateSetOn(set.id, true)" v-if="!set.isOn">启用</a> <a href="" @click.prevent="deleteSet(set.id)">删除</a>
|
||||||
|
|||||||
Reference in New Issue
Block a user