Forráskód Böngészése

敏感词屏蔽的范围包括留言、弹幕、缅怀信息

wuweihao 3 éve
szülő
commit
0884189370

+ 76 - 0
gis_admin/src/main/java/com/gis/admin/shiro/filters/CustomShiroFilterFactoryBean.java

@@ -0,0 +1,76 @@
+package com.gis.admin.shiro.filters;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
+import org.apache.shiro.web.filter.InvalidRequestFilter;
+import org.apache.shiro.web.filter.mgt.DefaultFilter;
+import org.apache.shiro.web.filter.mgt.FilterChainManager;
+import org.apache.shiro.web.filter.mgt.FilterChainResolver;
+import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
+import org.apache.shiro.web.mgt.WebSecurityManager;
+import org.apache.shiro.web.servlet.AbstractShiroFilter;
+import org.springframework.beans.factory.BeanInitializationException;
+
+import javax.servlet.Filter;
+import java.util.Map;
+
+/**
+ * 自定义ShiroFilterFactoryBean解决资源中文路径问题
+ */
+@Slf4j
+public class CustomShiroFilterFactoryBean extends ShiroFilterFactoryBean {
+    @Override
+    public Class getObjectType() {
+        return MySpringShiroFilter.class;
+    }
+
+    @Override
+    protected AbstractShiroFilter createInstance() throws Exception {
+
+        SecurityManager securityManager = getSecurityManager();
+        if (securityManager == null) {
+            String msg = "SecurityManager property must be set.";
+            throw new BeanInitializationException(msg);
+        }
+
+        if (!(securityManager instanceof WebSecurityManager)) {
+            String msg = "The security manager does not implement the WebSecurityManager interface.";
+            throw new BeanInitializationException(msg);
+        }
+
+        FilterChainManager manager = createFilterChainManager();
+        //Expose the constructed FilterChainManager by first wrapping it in a
+        // FilterChainResolver implementation. The AbstractShiroFilter implementations
+        // do not know about FilterChainManagers - only resolvers:
+        PathMatchingFilterChainResolver chainResolver = new PathMatchingFilterChainResolver();
+        chainResolver.setFilterChainManager(manager);
+
+        Map<String, Filter> filterMap = manager.getFilters();
+        Filter invalidRequestFilter = filterMap.get(DefaultFilter.invalidRequest.name());
+        if (invalidRequestFilter instanceof InvalidRequestFilter) {
+            //此处是关键,设置false跳过URL携带中文400,servletPath中文校验bug
+            ((InvalidRequestFilter) invalidRequestFilter).setBlockNonAscii(false);
+        }
+        //Now create a concrete ShiroFilter instance and apply the acquired SecurityManager and built
+        //FilterChainResolver.  It doesn't matter that the instance is an anonymous inner class
+        //here - we're just using it because it is a concrete AbstractShiroFilter instance that accepts
+        //injection of the SecurityManager and FilterChainResolver:
+        return new MySpringShiroFilter((WebSecurityManager) securityManager, chainResolver);
+    }
+
+    private static final class MySpringShiroFilter extends AbstractShiroFilter {
+        protected MySpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver) {
+            if (webSecurityManager == null) {
+                throw new IllegalArgumentException("WebSecurityManager property cannot be null.");
+            } else {
+                this.setSecurityManager(webSecurityManager);
+                if (resolver != null) {
+                    this.setFilterChainResolver(resolver);
+                }
+
+            }
+        }
+    }
+
+}

+ 149 - 0
gis_admin/src/main/java/com/gis/admin/shiro/filters/JwtFilter.java

