登录日志切面实现
基本思路
对标注了登录日志注解的方法进行切面处理,在登录接口成功后记录账号的登录成功日志,包括登录IP、时间、使用客户端等信息。
登录日志表设计
DROP TABLE IF EXISTS `account_login_log`;
CREATE TABLE `account_login_log` (
`id` bigint NOT NULL COMMENT '主键ID',
`create_by` bigint NULL DEFAULT NULL COMMENT '创建者',
`create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
`update_by` bigint NULL DEFAULT NULL COMMENT '最后更新者',
`update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
`account_id` bigint NOT NULL COMMENT '登录账号ID',
`login_time` datetime NULL DEFAULT NULL COMMENT '登录时间',
`login_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '登录方式,如用户名密码登录、短信验证码登录等登录IP地址',
`login_ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '登录IP地址',
`login_location` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '登录地点',
`login_device` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '登录设备信息',
`browser` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户登录时使用的浏览器信息',
`operating_system` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '用户登录时使用的操作系统信息',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '账号登录日志' ROW_FORMAT = Dynamic;
登录日志注解定义
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface LoginLog {
}
登录日志切面定义
@Aspect
@Component
@RequiredArgsConstructor
public class LoginLogAspect {
private final AccountLoginLogService accountLoginLogService;
@Pointcut(value = "@annotation(loginLog)")
public void pointcut(LoginLog loginLog) {
}
@AfterReturning("pointcut(loginLog)")
public void afterReturningAdvice(JoinPoint joinPoint, LoginLog loginLog) {
Long loginId = StpUtil.getLoginId(-1L);
accountLoginLogService.asyncSaveLog(loginId, DateUtil.date(), RequestUtils.getRequest());
}
}
登录日志保存服务实现
import cn.com.jcoo.system.entity.AccountLoginLog;
import cn.com.jcoo.system.mapper.AccountLoginLogMapper;
import cn.com.jcoo.util.RequestUtils;
import cn.hutool.http.useragent.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
@Slf4j
@RequiredArgsConstructor
@Service
public class AccountLoginLogService extends ServiceImpl<AccountLoginLogMapper, AccountLoginLog> {
@Async
public void asyncSaveLog(Long accountId, Date loginTime, HttpServletRequest request) {
AccountLoginLog accountLoginLog = new AccountLoginLog();
accountLoginLog.setAccountId(accountId);
accountLoginLog.setLoginTime(loginTime);
String requestIP = RequestUtils.getRequestIP(request);
String userAgentHeader = request.getHeader(HttpHeaders.USER_AGENT);
UserAgent userAgent = UserAgentUtil.parse(userAgentHeader);
Platform platform = userAgent.getPlatform();
Browser browser = userAgent.getBrowser();
OS os = userAgent.getOs();
String osName = os.getName().split(" ")[0];
String osVersion = os.getVersion(userAgentHeader);
accountLoginLog.setLoginIp(requestIP);
accountLoginLog.setLoginDevice(platform.getName());
accountLoginLog.setBrowser(browser.getName());
accountLoginLog.setOperatingSystem(osName + " " + osVersion);
this.save(accountLoginLog);
}
}
使用示例及效果展示
对登录接口中标注登录日志注解:
@ApiOperationSupport(author = "jinty")
@LoginLog
@Operation(summary = "登录")
@PostMapping("/login")
ApiRet<LoginUser> login(@Valid @RequestBody LoginParam param) {
...
}
评论区