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

462 lines
18 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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();
}
}