AOP日志组件 多次获取post参数
来源:互联网 发布:淘宝店铺怎么增加分类 编辑:程序博客网 时间:2024/06/06 03:28
AOP日志组件 多次获取post参数
- 需求:新增接口日志组件。通过拦截器对接口URL进行拦截处理,然后将接口post请求的参数与结果,写入日志表。
- 问题:POST方法的参数是存储在request.getInputStream中,只能读一次,不能多次读取。从中读取post请求参数,只能读取一次。在filter中获取之后,controller无法获取post请求参数。
- 解决办法:继承HttpServletRequest,先获取到请求参数,再加参数重新set到inputStream。
1.拦截器记录日志
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequest)request; String requestPath = httpRequest.getServletPath().split("\\?")[0]; if(request == null){ chain.doFilter(request, response); return ; } for (String noFilter : NO_FILETER_LIST) { if(requestPath.toLowerCase().contains(noFilter)){ chain.doFilter(request, response); return ; } } Pattern pattern = Pattern.compile(".*[api|interface].*"); Matcher matcher = pattern.matcher(requestPath); if(matcher.matches()){ LoggerManager loggerManager = SpringLoadListener.getBean("loggerManager",LoggerManager.class); //扩展request,防止字符注入等 XssSqlHttpServletRequestWrapper xssRequest = new XssSqlHttpServletRequestWrapper((HttpServletRequest)request); ResponseWrapper wrapResponse = new ResponseWrapper((HttpServletResponse)response); //继续请求处理类 chain.doFilter(xssRequest, wrapResponse); //获取URL的参数 get请求 Map<Object, Object> urlParam = xssRequest.getParameterMap(); //获取post参数 String param = xssRequest.getRequestParams(); JSONObject jObject = JSONObject.fromObject(urlParam); jObject.put("postParam", param.toString()); String params = jObject.toString(); //获取接口处理类返回结果 byte[] data = wrapResponse.getResponseData(); String result = new String(data,"UTF-8"); //保存日志 loggerManager.operateInterfaceLogger("", params, requestPath, result); ServletOutputStream out = response.getOutputStream(); out.write(data); out.flush(); }else{ chain.doFilter(request, response); } }
2.处理request请求,先获取inputStream,将请求参数复制给其他方法,同时再将获取的inputStream赋值回request中。
public class XssSqlHttpServletRequestWrapper extends HttpServletRequestWrapper { HttpServletRequest orgRequest = null; private byte[] bytes; private WrappedServletInputStream wrappedServletInputStream; public XssSqlHttpServletRequestWrapper(HttpServletRequest request) throws IOException { super(request); this.orgRequest = request; //读取输入流的请求参数,保存到bytes中 bytes = IOUtils.toByteArray(request.getInputStream()); ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes); this.wrappedServletInputStream = new WrappedServletInputStream(byteArrayInputStream); //把post参数重新写入请求流 reWriteInputStream(); } /** * 把参数重新写进请求里 */ public void reWriteInputStream() { wrappedServletInputStream.setStream(new ByteArrayInputStream(bytes != null ? bytes : new byte[0])); } @Override public ServletInputStream getInputStream() throws IOException { return wrappedServletInputStream; } @Override public BufferedReader getReader() throws IOException { return new BufferedReader(new InputStreamReader(wrappedServletInputStream)); } /** * 获取post参数 */ public String getRequestParams() throws IOException { return new String(bytes, this.getCharacterEncoding()); } //清洗参数,防止xss注入 public String[] getParameterValues(String parameter) { String[] values = super.getParameterValues(parameter); if (values == null) { return null; } int count = values.length; String[] encodedValues = new String[count]; for (int i = 0; i < count; i++) { encodedValues[i] = xssEncode(values[i]); } return encodedValues; } public String getParameter(String name) { String value = super.getParameter(xssEncode(name)); if (value != null) { value = xssEncode(value); } return value; } public String getHeader(String name) { String value = super.getHeader(xssEncode(name)); if (value != null) { value = xssEncode(value); } return value; } private static String xssEncode(String s) { return StringUtil.xssEncode(s); } public HttpServletRequest getOrgRequest() { return this.orgRequest; } public static HttpServletRequest getOrgRequest(HttpServletRequest req) { if ((req instanceof XssSqlHttpServletRequestWrapper)) { return ((XssSqlHttpServletRequestWrapper)req).getOrgRequest(); } return req; } private class WrappedServletInputStream extends ServletInputStream { public void setStream(InputStream stream) { this.stream = stream; } private InputStream stream; public WrappedServletInputStream(InputStream stream) { this.stream = stream; } public int read() throws IOException { return stream.read(); } public boolean isFinished() { return true; } public boolean isReady() { return true; } public void setReadListener(ReadListener readListener) { } } }
3.Manager保存日志记录。对LoggerAnnotation自定义注解,实现AOP日志保存。
@LoggerAnnotation(type="INTERFACE", name="#name", params="#params", desc="#pageLink")public String operateInterfaceLogger(String name, String params, String pageLink, String result){ return result;} @Component @Aspect @Async public class LoggerOperationAop { private static final Logger logger = LoggerFactory.getLogger(LoggerOperationAop.class); @Autowired private LoggerManager loggerManager; @Autowired private UserManager userManager; @Autowired private JdbcTemplateImpl jdbcTemplate; public LoggerOperationAop() {} @Pointcut("@annotation(LoggerAnnotation)") private void serviceAspect(LoggerAnnotation LoggerAnnotation) {} @Around("serviceAspect(LoggerAnnotation)") public Object process(ProceedingJoinPoint point, LoggerAnnotation LoggerAnnotation) throws Throwable { String targetName = point.getTarget().getClass().getName(); String methodName = point.getSignature().getName(); Object[] arguments = point.getArgs(); String operationType = LoggerAnnotation.type(); String message = LoggerAnnotation.desc(); String params = LoggerAnnotation.params(); String name = LoggerAnnotation.name(); String id = LoggerAnnotation.id(); String[] paramNames = ReflectParamNames.getNames(targetName, methodName); if ((StringUtil.isNotBlank(name)) && (name.startsWith("#"))) { String value = SpelParser.getKey(name, "", paramNames, arguments); if (StringUtil.isNotBlank(value)) { targetName = value; } } String methodParams = ""; if ((StringUtil.isNotBlank(params)) && (params.startsWith("#"))) { methodParams = SpelParser.getKey(params, "", paramNames, arguments); } if ((StringUtil.isNotBlank(message)) && (message.startsWith("#"))) { String value = SpelParser.getKey(message, "", paramNames, arguments); if (StringUtil.isNotBlank(value)) { message = value; } } String userId = null; String userName = "游客"; try { Subject currentSubject = SecurityUtils.getSubject(); if (currentSubject != null) { Object tmpObj = currentSubject.getSession().getAttribute("authorizeUser"); if ((tmpObj != null) && ("INTERFACE".equals(operationType))) { userName = StringUtil.parseAny2String(tmpObj); } else if (currentSubject.getPrincipal() != null) { ShiroDbRealm.ShiroUser shiroUser = (ShiroDbRealm.ShiroUser)currentSubject.getPrincipal(); userId = shiroUser.getUserId(); userName = shiroUser.getLoginName(); } } } catch (Exception e) { logger.info("不支持shiro技术框架"); logger.error("异常信息:{}", e.getMessage()); } Object target = point.proceed(); try { String extName = DateUtil.getYearMonth(new Date()); String sql = " INSERT INTO T_E4S_DB_LOG_MESSAGE_" + extName + " (USER_ID,USER_NAME,CLASS_NAME,METHOD_NAME,METHOD_PARAMS,LOG_DATE,LOG_MESSAGE,OPERATION_TYPE,REMARK) " + " VALUES(?,?,?,?,?,?,?,?,?) "; Object[] object = { userId, userName, targetName, methodName, methodParams, new Date(), message, operationType, target }; this.jdbcTemplate.beginTranstaion(); this.jdbcTemplate.update(sql, object); this.jdbcTemplate.commit(); } catch (Exception ex) { logger.error("==异常通知异常=="); logger.error("异常信息:{}", ex.getMessage()); this.jdbcTemplate.rollback(); } return target; } }
LoggerFilter里一个实现了XssSqlHttpServletRequestWrapper类,其构造器自动读取了servletRequest里的输入流,并把数据保存了下来,最后又把数据重新写入servletRequest里,在filter中可以读取post请求参数,cotroller也可以再次从request里读取到post请求参数。
阅读全文
3 0
- AOP日志组件 多次获取post参数
- POST获取参数。【POST】
- 获取post参数
- 获取POST参数
- java 获取 post参数
- Spring Boot 之AOP 日志组件
- java获取get,post参数
- nginx日志记录post的参数
- spring Aop 配置文件方式+JoinPoint获取参数
- spring Aop 配置文件方式+JoinPoint获取参数
- spring AOP切面,注解实现,获取参数
- 使用AOP实现日志和权限认证组件
- 关于dedecm获取get/post 参数
- fcgi/cgi 参数获取 get与post
- http post方式获取json参数
- Spring MVC后台获取jQuery post参数
- get、post获取参数的区别
- 【httplistener监听获取Post请求参数】
- redis学习日志八(集合(set)的常用命令和集合间的常用命令)
- mybatis 缓存
- 计算机网络自顶向下webserver
- 剑指offer——链表的递归反转打印
- Java 关于进行文件加密
- AOP日志组件 多次获取post参数
- jquery请求数据长时间loading等待效果
- 文章标题
- 简单实现了下SSDT SHADOW HOOK
- springMVC—拦截器
- UITableViewCell自定义UIImageView点击cell UIImageView大小改变
- Intellij idea 对YML文件支持的解决方案
- java分享功能
- python模块大全