IntelligentRecognition/ah-jjsp-service/.svn/pristine/12/124141101209595f5682c5a57dc...

462 lines
18 KiB
Plaintext
Raw Normal View History

2024-05-24 16:09:40 +08:00
package com.securityControl.common.security.interceptor;
import com.alibaba.fastjson2.JSON;
import com.github.pagehelper.util.StringUtil;
import com.securityControl.common.core.constant.SecurityConstants;
import com.securityControl.common.core.context.SecurityContextHolder;
import com.securityControl.common.core.utils.JwtUtils;
import com.securityControl.common.core.utils.ServletUtils;
import com.securityControl.common.core.utils.StringUtils;
import com.securityControl.common.core.utils.aes.DateTimeHelper;
import com.securityControl.common.core.utils.ip.IpUtils;
import com.securityControl.common.core.web.domain.AjaxResult;
import com.securityControl.common.security.enums.UrlEnums;
import com.securityControl.common.security.utils.SafeUtil;
import com.securityControl.common.security.utils.Sm3Utils;
import com.securityControl.common.security.utils.XssRequestWrapper;
import com.securityControl.system.api.RemoteLogService;
import com.securityControl.system.api.domain.SysOperLog;
import com.sgcc.isc.framework.common.constant.Constants;
import com.sgcc.isc.service.adapter.factory.AdapterFactory;
import com.sgcc.isc.service.adapter.helper.IResourceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
import org.springframework.web.servlet.AsyncHandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
/**
* @author bonus
* @data 2023/2/6 17:22
* @description 安全参数验证
*/
@Slf4j
public class ParamSecureHandler implements AsyncHandlerInterceptor {
@Autowired
private final PathMatcher pathMatcher = new AntPathMatcher();
//@Autow
private String rnd = null;
private String whiteURL ="http://10.145.34.32:21001/";
@Autowired
private RemoteLogService remoteLogService;
private static Map<String, List<Double>> requestLogMap = null;
IResourceService resourceService = (IResourceService) AdapterFactory.getInstance(Constants.CLASS_RESOURCE);
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("进入了拦截器");
System.err.println(request.getRequestURI());
if(Objects.equals("/pot/superStatistics/importExcel",request.getRequestURI()) ||
Objects.equals("/pot/todayTask/uploadNoticeVio",request.getRequestURI()) ||
Objects.equals("/pot/superStatistics/editUploadNoticeVio",request.getRequestURI()) ||
Objects.equals("/pot/todayTask/uploadExceptionReport",request.getRequestURI()) ||
Objects.equals("/pot/todayTask/uploadExceptionReport",request.getRequestURI()) ||
Objects.equals("/pot/superStatistics/uploadNoticeVioRect",request.getRequestURI()) ||
Objects.equals("/pot/device/importExcel",request.getRequestURI()) ||
Objects.equals("/pot/TRiskPressDropRate/importExcel",request.getRequestURI()) ||
Objects.equals("pot/early/exportToExcel",request.getRequestURI()) ||
Objects.equals("/sys/dict/getDictList",request.getRequestURI()) ||
Objects.equals( "/api/ballrisk/findBallUpDown",request.getRequestURI()) ||
Objects.equals("/api/ballrisk/findBallGb",request.getRequestURI()) || //外部接口的过滤
Objects.equals("/api/ballrisk/findDeviceStatus",request.getRequestURI()) || //外部接口的过滤
Objects.equals("/api/ballrisk/getDeviceState",request.getRequestURI()) || //外部接口的过滤
Objects.equals("/sys/menu/getAllMenuList",request.getRequestURI()) || //外部接口的过滤
request.getRequestURI().contains("/userManage/info/") || //外部接口的过滤
Objects.equals("/sys/menu/getMenuList",request.getRequestURI())){ // 过滤文件上传功能和菜单管理
return true;
}
if(StringUtils.isNotBlank(request.getRequestURI())){
if(request.getRequestURI().contains("/files/")){
return true;
}
}
XssRequestWrapper requestWrapper = new XssRequestWrapper(request);
String requestUrl = requestWrapper.getRequestURI();
/*if (StringUtil.isEmpty(requestUrl.trim())) {
return false;
}*/
/**
* 防止refer篡改
*/
String referUrl= request.getHeader("Referer");
if(!whiteURL.equals(referUrl)){
returnJson(response,"请求来源不正确!",500);
return false;
}
/**
* 白名单中不验证参数
*/
/* boolean doFilter = isWhiteURL(requestUrl);
if (doFilter) {
return true;
}*/
if (!requestWrapper.isChecked()) {
log.error("输入值非法{}", requestWrapper.getQueryString());
returnJson(response,"输入值非法!",500);
return false;
}
System.err.println(JSON.toJSONString(request.getParameterMap()));
/**
* 跨站点攻击
*/
/* boolean checkXss = checkXss(request, requestUrl);
if (!checkXss) {
//resultError(HttpConstants.HTTP_RES_CODE_400.getKey(), ctx, "请求非法!");
throw new BindException(null, "请求非法!");
return false;
}*/
/**
* 获取所有跳转路径参数,保留传入下个界面
*/
Map<String, String[]> map = requestWrapper.getParameterMap();
boolean checkParameterMap = checkParameterMap(map, requestUrl);
if (!checkParameterMap) {
//resultError(HttpConstants.HTTP_RES_CODE_400.getKey(), ctx, "输入值非法!");
// throw new ServiceException("输入值非法!",500);
returnJson(response,"输入值非法",500);
return false;
}
/**
* 同地址请求验证
*/
String ckval = request.getHeader("ckval");
String currentRequest = request.getRemoteAddr() + ":" + requestUrl + "?ckval=" + ckval;
/* boolean checkSameUrl = checkSameUrl(currentRequest, requestWrapper);
if (!checkSameUrl) {
log.info("{}请求重复,{}", currentRequest, rnd);
//resultError(HttpConstants.HTTP_RES_CODE_400.getKey(), ctx, "请求重复!");
throw new ServiceException("请求重复!");
}*/
/**
* 检查数据流参数
*/
String readerParam = requestWrapper.getReaderParam();
if (requestUrl.indexOf("uploadFile") < 0 && requestUrl.indexOf("uploadImage") < 0) {// 判断是否是文件上传,是不对流参数进行验证
boolean checkReader = checkReader(readerParam, requestUrl);
if (!checkReader) {
//resultError(HttpConstants.HTTP_RES_CODE_400.getKey(), ctx, "输入值非法!");
// throw new GlobalException("请求重复!");
returnJson(response,"请求重复",500);
return false;
}
}
if (!sm3Check(request)) {
// throw new GlobalException("请求参数丢失!");
returnJson(response,"请求参数丢失",500);
return false;
}
/*if(!checkIsYq(request,requestWrapper)){
// throw new ServiceException("请求越权,请检查用户权限!");
returnJson(response,"请求越权,请检查用户权限",500);
return false;
}*/
return true;
}
private void returnJson(HttpServletResponse response,String msg,int code){
PrintWriter writer=null;
response.setCharacterEncoding("UTF-8");
response.setContentType("applicatiopn/json;charset=utf-8");
AjaxResult a=AjaxResult.error(code,msg);
String res=JSON.toJSONString(a);
try {
writer=response.getWriter();
writer.println(res);
}catch (IOException e){
e.printStackTrace();
}
}
/**
* 判断是否越权
*/
private boolean checkIsYq(HttpServletRequest request,XssRequestWrapper requestWrapper) throws Exception {
String requestURI = request.getRequestURI();
String[] headUrls = requestURI.split("/");
String url = "/" + headUrls[1]+"/" + headUrls[2] + "/**";
Boolean result = true;
String token = requestWrapper.getParameter("token");
if (StringUtils.isNotEmpty(token)) {
String userId = JwtUtils.getIscUserId(token);
System.out.println("拦截器userId:" + userId);
if (StringUtil.isEmpty(userId)) {
result = false;
} else {
result = resourceService.hasPermitURLObj(userId, "9b4483c383538275018615493e1451ea", url);
}
System.out.println("==================越狱记录:========================userId:" + userId + "============是否越狱:" + result);
} else {
result = false;
}
if (!result) {
//记录日志 鹏飞
addExceedsAccessLog(url, token);
return false;
//添加弹框
}
return true;
}
private void addExceedsAccessLog(String url, String token) {
SysOperLog sysOperLog = new SysOperLog();
sysOperLog.setGrade("越权访问");
sysOperLog.setOperName(JwtUtils.getUserName(token));
sysOperLog.setTimes(DateTimeHelper.getNowTime());
sysOperLog.setRoleName("继远管理员");
sysOperLog.setDeptName("建设分公司");
sysOperLog.setOperIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
UrlEnums[] enums = UrlEnums.values();
for (UrlEnums anEnum : enums) {
if (url.startsWith(anEnum.getUrl())) {
sysOperLog.setTitle(anEnum.getInfo());
}
}
if (StringUtils.isEmpty(sysOperLog.getTitle())) {
sysOperLog.setTitle("系统管理");
}
sysOperLog.setRequestMethod("");
sysOperLog.setMethod("");
sysOperLog.setBusinessType(1);
sysOperLog.setOperUrl("");
sysOperLog.setOperParam("");
sysOperLog.setDetail("用户越权访问地址:" + url);
sysOperLog.setLogType("系统日志");
sysOperLog.setSysMenu("");
sysOperLog.setStatus(1);
remoteLogService.saveLogs(sysOperLog, SecurityConstants.INNER);
}
/**
* 简单的xss跨站点检查
*
* @param request
* @param requestUrl
* @return
*/
/*private boolean checkXss(HttpServletRequest request, String requestUrl) {
String host = request.getHeader("Host");
String localAddr = foundationConfig.getRequestUrl().getLocalAddr();//request.getLocalAddr();
String remoteHost = foundationConfig.getRequestUrl().getRemoteHost();//request.getRemoteHost();
String referer = request.getHeader("Referer");
log.debug("获取到host:{},localAddr:{},remoteHost:{},referer:{}", host, localAddr, remoteHost, referer);
if (StringUtil.isEmpty(host) || StringUtil.isEmpty(localAddr)
|| StringUtil.isEmpty(remoteHost) || StringUtil.isEmpty(referer)) {
return false;
}
// 如果请求地址为空则直接返回false
if (requestUrl == null) {
log.info("当前请求地址不存在");
return false;
}
String localAddr2 = request.getLocalAddr();
String remoteHost2 = request.getRemoteHost();
if (referer.indexOf(remoteHost) == -1 && referer.indexOf(remoteHost2) == -1) {
return false;
}
if (host.indexOf(localAddr) == -1 && host.indexOf(localAddr2) == -1) {
return false;
}
// 逻辑: 判断SERVICE_TYPES数组中 所有元素 是否有一个能够通过验证
// 循环SERVICE_TYPES
// 判断当前变量是否存在于referer判断当前变量在不存在于referer是否存在于requestUrl
// 存在则返回true,结束循环
// 不存在返回false提示当前来源不是本站请求
for (String headerURL : foundationConfig.getHeaderUrls()) {
if (referer.indexOf(headerURL) != -1 || requestUrl.indexOf(headerURL) != -1) {
return true;
}
}
log.info("当前请求来源不是本站请求!请求地址:" + requestUrl + ".请检查请求的URL是否正确!");
return false;
}*/
/* */
/**
* 判断白名单
*
* @param currentURL
* @return
*/
private boolean isWhiteURL(String currentURL) {
// for (String whiteURL : foundationConfig.getWhiteUrls()) {
if (pathMatcher.match(whiteURL, currentURL)) {
log.info("白名单过滤: [{}] 匹配 [{}] ", whiteURL, currentURL);
return true;
}
log.info("白名单过滤: [{}] 未匹配 [{}]", whiteURL, currentURL);
// }
return false;
}
/**
* 参数校验
*
* @param request
* @return
*/
private boolean sm3Check(HttpServletRequest request) {
Map<String, String> map = new LinkedHashMap<>();
request.getParameterMap().forEach((key, value) -> {
if (!Objects.equals(key, "token") ) {
map.put(key, String.join(" ", value));
}
});
String header = request.getHeader("encrypt");
String json = JSON.toJSONString(map);
request.getParameterMap();
String str = Sm3Utils.encrypt(json);
return str.equalsIgnoreCase(header);
}
/**
* 检查所有页面输入的参数是否安全 request.getParameterMap()
*
* @param map
* @param requestUrl
*/
private boolean checkParameterMap(Map<String, String[]> map, String requestUrl) {
rnd = null;
if (map != null && map.size() > 0) {
Iterator<Map.Entry<String, String[]>> iterator = map.entrySet().iterator();
String value = "";// 参数值
while (iterator.hasNext()) {
value = "";
Map.Entry<String, String[]> entry = iterator.next();
String pname = (String) entry.getKey(); // 参数名
if (Objects.equals("token", pname)) {
continue;
}
Object objValue = entry.getValue(); // 数组
if (null == objValue) {
value = "";
} else if (objValue instanceof String[]) {
String[] values = (String[]) objValue;
for (int i = 0; i < values.length; i++) {
value = values[i] + ",";
}
if (value.length() > 0) {
value = value.substring(0, value.length() - 1);
}
}
if ("rnd".equals(pname)) {
rnd = value;
}
if (SafeUtil.checkSafeSql(value)) {
log.info("请求失败,当前请求参数不安全!请求地址:\n" + requestUrl + "\n不安全参数" + pname + ":" + value);
return false;
}
if (SafeUtil.checkSpecial(value)) {
log.info("请求失败,当前请求参数包含特殊字符!请求地址:\n" + requestUrl + "\n特殊字符参数" + pname + ":" + value);
return false;
}
}
}
return true;
}
/**
* 通过rnd随机参数判断相同url是否多次请求访问
*
* @param currentRequest
* @param requestWrapper
* @return
*/
private boolean checkSameUrl(String currentRequest, XssRequestWrapper requestWrapper) {
if (rnd != null && rnd.length() > 0) {
try {
double newRnd = Double.parseDouble(rnd);
/**
* 当为空时,新增请求时间记录,第一次请求,放行,允许查询
*/
HttpSession session = requestWrapper.getSession();
Object obj = session.getAttribute("requestLogMap");
if (obj == null) {
requestLogMap = new HashMap<String, List<Double>>(16);
} else {
requestLogMap = (Map<String, List<Double>>) obj;
}
List<Double> list = requestLogMap.get(currentRequest);
if (list == null) {
list = new ArrayList<Double>();
} else {
for (Double oldRnd : list) {
if (oldRnd == newRnd) {
log.info("请求失败,当前请求已过期!请重新登录!您的请求地址:\n" + currentRequest);
return false;
}
}
}
list.add(newRnd);
requestLogMap.put(currentRequest, list);
if (session.getAttribute("requestLogMap") != null) {
session.removeAttribute("requestLogMap");
}
session.setAttribute("requestLogMap", requestLogMap);
} catch (NumberFormatException e) {
log.info("rnd参数格式化错误 请检查");
return false;
}
} else {
log.info("请求失败,rnd参数不存在!请重新登录!您的请求地址:\n" + currentRequest);
return true;
}
return true;
}
/**
* 检查所有页面输入的参数是否安全 request.getReader()
*
* @param readerParam
* @param requestUrl
*/
private boolean checkReader(String readerParam, String requestUrl) {
if (SafeUtil.checkScript(readerParam)) {
log.info("请求失败,当前请求参数不安全!请求地址:\n" + requestUrl + "\n不安全参数数据流:" + readerParam);
return false;
}
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
SecurityContextHolder.remove();
}
}