Procházet zdrojové kódy

黑名单增加时间范围的条件限制

xusl před 1 rokem
rodič
revize
33048bef90

+ 1 - 1
backend/src/main/java/com/jiayue/ssi/config/WebConfig.java

@@ -50,7 +50,7 @@ public class WebConfig implements WebMvcConfigurer {
         // 加载上报对象缓存
         List<SysBlacklist> sysBlacklists = sysBlacklistService.list();
         for (SysBlacklist sysBlacklist:sysBlacklists){
-            CacheConstants.blacklistMap.put(sysBlacklist.getIp(),sysBlacklist.getId());
+            CacheConstants.blacklistMap.put(sysBlacklist.getIp(),sysBlacklist);
         }
     }
 }

+ 4 - 2
backend/src/main/java/com/jiayue/ssi/constant/CacheConstants.java

@@ -1,5 +1,7 @@
 package com.jiayue.ssi.constant;
 
+import com.jiayue.ssi.entity.SysBlacklist;
+
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
@@ -59,9 +61,9 @@ public class CacheConstants {
     public static boolean use_send_mail = true;
 
     /**
-     * ip黑名单缓存
+     * ip黑名单缓存<ip,对象>
      */
-    public static ConcurrentMap<String, Long> blacklistMap = new ConcurrentHashMap<>();
+    public static ConcurrentMap<String, SysBlacklist> blacklistMap = new ConcurrentHashMap<>();
 
     /**
      * 用户名对应明文密码缓存

+ 14 - 5
backend/src/main/java/com/jiayue/ssi/controller/IpBlacklistController.java

@@ -10,6 +10,8 @@ import com.jiayue.ssi.backenum.BusinessType;
 import com.jiayue.ssi.constant.CacheConstants;
 import com.jiayue.ssi.constant.CustomException;
 import com.jiayue.ssi.entity.SysBlacklist;
+import com.jiayue.ssi.entity.SysUser;
+import com.jiayue.ssi.entity.SysUserRole;
 import com.jiayue.ssi.service.SysBlacklistService;
 import com.jiayue.ssi.util.*;
 import lombok.extern.slf4j.Slf4j;
@@ -90,18 +92,25 @@ public class IpBlacklistController {
     @OperateLog(title = "黑名单管理", businessType = BusinessType.INSERT, auditType = AuditType.SYS)
     @PreAuthorize("@ss.hasPermi('system:ipblacklist:add')")
     @PreventReplay
-    public ResponseVO addIp(String ip) throws CustomException {
+    public ResponseVO addIp(@RequestBody SysBlacklist sysBlacklist) throws CustomException {
         try {
-            if (!IPUtils.isIP(ip)) {
+            if (!IPUtils.isIP(sysBlacklist.getIp())) {
                 return ResponseVO.fail("ip不合法,不能添加!");
             }
-            SysBlacklist sysBlacklist = new SysBlacklist();
-            sysBlacklist.setIp(ip);
+            // ip存在的不能再次添加
+            QueryWrapper<SysBlacklist> wrapper = new QueryWrapper<>();
+            wrapper.eq("ip", sysBlacklist.getIp());
+            SysBlacklist sysBlacklist1 = sysBlacklistService.getOne(wrapper);
+            if (sysBlacklist1!=null){
+                return ResponseVO.fail("ip已经存在,不能添加!");
+            }
+
+            sysBlacklist.setIp(sysBlacklist.getIp());
             sysBlacklist.setIpTime(new Date());
             sysBlacklist.setAddBy(SecurityContextUtil.getSysUser().getUsername());
             boolean bo = sysBlacklistService.save(sysBlacklist);
             if (bo) {
-                CacheConstants.blacklistMap.put(sysBlacklist.getIp(),sysBlacklist.getId());
+                CacheConstants.blacklistMap.put(sysBlacklist.getIp(),sysBlacklist);
                 return ResponseVO.success("添加ip成功");
             } else {
                 log.error("添加ip失败");

+ 9 - 1
backend/src/main/java/com/jiayue/ssi/entity/SysBlacklist.java

@@ -20,7 +20,15 @@ public class SysBlacklist {
     private Long id;
     /** IP地址 */
     private String ip;
-    /** ip锁定时间 */
+    /** IP锁定类型 0永久 1时间段*/
+    private String type;
+    /** 限制时间段开始时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
+    private Date limitStartTime;
+    /** 限制时间段结束时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
+    private Date limitEndTime;
+    /** ip创建锁定时间 */
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
     private Date ipTime;
     /** 添加者 */

+ 27 - 8
backend/src/main/java/com/jiayue/ssi/filter/InterfaceLimitFilter.java

@@ -41,12 +41,30 @@ public class InterfaceLimitFilter extends OncePerRequestFilter {
     synchronized void checkIp(HttpServletRequest request,HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException{
         String remoteIp = IPUtils.getIpAddr(request);
         if (CacheConstants.blacklistMap.get(remoteIp)!=null){
-            log.info(remoteIp+"进入黑名单进行拦截!");
-            response.setHeader("Access-Control-Allow-Origin", "*");
-            response.setStatus(410);
-            response.setContentType("text/html;charset=utf-8");
-            response.getWriter().write("访问频率过快,IP已进黑名单,请联系管理员!");
-            return;
+            SysBlacklist sysBlacklist = CacheConstants.blacklistMap.get(remoteIp);
+            if ("1".equals(sysBlacklist.getType())){
+                // 此ip在黑名单里类型是时间范围,则需要判断当前时间是否在范围中
+                Date startDate = sysBlacklist.getLimitStartTime();
+                Date endDate = sysBlacklist.getLimitEndTime();
+                // 当前时间
+                Date currentDate = new Date();
+                if (currentDate.after(startDate) && currentDate.before(endDate)){
+                    log.info(remoteIp+"进入黑名单进行拦截!");
+                    response.setHeader("Access-Control-Allow-Origin", "*");
+                    response.setStatus(410);
+                    response.setContentType("text/html;charset=utf-8");
+                    response.getWriter().write("IP已进黑名单,请联系管理员!");
+                    return;
+                }
+            }
+            else{
+                log.info(remoteIp+"进入黑名单进行拦截!");
+                response.setHeader("Access-Control-Allow-Origin", "*");
+                response.setStatus(410);
+                response.setContentType("text/html;charset=utf-8");
+                response.getWriter().write("IP已进黑名单,请联系管理员!");
+                return;
+            }
         }
         if (!InterfaceLimitUtil.checkInterface(request, 1000, 20)) {
             log.info("接口拦截:{} 请求超过限制频率【{}次/{}ms】,IP为{}", request.getRequestURI(), 10,1000, remoteIp);
@@ -54,15 +72,16 @@ public class InterfaceLimitFilter extends OncePerRequestFilter {
             SysBlacklist sysBlacklist = new SysBlacklist();
             sysBlacklist.setIp(remoteIp);
             sysBlacklist.setIpTime(new Date());
+            sysBlacklist.setType("0");
             sysBlacklist.setAddBy("SYSTEM");
             SpringUtils.getBean(SysBlacklistService.class).save(sysBlacklist);
             // 将锁定ip加入缓存
-            CacheConstants.blacklistMap.put(remoteIp,sysBlacklist.getId());
+            CacheConstants.blacklistMap.put(remoteIp,sysBlacklist);
 
             response.setHeader("Access-Control-Allow-Origin", "*");
             response.setStatus(410);
             response.setContentType("text/html;charset=utf-8");
-            response.getWriter().write("访问频率过快,IP已进黑名单,请联系管理员!");
+            response.getWriter().write("IP已进黑名单,请联系管理员!");
             return;
         }
         filterChain.doFilter(request, response);

+ 169 - 76
ui/src/views/sysManager/ipBlacklist/index.vue

@@ -61,7 +61,10 @@
           >
             <vxe-column type="radio" width="60"/>
             <vxe-table-column field="ip" title="IP地址"/>
-            <vxe-table-column field="ipTime" title="锁定时间"/>
+            <vxe-table-column field="type" title="限制类型" :formatter="typeFormat"/>
+            <vxe-table-column field="limitStartTime" title="限制开始时间"/>
+            <vxe-table-column field="limitEndTime" title="限制结束时间"/>
+            <vxe-table-column field="ipTime" title="添加时间"/>
             <vxe-table-column field="addBy" title="添加人"/>
           </vxe-table>
           <vxe-pager
@@ -78,15 +81,62 @@
         </div>
       </el-col>
     </el-row>
+
+    <!-- 添加对话框 -->
+    <el-dialog :title="title" :visible.sync="open" width="650px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" width="630px" label-width="80px">
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="IP地址" prop="ip">
+              <el-input id="ip" ref="ip" style="width: 220px" v-model="form.ip" placeholder="请输入IP"/>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
+            <el-form-item label="限制类型">
+              <el-select style="width: 220px" v-model="form.type" placeholder="请选择类型" @change="changeType">
+                <el-option
+                  v-for="item in typeOptions"
+                  :key="item.value"
+                  :label="item.label"
+                  :value="item.value"
+                ></el-option>
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row v-show="isShow">
+          <el-col :span="12">
+            <el-form-item label="限制时间">
+              <el-date-picker
+                value-format="yyyy-MM-dd HH:mm:ss"
+                v-model="form.limitTime"
+                type="datetimerange"
+                range-separator="至"
+                start-placeholder="开始时间"
+                end-placeholder="结束时间">
+              </el-date-picker>
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
 <script>
-import { debounce } from 'lodash'
+import {debounce} from 'lodash'
+
 export default {
   name: "ipBlacklist",
   data() {
     return {
+      isShow:false,
       // 遮罩层
       loading: true,
       showTable: true,
@@ -103,7 +153,7 @@ export default {
       // 用户表格数据
       userList: null,
       // 弹出层标题
-      title: "",
+      title: "IP黑名单",
       // 是否显示弹出层
       open: false,
       // 默认密码
@@ -111,10 +161,23 @@ export default {
       // 角色选项
       roleOptions: [],
       // 表单参数
-      form: {},
+      form: {
+        type: "0",
+      },
       // 查询参数
       queryParams: {
         ip: undefined
+      },
+      typeOptions: [
+        {value: '0', label: '永久'},
+        {value: '1', label: '时间范围'}
+      ],
+      // 表单校验
+      rules: {
+        ip: [
+          {required: true, message: "ip不能为空", trigger: "blur"},
+          {pattern: /[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/, message: "请输入正确的IP", trigger: "blur"}
+        ]
       }
     };
   },
@@ -123,13 +186,105 @@ export default {
     this.getList()
   },
   methods: {
+    changeType(val){
+      if (val=="0"){
+        this.isShow = false;
+      }
+      else{
+        this.isShow = true;
+      }
+    },
+    /** 提交按钮 */
+    submitForm: debounce(function () {
+      this.$refs["form"].validate(async valid => {
+        if (valid) {
+          if (this.form.type=="1"){
+            if (this.form.limitTime==undefined){
+              this.$message({
+                type: 'warning',
+                message: '请录入限制时间!'
+              });
+              return
+            }
+            else{
+              this.form.limitStartTime = this.form.limitTime[0]
+              this.form.limitEndTime = this.form.limitTime[1]
+            }
+          }
+
+          let sysTime
+          let lk
+          await this.$axios.get('/sysPolicyController/getLicenseKey').then((res) => {
+            sysTime = res.data.sysTime
+            lk = res.data.lk
+          }).catch((error) => {
+          })
+
+          this.form.sysTime = sysTime
+          this.form.lk = lk
+
+          await this.$axios.post('/ipBlacklistController/addIp', this.form).then((res) => {
+            if (res.code == 0) {
+              this.$message({
+                type: 'success',
+                message: '添加成功!'
+              });
+              this.open = false;
+              this.getList();
+              this.reset();
+            } else {
+              this.$message({
+                type: 'error',
+                message: res.data
+              });
+            }
+          }).catch((error) => {
+            this.$message({
+              type: 'error',
+              message: '添加失败!'
+            });
+            this.loading = false
+          })
+        }
+      });
+    }, 1000),
+    // 表单重置
+    reset() {
+      this.form = {
+        ip: undefined,
+        type: "0",
+        limitTime: undefined,
+        limitStartTime: undefined,
+        limitEndTime: undefined,
+        sysTime: undefined,
+        lk: undefined
+      };
+      this.isShow = false;
+    },
+    // 取消按钮
+    cancel() {
+      this.open = false;
+      this.reset();
+    },
+    // 列表状态格式化
+    typeFormat({cellValue}) {
+      let belongTo = '未知的类型'
+      for (let i = 0; i < this.typeOptions.length; i++) {
+        if (cellValue == "0") {
+          belongTo = "永久"
+        } else if (cellValue == "1") {
+          belongTo = "时间范围"
+        }
+      }
+      return belongTo
+    },
     handlePageChange({currentPage, pageSize}) {
       this.currentPage = currentPage
       this.pageSize = pageSize
       this.getList()
     },
     /** 查询用户列表 */
-    async getList(){
+    async getList() {
       let sysTime
       let lk
       await this.$axios.get('/sysPolicyController/getLicenseKey').then((res) => {
@@ -170,11 +325,11 @@ export default {
       })
     },
     /** 搜索按钮操作 */
-    handleQuery:debounce(function(){
+    handleQuery: debounce(function () {
       // 验证查询条件ip是否合理
-      if (this.queryParams.ip!=undefined && this.queryParams.ip!=''){
+      if (this.queryParams.ip != undefined && this.queryParams.ip != '') {
         var reg = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/
-        if (!reg.test(this.queryParams.ip)){
+        if (!reg.test(this.queryParams.ip)) {
           this.$message({
             type: 'warning',
             message: '请输入正确ip地址!'
@@ -185,41 +340,17 @@ export default {
       this.currentPage = 1
       this.pageSize = 10
       this.getList();
-    },1000),
+    }, 1000),
     /** 重置按钮操作 */
     resetQuery() {
       this.resetForm("queryForm");
     },
     /** 添加按钮操作 */
-    handleAdd(){
-      const ipReg = new RegExp(/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/)
-      this.$prompt('请输入黑名单IP','黑名单操作',{
-        confirmButtonText: '确定',
-        cancelButtonText: '取消',
-        inputValidator:(val)=>{
-          if (!ipReg.test(val)){
-            return false;
-          }
-        },
-        inputErrorMessage: 'IP格式不正确',
-        beforeClose(action, instance, done) {
-          if (action === "confirm") {
-            instance.$refs["confirm"].$el.onclick = (function (e) {
-              e = e || window.event;
-              if (e.detail != 0) {
-                done();
-              }
-            })();
-          } else {
-            done();
-          }
-        }
-      }).then(async({value})=>{
-        this.doAdd(value)
-      }).catch((e)=>{})
+    handleAdd() {
+      this.open = true;
     },
     /** 删除按钮操作 */
-    handleDelete(){
+    handleDelete() {
       const _selectData = this.$refs.xTable.getRadioRecord(true)
       if (_selectData == null) {
         this.$message({
@@ -238,47 +369,9 @@ export default {
       });
     },
     /**
-     * 添加提交
-     */
-    doAdd:debounce(async function(ip){
-      let sysTime
-      let lk
-      await this.$axios.get('/sysPolicyController/getLicenseKey').then((res) => {
-        sysTime = res.data.sysTime
-        lk = res.data.lk
-      }).catch((error) => {
-      })
-
-      const param = {
-        ip:ip,
-        sysTime: sysTime,
-        lk: lk
-      }
-      await this.$axios.post('/ipBlacklistController/addIp', param).then((res) => {
-        if (res.code == 0) {
-          this.$message({
-            type: 'success',
-            message: '添加成功!'
-          });
-          this.getList();
-        } else {
-          this.$message({
-            type: 'error',
-            message: res.data
-          });
-        }
-      }).catch((error) => {
-        this.$message({
-          type: 'error',
-          message: '添加失败!'
-        });
-        this.loading = false
-      })
-    },1000),
-    /**
      * 删除提交
      */
-    doDelete:debounce(async function(_selectData){
+    doDelete: debounce(async function (_selectData) {
       let sysTime
       let lk
       await this.$axios.get('/sysPolicyController/getLicenseKey').then((res) => {
@@ -312,7 +405,7 @@ export default {
         });
         this.loading = false
       })
-    },1000)
+    }, 1000)
   }
 };
 </script>