1、验证码实现
1、后端返回的信息
2、前端通过该接口获取验证码信息
// 获取验证码
export function getCodeImg() {
return request({
url: '/captchaImage',
headers: {
isToken: false
},
method: 'get',
timeout: 20000
})
}
3、后端实现
验证码开关
boolean captchaEnabled = configService.selectCaptchaEnabled();
ajax.put("captchaEnabled", captchaEnabled);
if (!captchaEnabled)
{
return ajax;
}
生成uuid,作为验证码的唯一key,过期时间为2分钟,保存验证码信息
String uuid = IdUtils.simpleUUID();
String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid;
redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
获取验证码的类型,在yml中定义
# 验证码类型 math 数字计算 char 字符验证
captchaType: math
引入的库
import com.google.code.kaptcha.Producer;
返回格式:通常是一个包含 数学题目 和 答案 的组合字符串,用 @ 分隔
String captchaType = RuoYiConfig.getCaptchaType();
String capText = captchaProducerMath.createText();
capStr = capText.substring(0, capText.lastIndexOf("@"));
如果 capText = "3 + 5@8",则 capStr = "3 + 5"。
code = capText.substring(capText.lastIndexOf("@") + 1);
如果 capText = "3 + 5@8",则 code = "8"。
image = captchaProducerMath.createImage(capStr);
将数学题目(capStr)转换成图片
这段代码的作用是将一个图像(image)以 JPEG 格式 写入到 FastByteArrayOutputStream 内存流中
FastByteArrayOutputStream os = new FastByteArrayOutputStream();
try
{
ImageIO.write(image, "jpg", os);
}
catch (IOException e)
{
return AjaxResult.error(e.getMessage());
}
成果展示
</el-input>
<div class="login-code">
<img :src="codeUrl" @click="getCode" class="login-code-img"/>
</div>
</el-form-item>
把图片内容转成base64编码
src=“data:image/jpeg;base64,这里放的是上面写入的后端返回的内容”
2、日志实现
自定义Log注解
@Target({ ElementType.PARAMETER, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Log
Log AOP
@Aspect
@Component
public class LogAspect
创建了一个 ThreadLocal 变量,用于存储线程私有的 Long 类型数据,并命名为 "Cost Time",用于 记录线程执行耗时
private static final ThreadLocal<Long> TIME_THREADLOCAL = new NamedThreadLocal<Long>("Cost Time");
在添加了Log注解的方法执行前,记录下时间
@Before(value = "@annotation(controllerLog)")
public void doBefore(JoinPoint joinPoint, Log controllerLog)
{
TIME_THREADLOCAL.set(System.currentTimeMillis());
}
方法正常执行结束后,执行handleLog方法
@AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")
public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult)
{
handleLog(joinPoint, controllerLog, null, jsonResult);
}
同上,出现异常时执行
@AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")
public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e)
{
handleLog(joinPoint, controllerLog, e, null);
}
protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult)
operLog操作日志对象,通常包含:操作人、操作类型、操作时间、IP、请求参数、执行结果等信息。
AsyncFactory 是一个异步任务工厂
AsyncManager 是异步任务管理器
执行流程
1、构造操作日志(operLog)
2、创建异步任务(AsyncFactory.recordOper(operLog))
3、提交任务到线程池(AsyncManager.me().execute())
4、线程池异步执行(实际保存日志,写入日志表sys_oper_log)
使用
@Log(title = "登录日志", businessType = BusinessType.DELETE)
@annotation(“controllerlog”) 使用入参的形式将 log 注解实例直接传递给切面方法。
@annotation(“com.xxx.log”) 表示在目标方法上查找特定的注解类
a) 编译时类型推断:ide 使用编译时类型推断来确定目标方法上的 @log 注解类型。
b) 注解处理器:ide 还可以使用注解处理器来分析 @log 注解,并提取出其类型信息。