html5响应式网站建设,wordpress剑侠情缘主题,wordpress文字博客主题,大型网站建设优化企业文章目录背景Kaptcha 框架介绍添加Kaptcha依赖Kaptcha配置CommonUtil⼯具类接⼝开发JsonData响应⼯具类封装校验逻辑背景 注册-登录-修改密码⼀般需要发送验证码#xff0c;但是容易被攻击恶意调⽤ 什么是短信-邮箱轰炸机 ⼿机短信轰炸机是批、循环给⼿机⽆限发送各种⽹站的注…
文章目录背景Kaptcha 框架介绍添加Kaptcha依赖Kaptcha配置CommonUtil⼯具类接⼝开发JsonData响应⼯具类封装校验逻辑背景 注册-登录-修改密码⼀般需要发送验证码但是容易被攻击恶意调⽤ 什么是短信-邮箱轰炸机 ⼿机短信轰炸机是批、循环给⼿机⽆限发送各种⽹站的注册验证码短信的⽅法。 公司带来的损失 短信⼀条5分钱如果被⼤盗刷⼤家⾃⼰计算邮箱通知不⽤钱但被⼤盗刷带宽、接等都被占⽤导致⽆法正常使⽤ 如何避免⾃⼰的⽹站成为”⾁鸡“或者被刷呢 增加图形验证码(开发⼈员) 单IP请求次数限制(开发⼈员) 限制号码发送(⼀般短信提供商会做) 攻防永远是有的只过加⼤了攻击者的成本ROI划不过来⾃然就放弃了
Kaptcha 框架介绍 ⾕歌开源的⼀个可⾼度配置的实⽤验证码⽣成⼯具 验证码的字体/⼤⼩/颜⾊ 验证码内容的范围(数字字⺟中⽂汉字!) 验证码图⽚的⼤⼩边框边框粗细边框颜⾊ 验证码的⼲扰线 验证码的样式(⻥眼样式、3D、普通模糊) 添加Kaptcha依赖 !--kaptcha依赖包--dependencygroupIdcom.baomidou/groupIdartifactIdkaptcha-spring-boot-starter/artifactIdversion1.0.0/version/dependencyKaptcha配置
import com.google.code.kaptcha.Constants;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.Properties;Configuration
public class KaptchaConfig {/*** 验证码配置* Kaptcha配置类名** return*/BeanQualifier(kaptchaProducer)public DefaultKaptcha kaptcha() {DefaultKaptcha kaptcha new DefaultKaptcha();Properties properties new Properties();//验证码个数properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, 4);//字体间隔properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_SPACE,8);//干扰线颜色//干扰实现类properties.setProperty(Constants.KAPTCHA_NOISE_IMPL, com.google.code.kaptcha.impl.NoNoise);//图片样式properties.setProperty(Constants.KAPTCHA_OBSCURIFICATOR_IMPL, com.google.code.kaptcha.impl.WaterRipple);//文字来源properties.setProperty(Constants.KAPTCHA_TEXTPRODUCER_CHAR_STRING, 0123456789);Config config new Config(properties);kaptcha.setConfig(config);return kaptcha;}
}CommonUtil⼯具类
import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.MessageDigest;public class CommonUtil {/*** 获取ip* param request* return*/public static String getIpAddr(HttpServletRequest request) {String ipAddress null;try {ipAddress request.getHeader(x-forwarded-for);if (ipAddress null || ipAddress.length() 0 || unknown.equalsIgnoreCase(ipAddress)) {ipAddress request.getHeader(Proxy-Client-IP);}if (ipAddress null || ipAddress.length() 0 || unknown.equalsIgnoreCase(ipAddress)) {ipAddress request.getHeader(WL-Proxy-Client-IP);}if (ipAddress null || ipAddress.length() 0 || unknown.equalsIgnoreCase(ipAddress)) {ipAddress request.getRemoteAddr();if (ipAddress.equals(127.0.0.1)) {// 根据网卡取本机配置的IPInetAddress inet null;try {inet InetAddress.getLocalHost();} catch (UnknownHostException e) {e.printStackTrace();}ipAddress inet.getHostAddress();}}// 对于通过多个代理的情况第一个IP为客户端真实IP,多个IP按照,分割if (ipAddress ! null ipAddress.length() 15) {// ***.***.***.***.length()// 15if (ipAddress.indexOf(,) 0) {ipAddress ipAddress.substring(0, ipAddress.indexOf(,));}}} catch (Exception e) {ipAddress;}return ipAddress;}public static String MD5(String data) {try {java.security.MessageDigest md MessageDigest.getInstance(MD5);byte[] array md.digest(data.getBytes(UTF-8));StringBuilder sb new StringBuilder();for (byte item : array) {sb.append(Integer.toHexString((item 0xFF) | 0x100).substring(1, 3));}return sb.toString().toUpperCase();} catch (Exception exception) {}return null;}
}
接⼝开发
import com.google.code.kaptcha.Producer;
import net.xdclass.xdclassredis.util.CommonUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.util.concurrent.TimeUnit;RestController
RequestMapping(/api/v1/kaptcha)
public class KaptchaController {Autowiredprivate RedisTemplateString,Object redisTemplate;Autowiredprivate Producer kaptchaProducer;GetMapping(get_kaptcha)public void getKaptcha(HttpServletRequest request, HttpServletResponse response){String KaptchaText KaptchaProducer.createText();String key getKaptchaKey(request);//10分钟过期redisTemplate.opsForValue().set(key,kaptchaText,10,TimeUnit.MINUTES);BufferedImage bufferedImage kaptchaProducer.createImage(kaptchaText);ServletOutputStream outputStream null;try {outputStream response.getOutputStream();ImageIO.write(bufferedImage,jpg,outputStream);outputStream.flush();outputStream.close();}catch (Exception e){e.printStackTrace();}}private String getKaptchaKey(HttpServletRequest request){String ip CommonUtil.getIpAddr(request);String userAgent request.getHeader(User-Agent);String key user-service:kaptcha:CommonUtil.MD5(ipuserAgent);return key;}}
JsonData响应⼯具类封装
public class JsonData {/*** 状态码 0 表示成功*/private Integer code;/*** 数据*/private Object data;/*** 描述*/private String msg;public JsonData(int code,Object data,String msg){this.code code;this.msg msg;this.data data;}/*** 成功不传入数据* return*/public static JsonData buildSuccess() {return new JsonData(0, null, null);}/*** 成功传入数据* param data* return*/public static JsonData buildSuccess(Object data) {return new JsonData(0, data, null);}/*** 失败传入描述信息* param msg* return*/public static JsonData buildError(String msg) {return new JsonData(-1, null, msg);}public Integer getCode() {return code;}public void setCode(Integer code) {this.code code;}public Object getData() {return data;}public void setData(Object data) {this.data data;}public String getMsg() {return msg;}public void setMsg(String msg) {this.msg msg;}
}
校验逻辑
import com.google.code.kaptcha.Producer;
import net.xdclass.xdclassredis.util.CommonUtil;
import net.xdclass.xdclassredis.util.JsonData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.util.concurrent.TimeUnit;RestController
RequestMapping(/api/v1/kaptcha)
public class KaptchaController {Autowiredprivate RedisTemplateString,Object redisTemplate;Autowiredprivate Producer kaptchaProducer;GetMapping(get_kaptcha)public void getKaptcha(HttpServletRequest request, HttpServletResponse response){String kaptchaText kaptchaProducer.createText();String key getKaptchaKey(request);//10分钟过期redisTemplate.opsForValue().set(key,kaptchaText,10,TimeUnit.MINUTES);BufferedImage bufferedImage kaptchaProducer.createImage(kaptchaText);ServletOutputStream outputStream null;try {outputStream response.getOutputStream();ImageIO.write(bufferedImage,jpg,outputStream);outputStream.flush();outputStream.close();}catch (Exception e){e.printStackTrace();}}/*** 发送验证码* to: 验证码发送的手机号* return*/GetMapping(send_code)public JsonData sendCode(RequestParam(value to,required true)String to,RequestParam(value kaptcha,required true) String kaptcha,HttpServletRequest request){String key getKaptchaKey(request);String cacheKaptcha redisTemplate.opsForValue().get(key);if(kaptcha!null cacheKaptcha!null cacheKaptcha.equalsIgnoreCase(kaptcha)){redisTemplate.delete(key);//TODO 发送验证码return JsonData.buildSuccess();}else {return JsonData.buildError(验证码错误);}}private String getKaptchaKey(HttpServletRequest request){String ip CommonUtil.getIpAddr(request);String userAgent request.getHeader(User-Agent);String key user-service:captcha:CommonUtil.MD5(ipuserAgent);return key;}}