遇到问题: 测试人员用burpsuite工具抓取表单数据,当页面点击提交数据后,工具burpsuite将截取到的数据修改后模拟发送,依然可以正常修改,解决办法 项目添加token验证,
第一步:先写token生成和销毁方法
package com.smartt.api.interceptor; import java.lang.annotation.*; @Target(ElementType.METHOD) @Retention (RetentionPolicy.RUNTIME) @Documented public @interface Token { boolean save() default false; boolean remove() default false; }
TokenInterceptor.java
package com.smartt.api.interceptor; import java.lang.reflect.Method; import java.util.UUID; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; public class TokenInterceptor extends HandlerInterceptorAdapter { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (handler instanceof HandlerMethod) { HandlerMethod handlerMethod = (HandlerMethod) handler; Method method = handlerMethod.getMethod(); Token annotation = method.getAnnotation(Token.class); if (annotation != null) { boolean needSaveSession = annotation.save(); if (needSaveSession) { request.getSession(false).setAttribute("token", UUID.randomUUID().toString()); } boolean needRemoveSession = annotation.remove(); if (needRemoveSession) { if (isRepeatSubmit(request)) { return false; } request.getSession(false).removeAttribute("token"); } } return true; } else { return super.preHandle(request, response, handler); } } private boolean isRepeatSubmit(HttpServletRequest request) { String serverToken = (String) request.getSession(false).getAttribute("token"); if (serverToken == null) { return true; } String clinetToken = request.getParameter("token"); if (clinetToken == null) { return true; } if (!serverToken.equals(clinetToken)) { return true; } return false; } }
第二步:写springboot的拦截器,拦截对应的访问方法地址,进行token验证
package com.smartt.api; import org.springframework.boot.SpringApplication; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import com.smartt.api.interceptor.TokenInterceptor; @Configuration @ComponentScan(useDefaultFilters = true) public class WebAppConfig extends WebMvcConfigurerAdapter { public static void main(String[] args) { SpringApplication.run(WebAppConfig.class, args); } /** * 配置拦截器 * @author lance * @param registry */ public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new TokenInterceptor()).addPathPatterns("/admin/**"); } }
我写的是 /admin/ 对应的controller访问路径的,如果多个不同的访问地址可以这么写 /** 或
如果写了多个又不想全部都拦截可以这么写
多个拦截器组成一个拦截器链 // addPathPatterns 用于添加拦截规则 // excludePathPatterns 用户排除拦截 registry.addInterceptor(new MyInterceptor1()).addPathPatterns("/xxx1/**"); registry.addInterceptor(new MyInterceptor2()).addPathPatterns("/xxx2/**");
- 接下来就是关键,在进入到你需要提交的页面的controller方法上使用你的自定义注解
- 在提交数据的controller方法上删除
- 最后一个步骤,首先需要再页面获取到session中的token并放入隐藏域中,最后如果你是ajax提交的数据,记得一定要把token当做参数提交上去,否则后台无法获取到你页面提交的token值,就无法和session中的作比较