图片验证码
1、编写工具类
public class CaptchaUtils {
private static char mapTable[] = { '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
'A', 'B', 'C', 'D', 'E', 'F','G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
// 获取随机颜色
static Color getRandColor(int fc, int bc) {
Random random = new Random();
if (fc > 255)
fc = 255;
if (bc > 255)
bc = 255;
int r = fc + random.nextInt(bc - fc);
int g = fc + random.nextInt(bc - fc);
int b = fc + random.nextInt(bc - fc);
return new Color(r, g, b);
}
public static Map getImageCode(int width, int height) {
Map returnMap = new HashMap();
if (width <= 0) width = 60;
if (height <= 0) height = 20;
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
Random random = new Random();
g.setColor(getRandColor(200, 250));
g.fillRect(0, 0, width, height);
g.setFont(new Font("Times New Roman", Font.PLAIN, 18));
g.setColor(getRandColor(160, 200));
for (int i = 0; i < 146; i++) {
int x = random.nextInt(width);
int y = random.nextInt(height);
int x1 = random.nextInt(12);
int y1 = random.nextInt(12);
g.drawLine(x, y, x + x1, y + y1); // 干扰线
}
String captchaCode = ""; // 验证码
for (int i = 0; i < 4; ++i) {
captchaCode += mapTable[(int) (mapTable.length * Math.random())];
g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));
String str = captchaCode.substring(i, i + 1);
g.drawString(str, 13 * i + 6, 16);
}
g.dispose();
returnMap.put("image", image);
returnMap.put("value", captchaCode);
return returnMap;
}
}
2、编写Controller
// 获取验证码图片
@RequestMapping("/captchaImage")
public void captchaImage(HttpServletRequest request, HttpServletResponse response) throws Exception {
Map map = CaptchaUtils.getImageCode(60, 20);
request.getSession().setAttribute( "captchaCode", map.get("value").toString().toLowerCase());
request.getSession().setAttribute("captchaTime", new Date().getTime());
ImageIO.write((BufferedImage) map.get("image"), "JPG", response.getOutputStream());
}
// 验证验证码
@RequestMapping("/checkCaptcha")
@ResponseBody
public String checkCaptcha(HttpServletRequest request, HttpSession session) {
String testCode = request.getParameter("captchaCode");
Object realObj = session.getAttribute("captchaCode");
if (realObj == null) {
return "验证码已失效,请重新输入!";
}
String realCode = realObj.toString();
Date now = new Date();
Long captchaTime = Long.valueOf(session.getAttribute("captchaTime") + "");
if (StringUtils.isEmpty(testCode) || !(testCode.equalsIgnoreCase(realCode))) {
return "验证码错误";
} else if ((now.getTime() - captchaTime) / 1000 / 60 > 5) {
return "验证码已失效,请重新输入";
} else {
session.removeAttribute("captchaCode");
return "1";
}
}
图片验证码第三方组件:jcaptcha、kaptcha
腾讯滑动验证码
官网:https://007.qq.com
后端接入组成
1、添加Maven依赖
com.alibaba
fastjson
1.2.58
2、用于接收验证响应的POJO
public class Captcha implements Serializable {
private Integer response;
@JsonProperty("evil_level")
private String evilLevel;
@JsonProperty("err_msg")
private String errMsg;
}
3、过滤器
@Component
public class CaptchaFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// 针对指定接口,进行验证
if ("/client/submit".equals(request.getRequestURI()) && "post".equalsIgnoreCase(request.getMethod())) {
verify(request);
}
filterChain.doFilter(request, response);
}
private void verify(HttpServletRequest request) throws RestfulException {
String ticket = request.getParameter("ticket");
String randstr = request.getParameter("randstr"); // ticket 和 randstr 通过 URL参数传给后端
String userIp = request.getRemoteAddr();
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new FastJsonHttpMessageConverter()); // 允许多种 content-type
String url = String.format("https://ssl.captcha.qq.com/ticket/verify?aid=00&AppSecretKey=00&Ticket=%s&Randstr=%s&UserIP=%s", ticket, randstr, userIp);
Captcha response = restTemplate.getForObject(url, Captcha.class);
if (response.getResponse() != 1) {
throw new RestfulException("验证失败");
}
}
}
邮箱验证
SMTP:Simple Mail Transfer Protocol,简单邮件传输协议
POP3:Post Office Protocol - Version 3,邮局协议,用于客户端访问邮件服务器,客户端需要把所有邮件下载到本地
IMAP:Internet Mail Access Protocol,Internet邮件访问协议,POP3的替代协议,客户端无需下载所有邮件
JavaMail应用组成
1、配置Maven依赖
javax.mail
mail
1.4.7
org.springframework.boot
spring-boot-starter-mail
2、配置Bean
整合SpringMVC
true
javax.net.ssl.SSLSocketFactory
20000
整合SpringBoot
spring:
mail:
host: smtp.exmail.qq.com
username: [email protected]
password: xxx
default-encoding: UTF-8
port: 465 # 阿里云上封禁25端口,必须用465端口
properties.mail.smtp:
# SSL证书Socket工厂
socketFactory.class: javax.net.ssl.SSLSocketFactory
# 登录服务器是否需要认证
auth: true
3、编写工具类
public class MailUtils {
public static String sendMail(String text, String subject, String emailAddress, JavaMailSenderImpl javaMailSender, Boolean type) {
MimeMessage mMessage = javaMailSender.createMimeMessage(); // 邮件对象
MimeMessageHelper mMessageHelper;
try {
mMessageHelper = new MimeMessageHelper(mMessage, true, "UTF-8");
// MimeMessageHelper的from必须和JavaMailSender的username一致
mMessageHelper.setFrom(javaMailSender.getUsername());
mMessageHelper.setTo(emailAddress);
mMessageHelper.setSubject(subject); // 标题
mMessageHelper.addAttachment("文件名", new ByteArrayDataSource(bytes, "application/octet-stream")); // 附件
if (type) {
mMessageHelper.setText(text, true); // HTML格式
} else {
mMessageHelper.setText(text, false);
}
javaMailSender.send(mMessage); // 发送邮件
} catch (MessagingException e) {
e.printStackTrace();
return "failure";
}
return "success";
}
}
4、编写Controller
@Autowired
private JavaMailSenderImpl javaMailSender;
// 发送文本
@RequestMapping("sendText")
@Async // 用异步方式发送邮件,得配合@EnableAsync使用
public String sendTextEmail() {
return MailUtils.sendMail("邮件内容", "邮件标题", "[email protected]", javaMailSender, false);
}
// 发送 html
@RequestMapping("sendHtml")
public String sendHtmlEmail() {
String html = "链接"
return MailUtils.sendMail(html, "邮件标题", "[email protected]", javaMailSender, true);
}
可以使用Velocity、FreeMarker等模板引擎,发送复杂内容
阿里云滑动验证码
1、前端
登录
2、JAVA后端
pom.xml
com.aliyun
captcha20230305
1.0.1
com.aliyun
tea-openapi
0.2.8
com.aliyun
tea
1.1.14
private void validate(HttpServletRequest request) throws Exception {
Config config = new Config();
config.accessKeyId = accessKeyId;
config.accessKeySecret = accessKeySecret;
config.endpoint = "captcha.cn-shanghai.aliyuncs.com";
config.connectTimeout = 5000;
config.readTimeout = 5000;
com.aliyun.captcha20230305.Client client = new com.aliyun.captcha20230305.Client(config);
VerifyCaptchaRequest captchaRequest = new VerifyCaptchaRequest();
captchaRequest.captchaVerifyParam = request.getParameter("captchaVerifyParam");
VerifyCaptchaResponse resp = client.verifyCaptcha(captchaRequest);
if (!resp.body.result.verifyResult) {
throw new CaptchaException("验证失败");
}
}
阿里云短信服务
1、申请签名,添加短信模板
2、pom.xml
com.aliyun
alibabacloud-dysmsapi20170525
2.0.24
3、发送短信
/* 生成验证码 */
Random random = new Random();
String code = String.valueOf(1000 + random.nextInt(8999));
/* 发送短信 */
String templateParam = String.format("{\"code\":\"%s\"}", code);
StaticCredentialProvider provider = StaticCredentialProvider.create(
Credential.builder().accessKeyId(accessKeyId).accessKeySecret(accessKeySecret).build()
);
AsyncClient client = AsyncClient.builder().region(阿里云region).credentialsProvider(provider)
.overrideConfiguration(
ClientOverrideConfiguration.create().setEndpointOverride("dysmsapi.aliyuncs.com")
).build();
SendSmsRequest sendSmsRequest = SendSmsRequest.builder().signName(签名名称)
.templateCode(模板CODE).templateParam(templateParam).phoneNumbers(目标手机号).build();
CompletableFuture response = client.sendSms(sendSmsRequest);
SendSmsResponse resp = response.get();
System.out.println(new Gson().toJson(resp));
client.close();
阿里云
短信服务、语言服务
流量服务:向手机充值流量,用于营销
号码隐私保护:把一个临时号码绑定到客户的手机号,以保密客户的手机号
号码认证服务:直接验证客户的手机号,以免除短信验证
邮件推送
敏感数据保护
内容安全:敏感内容识别
实人认证:人脸比对、OCR等