@@ -0,0 +1,149 @@
+package com.gis.admin.shiro.filters;
+
+import com.alibaba.fastjson.JSONObject;
+import com.gis.admin.shiro.JwtAuthenticationException;
+import com.gis.admin.shiro.JwtToken;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.time.LocalDateTime;
+
+/**
+ * @Description: 鉴权登录拦截器
+ * @Author: Scott
+ * @Date: 2018/10/7
+ **/
+@Slf4j
+public class JwtFilter extends BasicHttpAuthenticationFilter {
+
+    private boolean allowOrigin = true;
+
+    public JwtFilter(){}
+    public JwtFilter(boolean allowOrigin){
+        this.allowOrigin = allowOrigin;
+    }
+
+    /**
+     * 执行登录认证
+     *
+     * @param request
+     * @param response
+     * @param mappedValue
+     * @return
+     */
+    @Override
+    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
+        try {
+            executeLogin(request, response);
+            return true;
+        } catch (Exception e) {
+//            throw new AuthenticationException("Token失效,请重新登录", e);
+            exceptionMsg(e, response);
+
+        }
+        // 前端没有响应,接收不到异常
+        return false;
+    }
+
+    /**
+     *
+     */
+    @Override
+    protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
+        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+        String token = httpServletRequest.getHeader("token");
+        // update-begin--Author:lvdandan Date:20210105 for:JT-355 OA聊天添加token验证,获取token参数
+        if(token == null){
+            token = httpServletRequest.getParameter("token");
+        }
+        // update-end--Author:lvdandan Date:20210105 for:JT-355 OA聊天添加token验证,获取token参数
+
+        JwtToken jwtToken = new JwtToken(token);
+        // 提交给realm进行登入,如果错误他会抛出异常并被捕获
+        getSubject(request, response).login(jwtToken);
+        // 如果没有抛出异常则代表登入成功,返回true
+        return true;
+    }
+
+    /**
+     * 对跨域提供支持
+     */
+    @Override
+    protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
+        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
+        if(allowOrigin){
+            httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin"));
+            httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");
+            httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers"));
+            //update-begin-author:scott date:20200907 for:issues/I1TAAP 前后端分离,shiro过滤器配置引起的跨域问题
+            // 是否允许发送Cookie,默认Cookie不包括在CORS请求之中。设为true时,表示服务器允许Cookie包含在请求中。
+            httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
+            //update-end-author:scott date:20200907 for:issues/I1TAAP 前后端分离,shiro过滤器配置引起的跨域问题
+        }
+        // 跨域时会首先发送一个option请求,这里我们给option请求直接返回正常状态
+        if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
+            httpServletResponse.setStatus(HttpStatus.OK.value());
+            return false;
+        }
+        //update-begin-author:taoyan date:20200708 for:多租户用到
+//        String tenant_id = httpServletRequest.getHeader(CommonConstant.TENANT_ID);
+//        TenantContext.setTenant(tenant_id);
+        //update-end-author:taoyan date:20200708 for:多租户用到
+        return super.preHandle(request, response);
+    }
+
+    /**
+     * 封装异常信息
+     */
+    private void exceptionMsg(Exception e, ServletResponse response) {
+        // 认证出现异常,传递错误信息msg
+        String msg = e.getMessage();
+        // 获取应用异常(该Cause是导致抛出此throwable(异常)的throwable(异常))
+        Throwable throwable = e.getCause();
+        JSONObject jsonObject = new JSONObject();
+        if (throwable instanceof JwtAuthenticationException) {
+            jsonObject.put("code", ((JwtAuthenticationException) throwable).getCode());
+            jsonObject.put("msg", ((JwtAuthenticationException) throwable).getMsg());
+        } else {
+            log.error(msg);
+            jsonObject.put("code", 5002);
+            jsonObject.put("msg", "token invalid");
+
+        }
+        jsonObject.put("timestamp", LocalDateTime.now());
+        // 直接返回Response信息
+        this.writeResponse(response, jsonObject);
+
+    }
+
+    /**
+     * 无需转发,直接返回Response信息
+     *
+     */
+    private void writeResponse(ServletResponse response, JSONObject msg) {
+        response.setCharacterEncoding("UTF-8");
+        response.setContentType("application/json; charset=utf-8");
+        ServletOutputStream outputStream = null;
+        try {
+            outputStream = response.getOutputStream();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        assert outputStream != null;
+        PrintWriter printWriter = new PrintWriter(outputStream, true);
+        printWriter.write(msg.toString());//直接将json输出到页面
+        printWriter.flush();
+        printWriter.close();
+
+    }
+}

