【SpringSecurity+OAuth2+JWT入门到实战】10.改造优化获取图形验证码和短信验证码
项目文件结构
验证码处理器代码结构
虚线是调用
- ValidateCodeController # 服务入口
- ValidateCodeProcessor # 验证码处理接口
- AbstractValidateCodeProcessor # 验证码处理 公共功能,使用模版方法模式聚合公共逻辑
- ImageCodeProcessor # 图片验证码处理:响应
- SmsCodeProcessor # 短信验证码处理:发送
- ValidateCodeGenerator # 生成接口
- ImageCodeGenerate # 图形验证码生成
- SmsCodeGenerator # 短信验证码生成
ValidateCodeProcessor
com.spring.security.validate.code路径创建ValidateCodeProcessor类,生成验证码入口
package com.spring.security.validate.code;import org.springframework.web.context.request.ServletWebRequest;
/**
* 校验码处理器,封装不同校验码的处理逻辑
*
*/
public interface ValidateCodeProcessor {
/**
* 验证码放入session时的前缀
*/
String SESSION_KEY_PREFIX = "SESSION_KEY_FOR_CODE_";
/**
* 创建校验码
*
* @param request
* @throws Exception
*/
void createCode(ServletWebRequest request) throws Exception;
}
AbstractValidateCodeProcessor
验证码处理 公共功能,使用模版方法模式聚合公共逻辑
com.spring.security.validate.code.impl路径创建AbstractValidateCodeProcessor类
package com.spring.security.validate.code.impl;import java.util.Map;
import com.spring.security.validate.code.ValidateCodeException;
import org.apache.commons.lang.StringUtils;
import com.spring.security.validate.code.ValidateCode;
import com.spring.security.validate.code.ValidateCodeGenerator;
import com.spring.security.validate.code.ValidateCodeProcessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.social.connect.web.HttpSessionSessionStrategy;
import org.springframework.social.connect.web.SessionStrategy;
import org.springframework.web.context.request.ServletWebRequest;
public abstract class AbstractValidateCodeProcessor<C extends ValidateCode> implements ValidateCodeProcessor {
/**
* 操作session的工具类
*/
private SessionStrategy sessionStrategy = new HttpSessionSessionStrategy();
/**
* 收集系统中所有的 {@link ValidateCodeGenerator} 接口的实现。
*/
@Autowired
private Map<String, ValidateCodeGenerator> validateCodeGenerators;
/**
* ValidateCodeProcessor
*/
@Override
public void createCode(ServletWebRequest request) throws Exception {
C validateCode = generate(request);
save(request, validateCode);
send(request, validateCode);
}
/**
* 生成校验码
*
* @param request
* @return
*/
@SuppressWarnings("unchecked")
private C generate(ServletWebRequest request) {
String type = getProcessorType(request);
ValidateCodeGenerator validateCodeGenerator = validateCodeGenerators.get(type + "CodeGenerator");
if (validateCodeGenerator == null) {
throw new ValidateCodeException("验证码生成器" + type + "CodeGenerator不存在");
}
return (C) validateCodeGenerator.createCode(request);
}
/**
* 保存校验码
*
* @param request
* @param validateCode
*/
private void save(ServletWebRequest request, C validateCode) {
sessionStrategy.setAttribute(request, SESSION_KEY_PREFIX + getProcessorType(request).toUpperCase(), validateCode);
}
/**
* 发送校验码,由子类实现
*
* @param request
* @param validateCode
* @throws Exception
*/
protected abstract void send(ServletWebRequest request, C validateCode) throws Exception;
/**
* 根据请求的url获取校验码的类型
*
* @param request
* @return
*/
private String getProcessorType(ServletWebRequest request) {
return StringUtils.substringAfter(request.getRequest().getRequestURI(), "/code/");
}
}
ImageCodeProcessor
com.spring.security.validate.code.image路径创建ImageCodeProcessor图片验证码处理:响应
/** *
*/
package com.spring.security.validate.code.image;
import javax.imageio.ImageIO;
import com.spring.security.validate.code.impl.AbstractValidateCodeProcessor;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.ServletWebRequest;
/**
* 图片验证码处理器
*
*/
@Component("imageCodeProcessor")
public class ImageCodeProcessor extends AbstractValidateCodeProcessor<ImageCode> {
/**
* 发送图形验证码,将其写到响应中
*/
@Override
protected void send(ServletWebRequest request, ImageCode imageCode) throws Exception {
ImageIO.write(imageCode.getImage(), "JPEG", request.getResponse().getOutputStream());
}
}
SmsCodeProcessor
com.spring.security.validate.code.sms路径创建SmsCodeProcessor短信验证码处理:发送
/** *
*/
package com.spring.security.validate.code.sms;
import com.spring.security.validate.code.ValidateCode;
import com.spring.security.validate.code.impl.AbstractValidateCodeProcessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.context.request.ServletWebRequest;
/**
* 短信验证码处理器
*
*/
@Component("smsCodeProcessor")
public class SmsCodeProcessor extends AbstractValidateCodeProcessor<ValidateCode> {
/**
* 短信验证码发送器
*/
@Autowired
private SmsCodeSender smsCodeSender;
@Override
protected void send(ServletWebRequest request, ValidateCode validateCode) throws Exception {
//获取手机号
String mobile = ServletRequestUtils.getRequiredStringParameter(request.getRequest(), "mobile");
//发送短信
smsCodeSender.send(mobile, validateCode.getCode());
}
}
修改控制器
改造ValidateController类统一访问路径
package com.spring.security.validate.code;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.ServletWebRequest;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
/**
* 获取验证码控制器
*/
@RestController
public class ValidateController {
@Autowired
private Map<String, ValidateCodeProcessor> validateCodeProcessor;
/**
* 创建验证码,根据验证码类型不同,调用不同的 {@link ValidateCodeProcessor}接口实现
*
* @param request
* @param response
* @param type
* @throws Exception
*/
@GetMapping("/code/{type}")
public void createCode(HttpServletRequest request, HttpServletResponse response, @PathVariable String type)
throws Exception {
validateCodeProcessor.get(type + "CodeProcessor").createCode(new ServletWebRequest(request, response));
}
}
修改图形验证码拦截器
修改ValidateCodeFilter类的validateCode方法:
ImageCode codeInSession = (ImageCode) sessionStrategy.getAttribute(servletWebRequest, "SESSION_KEY_FOR_CODE_IMAGE");
session值我们先写死,等做到短信验证码拦截器一起优化掉。
测试
启动项目访问:http://127.0.0.1:8080/signIn.html
获取图形验证码没问题,输入正确验证码账号登录:
重启项目测试获取短信验证:
以上是 【SpringSecurity+OAuth2+JWT入门到实战】10.改造优化获取图形验证码和短信验证码 的全部内容, 来源链接: utcz.com/z/514083.html