springboot项目敏感词屏蔽html页面modelAndView中值基于HandlerInterceptor实现已及外围接口Response中值屏蔽基于Filter

1 需求背景:

网站内容防止触发广告法,需要自动屏蔽些关键字;例如: "最", "第一" 等;可以通过后台配置及时生效

2 html页面屏蔽实现:

中小型公司官网等项目,日访问量不会很大,而且要考虑SEO问题,而且基本就1个程序员.项目选型大多数都不会使用前后端分离技术,而是选择前后端一体单应用,

例如:上古时期的springMVC+JSP 及后来的 springboot + html + 模板引擎(freemark,velocity,thymeleaf).

对于上述需求,要求屏蔽词语随时可以更改, 那么就不能在编写文章入库时候处理,只能在页面展示时候屏蔽,

 

在springboot返回页面传值时使用modelAndView赋值,那么怎么进行敏感词过滤呢?

其实很简单,HandlerInterceptor的 postHandle中会直接获取到modelAndView,对其ModelMap值遍历过滤就可以;屏蔽的关键字需要从数据库中读取

@Component
public class BlackWordsInterceptor implements HandlerInterceptor {
    @Autowired
    private BlackWordsUtil blackWordsUtil;

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) {
        if(modelAndView != null){
            ModelMap modelMap = modelAndView.getModelMap();

            modelMap.forEach((k,v) -> {
                try {
                    //跳过敏感词校验的key
                    if(!CST.BLACK_WORDS_SKIP_KEY.contains(k)){
                        String s = BeanUtil.beanToJson(v);
                        s = blackWordsUtil.doFilter(s);
                        //过滤后的值覆盖旧值
                        modelMap.addAttribute(k, BeanUtil.jsonToBean(s,v.getClass()));
                    }
                } catch (Exception e) {
                }
            });
        }
    }
}

 

@Component
public class BlackWordsUtil {
    public final String REPLACE_WORDS = "*";
    @Autowired
    private IBlackWordsService blackWordsService;

    public String doFilter(String str){
        if(StringUtils.isBlank(str)){
            return str;
        }
        List<BlackWords> blackWords = blackWordsService.findAll();
        for (BlackWords blackWord : ListUtil.nvlList(blackWords)) {
            str = str.replaceAll(blackWord.getValue(),getStr(blackWord.getValue().length()));
        }
        return str;
    }
    private String getStr(int l){
        String s = "";
        for(int i=0 ; i < l;i++){
            s += REPLACE_WORDS;
        }
        return s;
    }
}

3 提供接口过滤

 

@WebFilter(urlPatterns = {"/pc/*","/app/*","/uni/*"}, filterName = "blackWordsFilter")
@Order(1)
// 需要在启动类加@ServletComponentScan注解  urlPatterns 必须是 /* 结尾
public class BlackWordsFilter implements Filter {
    @Autowired
    private BlackWordsUtil blackWordsUtil;
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        ResponseWrapper wrapperResponse = new ResponseWrapper((HttpServletResponse) response);//转换成代理类
        // 这里只拦截返回,直接让请求过去,如果在请求前有处理,可以在这里处理
        chain.doFilter(request, wrapperResponse);
        byte[] content = wrapperResponse.getContent();//获取返回值
        //判断是否有值
        if (content != null && content.length > 0) {

            String str = new String(content, "UTF-8");
            String outStr = blackWordsUtil.doFilter(str);
            //把返回值输出到客户端
            byte[] outBytes = outStr.getBytes();
            ServletOutputStream out = response.getOutputStream();
            response.setContentLength(outBytes.length);//重新设置返回长度
            out.write(outBytes);
            out.flush();
        }
    }

    @Override
    public void destroy() {
        Filter.super.destroy();
    }

}

 

 

 

 

public class ResponseWrapper extends HttpServletResponseWrapper
{

    private ByteArrayOutputStream buffer;

    private ServletOutputStream out;

    public ResponseWrapper(HttpServletResponse httpServletResponse)
    {
        super(httpServletResponse);
        buffer = new ByteArrayOutputStream();
        out = new WrapperOutputStream(buffer);
    }

    @Override
    public ServletOutputStream getOutputStream()
        throws IOException
    {
        return out;
    }

    @Override
    public void flushBuffer()
        throws IOException
    {
        if (out != null)
        {
            out.flush();
        }
    }

    public byte[] getContent()
        throws IOException
    {
        flushBuffer();
        return buffer.toByteArray();
    }

    class WrapperOutputStream extends ServletOutputStream
    {
        private ByteArrayOutputStream bos;

        public WrapperOutputStream(ByteArrayOutputStream bos)
        {
            this.bos = bos;
        }

        @Override
        public void write(int b)
            throws IOException
        {
            bos.write(b);
        }

        @Override
        public boolean isReady()
        {

            // TODO Auto-generated method stub
            return false;

        }

        @Override
        public void setWriteListener(WriteListener arg0)
        {

            // TODO Auto-generated method stub

        }
    }

}

 

4 测试效果


1页面屏蔽

 

 

 

 2 接口屏蔽

 

posted @ 2022-06-24 11:00  若星汉浮云  Views(81)  Comments(0Edit  收藏  举报