七、测试验证
获取token
的控制器TokenController
package com.wangzaiplus.test.controller; import com.wangzaiplus.test.common.ServerResponse; import com.wangzaiplus.test.service.TokenService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/token") publicclass TokenController { @Autowired private TokenService tokenService; @GetMapping public ServerResponse token() { return tokenService.createToken(); } }
TestController
, 注意@ApiIdempotent
注解, 在需要幂等性校验的方法上声明此注解即可, 不需要校验的无影响
package com.wangzaiplus.test.controller; import com.wangzaiplus.test.annotation.ApiIdempotent; import com.wangzaiplus.test.common.ServerResponse; import com.wangzaiplus.test.service.TestService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/test") @Slf4j publicclass TestController { @Autowired private TestService testService; @ApiIdempotent @PostMapping("testIdempotence") public ServerResponse testIdempotence() { return testService.testIdempotence(); } }
获取token
查看redis
测试接口安全性: 利用jmeter测试工具模拟50个并发请求, 将上一步获取到的token作为参数
header或参数均不传token, 或者token值为空, 或者token值乱填, 均无法通过校验, 如token值为"abcd"
八、注意点(非常重要)
上图中, 不能单纯的直接删除token而不校验是否删除成功, 会出现并发安全性问题, 因为, 有可能多个线程同时走到第46行, 此时token还未被删除, 所以继续往下执行, 如果不校验jedisUtil.del(token)
的删除结果而直接放行, 那么还是会出现重复提交问题, 即使实际上只有一次真正的删除操作, 下面重现一下
稍微修改一下代码:
再次请求
再看看控制台
虽然只有一个真正删除掉token, 但由于没有对删除结果进行校验, 所以还是有并发问题, 因此, 必须校验
九、总结
其实思路很简单, 就是每次请求保证唯一性, 从而保证幂等性, 通过拦截器+注解, 就不用每次请求都写重复代码, 其实也可以利用spring aop实现。