+ 68 - 0
gis_admin/src/main/java/com/gis/admin/shiro/filters/ResourceCheckFilter.java

@@ -0,0 +1,68 @@
+package com.gis.admin.shiro.filters;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shiro.subject.Subject;
+import org.apache.shiro.web.filter.AccessControlFilter;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * @Author Scott
+ * @create 2019-02-01 15:56
+ * @desc 鉴权请求URL访问权限拦截器
+ */
+@Slf4j
+public class ResourceCheckFilter extends AccessControlFilter {
+
+    private String errorUrl;
+
+    public String getErrorUrl() {
+        return errorUrl;
+    }
+
+    public void setErrorUrl(String errorUrl) {
+        this.errorUrl = errorUrl;
+    }
+
+    /**
+     * 表示是否允许访问 ,如果允许访问返回true,否则false;
+     *
+     * @param servletRequest
+     * @param servletResponse
+     * @param o               表示写在拦截器中括号里面的字符串 mappedValue 就是 [urls] 配置中拦截器参数部分
+     * @return
+     * @throws Exception
+     */
+    @Override
+    protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o) throws Exception {
+        Subject subject = getSubject(servletRequest, servletResponse);
+        String url = getPathWithinApplication(servletRequest);
+        log.info("当前用户正在访问的 url => " + url);
+        return subject.isPermitted(url);
+    }
+
+    /**
+     * onAccessDenied:表示当访问拒绝时是否已经处理了; 如果返回 true 表示需要继续处理; 如果返回 false
+     * 表示该拦截器实例已经处理了,将直接返回即可。
+     *
+     * @param servletRequest
+     * @param servletResponse
+     * @return
+     * @throws Exception
+     */
+    @Override
+    protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
+        log.info("当 isAccessAllowed 返回 false 的时候,才会执行 method onAccessDenied ");
+
+        HttpServletRequest request = (HttpServletRequest) servletRequest;
+        HttpServletResponse response = (HttpServletResponse) servletResponse;
+        response.sendRedirect(request.getContextPath() + this.errorUrl);
+
+        // 返回 false 表示已经处理,例如页面跳转啥的,表示不在走以下的拦截器了(如果还有配置的话)
+        return false;
+    }
+
+}

+ 0 - 9
gis_cms/src/main/java/com/gis/cms/controller/WebController.java

@@ -157,13 +157,6 @@ public class WebController {
     }
 
 
-//    @WebControllerLog(description = "门户网站-拜祭访问量")
-//    @ApiOperation("拜祭访问量")
-//    @GetMapping("mourn/visit/{id}")
-//    public Result mournVisit(@PathVariable Long id){
-//        mournService.addVisit(id);
-//        return Result.success();
-//    }
 
     @WebControllerLog(description = "门户网站-悼念烈士留言")
     @ApiOperation("门户网站-悼念烈士留言")
