认证退出与操作日志、密码规则,以及运输业务多项修正

This commit is contained in:
2026-09-22 12:03:59 +08:00
parent 5254a46de8
commit 14c1d9dff0
21 changed files with 790 additions and 26 deletions
@@ -25,6 +25,7 @@
*/
package org.springblade.auth.config;
import org.springblade.auth.filter.LogoutLogFilter;
import org.springblade.auth.granter.IamAwareTokenGranterFactory;
import org.springblade.auth.handler.BladeAuthorizationHandler;
import org.springblade.auth.handler.BladeLockHandler;
@@ -53,9 +54,11 @@ import org.springblade.core.tenant.BladeTenantProperties;
import org.springblade.system.feign.IUserClient;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.Ordered;
import org.springframework.jdbc.core.JdbcTemplate;
import java.util.List;
@@ -88,6 +91,16 @@ public class BladeAuthConfiguration {
return new BladeLogHandler(authLogClient, bladeProperties, serverInfo);
}
@Bean
public FilterRegistrationBean<LogoutLogFilter> logoutLogFilter(BladeLogHandler logHandler) {
FilterRegistrationBean<LogoutLogFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new LogoutLogFilter(logHandler));
registration.addUrlPatterns("/*");
registration.setName("logoutLogFilter");
registration.setOrder(Ordered.LOWEST_PRECEDENCE - 100);
return registration;
}
@Bean
public PasswordHandler passwordHandler(OAuth2Properties properties) {
return new BladePasswordHandler(properties);
@@ -0,0 +1,80 @@
/**
* BladeX Commercial License Agreement
* Copyright (c) 2018-2099, https://bladex.cn. All rights reserved.
* <p>
* Use of this software is governed by the Commercial License Agreement
* obtained after purchasing a license from BladeX.
* <p>
* 1. This software is for development use only under a valid license
* from BladeX.
* <p>
* 2. Redistribution of this software's source code to any third party
* without a commercial license is strictly prohibited.
* <p>
* 3. Licensees may copyright their own code but cannot use segments
* from this software for such purposes. Copyright of this software
* remains with BladeX.
* <p>
* Using this software signifies agreement to this License, and the software
* must not be used for illegal purposes.
* <p>
* THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY. The author is
* not liable for any claims arising from secondary or illegal development.
* <p>
* Author: Chill Zhuang (bladejava@qq.com)
*/
package org.springblade.auth.filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springblade.auth.handler.BladeLogHandler;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.utils.StringUtil;
import org.springframework.core.Ordered;
import org.springframework.web.filter.OncePerRequestFilter;
import java.io.IOException;
/**
* 退出登录日志过滤器
* 在清除 Token 前解析当前用户并异步写入认证日志
*
* @author BladeX
*/
@RequiredArgsConstructor
public class LogoutLogFilter extends OncePerRequestFilter implements Ordered {
private static final String LOGOUT_PATH = "/oauth/logout";
private final BladeLogHandler logHandler;
@Override
protected boolean shouldNotFilter(HttpServletRequest request) {
String path = request.getRequestURI();
return StringUtil.isBlank(path) || !path.contains(LOGOUT_PATH);
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// 必须在 logout 清 token 之前取用户,否则无法关联账号
BladeUser user = AuthUtil.getUser();
try {
filterChain.doFilter(request, response);
} finally {
if (user != null) {
logHandler.handleLogoutLog(user, request);
}
}
}
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE - 100;
}
}
@@ -29,12 +29,15 @@ import org.springblade.core.launch.props.BladeProperties;
import org.springblade.core.launch.server.ServerInfo;
import org.springblade.core.oauth2.provider.OAuth2Request;
import org.springblade.core.oauth2.service.OAuth2User;
import org.springblade.core.secure.BladeUser;
import org.springblade.core.tool.utils.DateUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.StringUtil;
import org.springblade.core.tool.utils.WebUtil;
import org.springblade.system.pojo.entity.AuthLog;
import org.springblade.system.feign.IAuthLogClient;
import org.springblade.system.pojo.entity.AuthLog;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -42,7 +45,7 @@ import java.util.concurrent.CompletableFuture;
/**
* 认证日志处理器
* 在用户认证成功时异步记录登录日志
* 在用户认证成功/退出时异步记录登录、退出日志
*
* @author BladeX
*/
@@ -50,6 +53,11 @@ import java.util.concurrent.CompletableFuture;
@RequiredArgsConstructor
public class BladeLogHandler {
/**
* 退出登录授权类型标识
*/
public static final String GRANT_TYPE_LOGOUT = "logout";
private final IAuthLogClient authLogClient;
private final BladeProperties bladeProperties;
private final ServerInfo serverInfo;
@@ -72,6 +80,26 @@ public class BladeLogHandler {
});
}
/**
* 记录退出登录日志
*
* @param user 当前登录用户
* @param request HTTP 请求
*/
public void handleLogoutLog(BladeUser user, HttpServletRequest request) {
if (user == null) {
return;
}
CompletableFuture.runAsync(() -> {
try {
AuthLog authLog = buildLogoutLog(user, request);
authLogClient.saveAuthLog(authLog);
} catch (Exception exception) {
log.error("记录退出日志异常:{}", exception.getMessage(), exception);
}
});
}
/**
* 构建认证日志实体
*
@@ -96,4 +124,38 @@ public class BladeLogHandler {
return authLog;
}
/**
* 构建退出日志实体
*
* @param user 当前登录用户
* @param request HTTP 请求
* @return AuthLog
*/
private AuthLog buildLogoutLog(BladeUser user, HttpServletRequest request) {
AuthLog authLog = new AuthLog();
authLog.setUserId(user.getUserId());
authLog.setTenantId(user.getTenantId());
authLog.setServiceId(bladeProperties.getName());
authLog.setServerIp(serverInfo.getIpWithPort());
authLog.setServerHost(serverInfo.getHostName());
authLog.setEnv(bladeProperties.getEnv());
authLog.setAccount(user.getAccount());
authLog.setRealName(resolveRealName(user));
authLog.setGrantType(GRANT_TYPE_LOGOUT);
authLog.setRemoteIp(WebUtil.getIP(request));
authLog.setUserAgent(WebUtil.getUserAgent(request));
authLog.setLoginTime(DateUtil.now());
return authLog;
}
private String resolveRealName(BladeUser user) {
if (StringUtil.isNotBlank(user.getNickName())) {
return user.getNickName();
}
if (StringUtil.isNotBlank(user.getUserName())) {
return user.getUserName();
}
return user.getAccount();
}
}