系列文章目录
刚入门Java的硕士宝宝,实验室没什么Java项目,看到网上的秒杀项目,跟着学习并且记录一下,可能错误会很多,欢迎大家指正。
前言
本文介绍安全优化模块,具体详细介绍隐藏接口地址、验证码、接口限流。
一、秒杀接口地址隐藏
思路:秒杀开始之前,先去请求接口获取秒杀地址
- 获取秒杀地址:
@RequestMapping(value = "/path", method = RequestMethod.GET)
@ResponseBody
public RespBean getPath(User user, Long goodsId) {
if (user == null) {
return RespBean.error(RespBeanEnum.SESSION_ERROR);
}
String str = orderService.createPath(user,goodsId);
return RespBean.success(str);
- 生成秒杀地址:
@Override
public String createPath(User user, Long goodsId) {
String str = MD5Util.md5(UUIDUtil.uuid() + "123456");
redisTemplate.opsForValue().set("seckillPath:" + user.getId() + ":" + goodsId, str, 60, TimeUnit.SECONDS);
return str;
}
- 验证请求地址:
@Override
public boolean checkPath(User user, Long goodsId, String path) {
if (user==null|| StringUtils.isEmpty(path)){
return false;
}
String redisPath = (String) redisTemplate.opsForValue().get("seckillPath:" + user.getId() + ":" + goodsId);
return path.equals(redisPath);
}
二、图形验证码
思路:点击秒杀开始前,先输入验证码,分散用户的请求
- 生成验证码
@RequestMapping(value = "/captcha", method = RequestMethod.GET)
public void verifyCode(User user, Long goodsId, HttpServletResponse response) {
if (null==user||goodsId<0){
throw new GlobalException(RespBeanEnum.REQUEST_ILLEGAL);
}
// 设置请求头为输出图片类型
response.setContentType("image/jpg");
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
//生成验证码,将结果放入redis
ArithmeticCaptcha captcha = new ArithmeticCaptcha(130, 32, 3);
redisTemplate.opsForValue().set("captcha:"+user.getId()+":"+goodsId,captcha.text
(),300, TimeUnit.SECONDS);
try {
captcha.out(response.getOutputStream());
} catch (IOException e) {
log.error("验证码生成失败",e.getMessage());
}
}
- 验证验证码
@Override
public boolean checkCaptcha(User user, Long goodsId, String captcha) {
if (StringUtils.isEmpty(captcha)||null==user||goodsId<0){
return false;
}
String redisCaptcha = (String) redisTemplate.opsForValue().get("captcha:" + user.getId() + ":" + goodsId);
return redisCaptcha.equals(captcha);
}
三、接口限流
- 简单接口限流
@RequestMapping(value = "/path", method = RequestMethod.GET)
@ResponseBody
public RespBean getPath(User user, Long goodsId, String captcha,
HttpServletRequest request) {
if (user == null) {
return RespBean.error(RespBeanEnum.SESSION_ERROR);
}
ValueOperations valueOperations = redisTemplate.opsForValue();
//限制访问次数,5秒内访问5次
String uri = request.getRequestURI();
//方便测试
captcha = "0";
Integer count = (Integer) valueOperations.get(uri + ":" + user.getId());
if (count==null){
valueOperations.set(uri + ":" + user.getId(),1,5,TimeUnit.SECONDS);
}else if (count<5){
valueOperations.increment(uri + ":" + user.getId());
}else {
return RespBean.error(RespBeanEnum.ACCESS_LIMIT_REACHED);
}
boolean check = orderService.checkCaptcha(user, goodsId, captcha);
if (!check){
return RespBean.error(RespBeanEnum.ERROR_CAPTCHA);
}
String str = orderService.createPath(user, goodsId);
return RespBean.success(str);
}
- 通用接口限流
@AccessLimit(second = 5, maxCount = 5, needLogin = true)
@RequestMapping(value = "/path", method = RequestMethod.GET)
@ResponseBody
public RespBean getPath(User user, Long goodsId, String captcha,
HttpServletRequest request) {
if (user == null) {
return RespBean.error(RespBeanEnum.SESSION_ERROR);
}
//方便测试
captcha = "0";
boolean check = orderService.checkCaptcha(user, goodsId, captcha);
if (!check) {
return RespBean.error(RespBeanEnum.ERROR_CAPTCHA);
}
String str = orderService.createPath(user, goodsId);
return RespBean.success(str);
}
总结
以上就是今天要讲的内容,本文简单介绍了安全优化模块,具体参考 乐字节 Java电商秒杀项目。