@@ -231,9 +224,7 @@ public class WebController {
     public Result updatePwd(@Valid @RequestBody PasswordDto param) {
         // 密码加密了,需要解密
         String newPassword = Base64Converter.decodePassword(param.getNewPassword());
-//        String oldPassword = Base64Converter.decodePassword(param.getOldPassword());
         param.setNewPassword(newPassword);
-//        param.setOldPassword(oldPassword);
 
         return sysUserService.updatePwdByWeb(param);
 

+ 0 - 11
gis_cms/src/main/java/com/gis/cms/controller/WebManageController.java

@@ -92,17 +92,6 @@ public class WebManageController {
         return questionGroupService.detail(id);
     }
 
-//    @ApiImplicitParams({
-//            @ApiImplicitParam(name = "questionGroupId", value = "题组id", required = true),
-//            @ApiImplicitParam(name = "answers", value = "Map传参, id:题组id, map, key:问题id, value:正确答案编号", required = true)
-//    })
-//    @WebControllerLog(description = "门户网站-提交答案", addDb = true)
-//    @ApiOperation(value = "门户网站-提交答案")
-//    @PostMapping("questionUser/submit/{questionGroupId}")
-//    public Result questionUserSubmit(@PathVariable Long questionGroupId, @RequestBody Map<String, String> answers) {
-//        return questionUserService.submit(questionGroupId, answers);
-//    }
-
 
     @WebControllerLog(description = "门户网站-提交答案", addDb = true)
     @ApiOperation(value = "门户网站-提交答案")

+ 18 - 0
gis_cms/src/main/java/com/gis/cms/service/impl/BarrageServiceImpl.java

@@ -4,10 +4,13 @@ import com.gis.cms.entity.dto.CommentDto;
 import com.gis.cms.entity.po.BarrageEntity;
 import com.gis.cms.entity.po.CommentEntity;
 import com.gis.cms.entity.vo.BarrageVo;
+import com.gis.cms.entity.vo.MournVo;
 import com.gis.cms.mapper.BarrageMapper;
+import com.gis.cms.service.SensitiveService;
 import com.gis.common.base.entity.dto.PageDateDto;
 import com.gis.common.base.mapper.IBaseMapper;
 import com.gis.common.base.service.impl.IBaseServiceImpl;
+import com.gis.common.util.MyStrUtil;
 import com.gis.common.util.Result;
 import com.gis.cms.service.BarrageService;
 import com.github.pagehelper.PageInfo;
@@ -16,6 +19,8 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Set;
 
 
 /**
@@ -27,6 +32,9 @@ public class BarrageServiceImpl extends IBaseServiceImpl<BarrageEntity, Long> im
     @Autowired
     private BarrageMapper entityMapper;
 
+    @Autowired
+    SensitiveService sensitiveService;
+
     @Override
     public IBaseMapper<BarrageEntity, Long> getBaseMapper() {
         return this.entityMapper;
@@ -37,6 +45,16 @@ public class BarrageServiceImpl extends IBaseServiceImpl<BarrageEntity, Long> im
     public Result<PageInfo<BarrageVo>> search(PageDateDto param, Integer display) {
         startPage(param);
         PageInfo<BarrageVo> page = new PageInfo<>(entityMapper.search(param, display));
+        List<BarrageVo> list = page.getList();
+        Set<Object> filterKey = sensitiveService.getFilterKey();
+        for (BarrageVo vo : list) {
+            String content = vo.getContent();
+            if (content != null){
+                vo.setContent(MyStrUtil.getFilterMsg(filterKey, content));
+            }
+        }
+
+
         return Result.success(page);
     }
 

+ 16 - 0
gis_cms/src/main/java/com/gis/cms/service/impl/MournServiceImpl.java

@@ -4,11 +4,13 @@ import com.gis.cms.entity.dto.MournDto;
 import com.gis.cms.entity.po.MournEntity;
 import com.gis.cms.entity.vo.MournVo;
 import com.gis.cms.mapper.MournMapper;
+import com.gis.cms.service.SensitiveService;
 import com.gis.common.base.exception.BaseRuntimeException;
 import com.gis.common.base.entity.dto.PageDateDto;
 import com.gis.common.base.mapper.IBaseMapper;
 import com.gis.common.base.service.impl.IBaseServiceImpl;
 import com.gis.common.constant.MsgCode;
+import com.gis.common.util.MyStrUtil;
 import com.gis.common.util.Result;
 import com.gis.cms.service.MournService;
 import com.github.pagehelper.PageInfo;
@@ -20,6 +22,7 @@ import tk.mybatis.mapper.entity.Condition;
 
 import java.time.LocalDateTime;
 import java.util.List;
+import java.util.Set;
 
 
 /**
@@ -32,6 +35,9 @@ public class MournServiceImpl extends IBaseServiceImpl<MournEntity, Long> implem
     private MournMapper entityMapper;
 
 
+    @Autowired
+    SensitiveService sensitiveService;
+
     @Override
     public IBaseMapper<MournEntity, Long> getBaseMapper() {
         return this.entityMapper;
@@ -61,6 +67,16 @@ public class MournServiceImpl extends IBaseServiceImpl<MournEntity, Long> implem
     @Override
     public Result mournComment(Long martyrId) {
        List<MournVo> list = entityMapper.findByMartyrIdMapper(martyrId);
+
+       // 处理敏感词
+        Set<Object> filterKey = sensitiveService.getFilterKey();
+        for (MournVo mournVo : list) {
+            String content = mournVo.getContent();
+            if (content != null){
+                mournVo.setContent(MyStrUtil.getFilterMsg(filterKey, content));
+            }
+        }
+
         return Result.success(list);
     }
 

+ 0 - 2
gis_cms/src/main/java/com/gis/cms/service/impl/SensitiveServiceImpl.java

@@ -109,13 +109,11 @@ public class SensitiveServiceImpl extends IBaseServiceImpl<SensitiveEntity, Long
     @Override
     public Set<Object> getFilterKey(){
         String redisFilterKey = getRedisFilterKey();
-//        Set<String> filterKey = (Set)redisUtil.get(redisFilterKeyKey);
         Set<Object> filterKey = redisUtil.getJsonSet(redisFilterKey);
         if (filterKey == null) {
             log.info("走数据库");
             filterKey = entityMapper.getName();
             // 86400s-> 24H
-//            redisUtil.set(redisFilterKeyKey, filterKey, 86400);
             redisUtil.setObjectToJson(redisFilterKey, filterKey, 86400);
         }
         log.info("走缓存");

+ 10 - 9
gis_cms/src/main/java/com/gis/cms/tree/CommentTreeUtil.java

@@ -2,6 +2,7 @@ package com.gis.cms.tree;
 
 import com.gis.cms.entity.vo.CommentVo;
 import com.gis.cms.tree.vo.CommentTree;
+import com.gis.common.util.MyStrUtil;
 import lombok.extern.slf4j.Slf4j;
 
 import java.util.ArrayList;
@@ -27,7 +28,7 @@ public class CommentTreeUtil {
             vo.setId(n.getId());
             vo.setContent(n.getContent());
             // 过滤敏感内容
-            vo.setContent(getFilterMsg(filterKey, n.getContent()));
+            vo.setContent(MyStrUtil.getFilterMsg(filterKey, n.getContent()));
 
 
             vo.setRealName(n.getRealName());
@@ -107,14 +108,14 @@ public class CommentTreeUtil {
      * @param content 过滤内容
      * @return
      */
-    private String getFilterMsg(Set<Object> filterKey, String content){
-        for (Object s : filterKey) {
-            if (s != null){
-                content =  content.replaceAll(s.toString(), "**");
-            }
-        }
-        return content;
-    }
+//    private String getFilterMsg(Set<Object> filterKey, String content){
+//        for (Object s : filterKey) {
+//            if (s != null){
+//                content =  content.replaceAll(s.toString(), "**");
+//            }
+//        }
+//        return content;
+//    }
 
 //    public List<CommentTree> buildTree(List<SysResourceEntity> all, List<SysResourceEntity> in) {
 //        for (SysResourceEntity n : all) {

+ 25 - 0
gis_common/src/main/java/com/gis/common/util/MyStrUtil.java

@@ -0,0 +1,25 @@
+package com.gis.common.util;
+
+import java.util.Set;
+
+/**
+ * Created by owen on 2021/10/18 0018 17:35
+ */
+public class MyStrUtil {
+
+
+    /**
+     * 过滤敏感内容
+     * @param filterKey 敏感词集合
+     * @param content 过滤内容
+     * @return
+     */
+    public static String getFilterMsg(Set<Object> filterKey, String content){
+        for (Object s : filterKey) {
+            if (s != null){
+                content =  content.replaceAll(s.toString(), "**");
+            }
+        }
+        return content;
+    }
+}