zoukankan      html  css  js  c++  java
  • Springboot敏感词过滤

    实现方案2种

    1.Springboot参数拦截 

    继承AbstractNamedValueMethodArgumentResolver

    2.Springboot AOP  所有String类型的参数提交都会被验证,替换规则参考百度

      @Around实现

    package com.bysk.admin.common.filter;
    
    import com.bysk.base.util.RedisUtils;
    import lombok.SneakyThrows;
    import org.aspectj.lang.ProceedingJoinPoint;
    import org.aspectj.lang.annotation.Around;
    import org.aspectj.lang.annotation.Aspect;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    import javax.servlet.http.HttpServletRequest;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    
    /**
     * @author: zhangyb
     * @date: 2020/11/19 9:21
     * @Description: 敏感词过滤 只会拦截使用了Post和put请求的方法即修改和新增,感觉会影响性能,
     *              后面建议使用单独注解实现关键字过滤
     * @UpdateUser : zhangyb
     * @UpdateDate :2020/11/19 9:21
     * @UpdateRemark:
     */
    @Aspect
    @Component
    public class SensitiveWord {
        @Autowired
        RedisUtils redisUtils;
        @Autowired
        WordFilter wordFilter;
        @Around("@annotation(org.springframework.web.bind.annotation.PostMapping)||@annotation(org.springframework.web.bind.annotation.PutMapping)")
        @SneakyThrows
        public Object doBefore(ProceedingJoinPoint point) {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            if (request.getRequestURI().contains("/word/sensitiveword")) {
                return point.proceed();
            }
            //所有的参数对象
            for (Object arg : point.getArgs()) {
                //参数对象,通过反射将String类型的值进行敏感词过滤
                Class<?> aClass = arg.getClass();
                //递归遍历,将所有String参数进行敏感词匹配
                foundString(aClass,arg);
            }
            return  point.proceed();
        }
    
        /**
        * @author: zhangyb
        * @date:  2020/11/19 13:57
        * @Description: 递归将String替换
        * @UpdateUser : zhangyb
        * @UpdateDate :2020/11/19 13:57
        * @UpdateRemark:
        */
        @SneakyThrows
        public Class<?> foundString(Class clazz,Object arg ){
            Field[] declaredFields = clazz.getDeclaredFields();
            for (Field declaredField : declaredFields) {
                Class<?> type = declaredField.getType();
                if (type==String.class&&!Modifier.toString(declaredField.getModifiers()).contains("final")){
                    //如果是String类型,进行关键词匹配 且要排除final修饰的字段
                        declaredField.setAccessible(true);
                        String value=(String)declaredField.get(arg);
                        declaredField.set(arg, wordFilter.replaceWords(value));
                }else if (type.getPackage()!=null&&type.getPackage().getName().contains("com.bysk")){
                            Method[] methods = clazz.getMethods();
                            for (Method method : methods) {
                                String name = method.getName();
                                if (name.toLowerCase().contains("get"+declaredField.getName().toLowerCase())){
                                    Object invoke = method.invoke(arg);
                                    this.foundString(type,invoke);
                                    break;
                                }
                            }
                        }
            }
            return  clazz;
        }
    }
    package com.bysk.admin.common.filter;
    import com.bysk.admin.modules.word.mapper.SensitiveWordMapper;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.stereotype.Component;
    
    import java.util.*;
    /**
     * @Author: zhangyb
     * @Date: 2020/11/19 11:13
     */
    
    /**
     * @program: 农事云
     * @description:
     * @Author: Zhangyb
     * @CreateDate: 11:13
     * @UpdateUser:
     * @UpdateDate
     * @UpdateRemark:
     * @Version: 1.0
     */
    @Slf4j
    @Component
    public class WordFilter {
        private final static String WORDS = "WORDS";
        private final static String REPLACE_CHAR = "*";
        private static HashMap sensitiveWordMap;
        /**     * 最小匹配规则     */
        private static int minMatchTYpe = 1;
        /**     * 最大匹配规则     */
        private static int maxMatchType = 2;
        @Autowired
        private RedisTemplate<String, Object> redisTemplate;
        @Autowired
        private SensitiveWordMapper sensitiveWordMapper ;
    
        public  String replaceWords(String text) {
            if (StringUtils.isBlank(text)) {
                return text;
            }
            List<Object> words = redisTemplate.opsForList().range("SensitiveWord", 0, -1);
            if (words.size()<=0){
                words=sensitiveWordMapper.listStr();
                //更新redis
                redisTemplate.opsForList().leftPushAll("SensitiveWord",sensitiveWordMapper.listStr());
            }
            //缓存获取敏感词汇原记录
            return WordFilter.replaceSensitiveWord(words, text, WordFilter.minMatchTYpe);
        }
    
        /**
         * 替换敏感字字符
         *
         * @param data      敏感字集合
         * @param txt       待检查文本
         * @param matchType 匹配规则
         */
        private static String replaceSensitiveWord(List<Object> data, String txt, int matchType) {
            if (sensitiveWordMap == null) {
                addSensitiveWord(data);
            }
            String resultTxt = txt;
            //获取所有的敏感词
            List<String> set = getSensitiveWord(txt, matchType);
            Iterator<String> iterator = set.iterator();
            while (iterator.hasNext()) {
                resultTxt = resultTxt.replaceAll(iterator.next(), REPLACE_CHAR);
            }
            return resultTxt;
        }
    
    
        /**
         * 读取敏感词库,将敏感词放入HashSet中,构建一个DFA算法模型:
         * 说明:该方法来源于互联网
         */
        private static void addSensitiveWord(List<Object> datas) {
            sensitiveWordMap = new HashMap(datas.size());
            Iterator<Object> iterator = datas.iterator();
            Map<String, Object> now = null;
            Map now2 = null;
            while (iterator.hasNext()) {
                now2 = sensitiveWordMap;
                String word = (String)iterator.next(); //敏感词
                word=word.trim();
                for (int i = 0; i < word.length(); i++) {
                    char key_word = word.charAt(i);
                    Object obj = now2.get(key_word);
                    if (obj != null) { //存在
                        now2 = (Map) obj;
                    } else { //不存在
                        now = new HashMap<String, Object>();
                        now.put("isEnd", "0");
                        now2.put(key_word, now);
                        now2 = now;
                    }
                    if (i == word.length() - 1) {
                        now2.put("isEnd", "1");
                    }
                }
            }
        }
    
        /**
         * 获取内容中的敏感词
         *说明:该方法来源于互联网
         * @param text      内容
         * @param matchType 匹配规则 1=不最佳匹配,2=最佳匹配
         * @return
         */
        private static List<String> getSensitiveWord(String text, int matchType) {
            List<String> words = new ArrayList<String>();
            Map now = sensitiveWordMap;
            int count = 0; //初始化敏感词长度
            int start = 0; //标志敏感词开始的下标
            for (int i = 0; i < text.length(); i++) {
                char key = text.charAt(i);
                now = (Map) now.get(key);
                if (now != null) { //存在
                    count++;
                    if (count == 1) {
                        start = i;
                    }
                    if ("1".equals(now.get("isEnd"))) { //敏感词结束
                        now = sensitiveWordMap; //重新获取敏感词库
                        words.add(text.substring(start, start + count)); //取出敏感词,添加到集合
                        count = 0; //初始化敏感词长度
                    }
                } else { //不存在
                    now = sensitiveWordMap;//重新获取敏感词库
                    if (count == 1 && matchType == 1) { //不最佳匹配
                        count = 0;
                    } else if (count == 1 && matchType == 2) { //最佳匹配
                        words.add(text.substring(start, start + count));
                        count = 0;
                    }
                }
            }
            return words;
        }
        public WordFilter() {
            super();
        }
    }
  • 相关阅读:
    【杭电】[2092]整数解cpp
    【杭电】[2045]不容易系列之(3)——LELE的RPG难题
    【杭电】[2045]不容易系列之(3)——LELE的RPG难题
    【杭电】[2502]月之数
    【杭电】[2502]月之数
    【杭电】[2187]悼念512汶川大地震遇难同胞——老人是真饿了
    【杭电】[2187]悼念512汶川大地震遇难同胞——老人是真饿了
    【杭电】[1877]又一版 A+B
    【杭电】[1877]又一版 A+B
    Sevlet 02: Servlet对比JSP
  • 原文地址:https://www.cnblogs.com/xyzxy/p/14016031.html
Copyright © 2011-2022 走看看