背景:针对越权测试,通过拦截工具Fiddler修改请求参数,越权查看平台里面所有公司的数据
1、自定义MyResponseBodyAdvice 实现ResponseBodyAdvice
使用过滤器和拦截我都试过,最终没有成功,可能技术比较菜,这种方式相当简单
逻辑:
1、获取请求路径path
2、获取当前登录人的公司id和userId,如果为空说明是登录、注册等相关接口,直接返回
3、redis中配置不需要拦截的接口(文件上传、导出等),获取配置,与当前接口路径相比较,如果包含说明不需要拦截
4、判断返回的json串中是否包含当前登录人的公司或者userId,如果包含,说明是有访问权限的,如果不包含,说明是恶意攻击,直接返回没有权限
package com.xiaoniu56.security.interceptor;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xiaoniu56.common.cache.redis.StringRedis;
import com.xiaoniu56.security.ApplicationNiuContext;
import com.xiaoniu56.service.common.CacheService;
import com.xiaoniu56.webservice.param.Constant;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import javax.annotation.Resource;
@ControllerAdvice
public class MyResponseBodyAdvice implements ResponseBodyAdvice<Object> {
@Autowired
private CacheService cacheService;
@Resource
private StringRedis<String, String> stringRedis;
@Autowired
private ObjectMapper objectMapper;
@Override
public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
return true;
}
@SneakyThrows
@Override
public Object beforeBodyWrite(Object body, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
// Object header= null;
// if (body != null) {
// JSONObject jsonObject = JSON.parseObject(body.toString());
// header = jsonObject.get("header");
// }
// if(1 == 1){
// Map map = new HashMap();
// Body bodyOne = new Body();
// bodyOne.setCode(RESULT_CODE.FAIL.getValue());
// bodyOne.setContent("抱歉,您没有访问权限");
// map.put("header", header);
// map.put("body", bodyOne);
// return map;
// }
//获取前端请求的路径
String path = serverHttpRequest.getURI().getPath();
if(ObjectUtil.isEmpty(body)){
return body;
}
//获取当前登录人的公司id
String currentUserCompanyId = ApplicationNiuContext.getCurrentUserCompanyId();
String userId = ApplicationNiuContext.getCurrentUserId();
if(ObjectUtil.isEmpty(currentUserCompanyId) || ObjectUtil.isEmpty(userId) ){
return body;
}
String dictJson = stringRedis.getV(Constant.DIC_CACHE);
String code = "";
JSONArray jsonArray = JSON.parseArray(dictJson);
for (Object obj : jsonArray) {
JSONObject jsonObject = (JSONObject) obj;
//这里根据type去获取code,code的长度为1024
Object type = jsonObject.get("type");
if(!Constant.filter_url_code.equals(type)){
continue;
}
code = jsonObject.get("code").toString();
}
if (code.contains(path)) {
return body;
}
String retrunJson = body.toString();
if(!retrunJson.contains(currentUserCompanyId) && !retrunJson.contains(userId)){
System.out.println("path--->"+ path);
throw new Exception("无访问权限,请检查重试");
}
return body;
}
}