refactor: 优化认证及客户端相关代码

This commit is contained in:
2024-12-27 00:20:36 +08:00
parent 95f2617a4c
commit c90e80e9d7
35 changed files with 595 additions and 867 deletions

View File

@@ -146,13 +146,13 @@ public class LogDaoLocalImpl implements LogDao {
// 解析登录接口信息
if (requestUri.startsWith(SysConstants.LOGIN_URI) && LogStatusEnum.SUCCESS.equals(logDO.getStatus())) {
String requestBody = logRequest.getBody();
//账号登录设置操作人
// 解析账号登录用户为操作人
if (requestBody.contains(AuthTypeEnum.ACCOUNT.getValue())) {
AccountAuthReq loginReq = JSONUtil.toBean(requestBody, AccountAuthReq.class);
logDO.setCreateUser(ExceptionUtils.exToNull(() -> userService.getByUsername(loginReq.getUsername())
AccountAuthReq authReq = JSONUtil.toBean(requestBody, AccountAuthReq.class);
logDO.setCreateUser(ExceptionUtils.exToNull(() -> userService.getByUsername(authReq.getUsername())
.getId()));
return;
}
return;
}
// 解析 Token 信息
Map<String, String> requestHeaders = logRequest.getHeaders();

View File

@@ -19,30 +19,23 @@ package top.continew.admin.controller.auth;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import top.continew.admin.auth.config.AuthHandlerContext;
import top.continew.admin.auth.model.req.AuthReq;
import top.continew.admin.auth.model.resp.LoginResp;
import top.continew.admin.auth.model.resp.RouteResp;
import top.continew.admin.auth.model.resp.UserInfoResp;
import top.continew.admin.auth.service.LoginService;
import top.continew.admin.auth.service.AuthService;
import top.continew.admin.common.context.UserContext;
import top.continew.admin.common.context.UserContextHolder;
import top.continew.admin.system.model.resp.ClientResp;
import top.continew.admin.system.model.resp.user.UserDetailResp;
import top.continew.admin.system.service.ClientService;
import top.continew.admin.system.service.UserService;
import top.continew.starter.core.exception.BusinessException;
import top.continew.starter.core.validation.ValidationUtils;
import top.continew.starter.log.annotation.Log;
import java.util.List;
@@ -53,44 +46,25 @@ import java.util.List;
* @author Charles7c
* @since 2022/12/21 20:37
*/
@Slf4j
@Log(module = "登录")
@Tag(name = "认证 API")
@Log(module = "登录")
@Validated
@RestController
@RequiredArgsConstructor
@RequestMapping("/auth")
public class AuthController {
private final ClientService clientService;
private final AuthService authService;
private final UserService userService;
private final LoginService loginService;
private final AuthHandlerContext authHandlerContext;
@SaIgnore
@Operation(summary = "登录", description = "统一登录入口")
@Operation(summary = "登录", description = "用户登录")
@PostMapping("/login")
public LoginResp login(@Validated @RequestBody AuthReq loginReq, HttpServletRequest request) {
// 认证类型
String authType = loginReq.getAuthType();
// 获取并验证客户端信息
ClientResp clientResp = clientService.getClientByClientId(loginReq.getClientId());
ValidationUtils.throwIfNull(clientResp, "客户端信息不存在,请检查客户端id是否正确!");
// 验证认证类型
ValidationUtils.throwIf(!clientResp.getAuthType().contains(authType), StrUtil.format("暂未授权此类型:{}", authType));
try {
// 执行登录策略
return (LoginResp)authHandlerContext.getHandler(authType).login(loginReq, clientResp, request);
} catch (Exception e) {
log.error("登录失败: {}", e.getMessage(), e);
throw new BusinessException("登录失败: " + e.getMessage());
}
public LoginResp login(@Validated @RequestBody AuthReq req, HttpServletRequest request) {
return authService.login(req, request);
}
@Operation(summary = "用户退", description = "注销用户的当前登录")
@Operation(summary = "", description = "注销用户的当前登录")
@Parameter(name = "Authorization", description = "令牌", required = true, example = "Bearer xxxx-xxxx-xxxx-xxxx", in = ParameterIn.HEADER)
@PostMapping("/logout")
public Object logout() {
@@ -114,8 +88,8 @@ public class AuthController {
@Log(ignore = true)
@Operation(summary = "获取路由信息", description = "获取登录用户的路由信息")
@GetMapping("/route")
@GetMapping("/user/route")
public List<RouteResp> listRoute() {
return loginService.buildRouteTree(UserContextHolder.getUserId());
return authService.buildRouteTree(UserContextHolder.getUserId());
}
}

View File

@@ -17,24 +17,20 @@
package top.continew.admin.controller.auth;
import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.stp.StpUtil;
import com.xkcoding.justauth.AuthRequestFactory;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.springframework.web.bind.annotation.*;
import top.continew.admin.auth.model.resp.LoginResp;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import top.continew.admin.auth.model.resp.SocialAuthAuthorizeResp;
import top.continew.admin.auth.service.LoginService;
import top.continew.starter.core.exception.BadRequestException;
import top.continew.starter.core.validation.ValidationUtils;
import top.continew.starter.log.annotation.Log;
/**
@@ -51,7 +47,6 @@ import top.continew.starter.log.annotation.Log;
@RequestMapping("/oauth")
public class SocialAuthController {
private final LoginService loginService;
private final AuthRequestFactory authRequestFactory;
@Operation(summary = "三方账号登录授权", description = "三方账号登录授权")
@@ -64,21 +59,6 @@ public class SocialAuthController {
.build();
}
@Operation(summary = "三方账号登录", description = "三方账号登录")
@Parameter(name = "source", description = "来源", example = "gitee", in = ParameterIn.PATH)
@PostMapping("/{source}")
public LoginResp login(@PathVariable String source, @RequestBody AuthCallback callback) {
if (StpUtil.isLogin()) {
StpUtil.logout();
}
AuthRequest authRequest = this.getAuthRequest(source);
AuthResponse<AuthUser> response = authRequest.login(callback);
ValidationUtils.throwIf(!response.ok(), response.getMsg());
AuthUser authUser = response.getData();
String token = loginService.socialLogin(authUser);
return LoginResp.builder().token(token).build();
}
private AuthRequest getAuthRequest(String source) {
try {
return authRequestFactory.get(source);

View File

@@ -28,12 +28,12 @@ import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
import top.continew.starter.extension.crud.enums.Api;
/**
* 客户端管理管理 API
* 客户端管理 API
*
* @author MoChou
* @author KAI
* @since 2024/12/03 16:04
*/
@Tag(name = "客户端管理管理 API")
@Tag(name = "客户端管理 API")
@RestController
@CrudRequestMapping(value = "/system/client", api = {Api.PAGE, Api.DETAIL, Api.ADD, Api.UPDATE, Api.DELETE, Api.EXPORT})
public class ClientController extends BaseController<ClientService, ClientResp, ClientDetailResp, ClientQuery, ClientReq> {

View File

@@ -1,6 +1,6 @@
-- liquibase formatted sql
-- changeset Charles7c:1
-- changeset charles7c:1
-- comment 初始化表数据
-- 初始化默认菜单
INSERT INTO `sys_menu`
@@ -76,6 +76,13 @@ VALUES
(1114, '修改', 1110, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:storage:update', 4, 1, 1, NOW()),
(1115, '删除', 1110, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:storage:delete', 5, 1, 1, NOW()),
( 1180, '客户端管理', 1000, 2, '/system/client', 'SystemClient', 'system/client/index', NULL, 'mobile', b'0', b'0', b'0', NULL, 9, 1, 1, NOW()),
(1181, '列表', 1180, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:client:list', 1, 1, 1, NOW()),
(1182, '详情', 1180, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:client:detail', 2, 1, 1, NOW()),
(1183, '新增', 1180, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:client:add', 3, 1, 1, NOW()),
(1184, '修改', 1180, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:client:update', 4, 1, 1, NOW()),
(1185, '删除', 1180, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:client:delete', 5, 1, 1, NOW()),
(1190, '系统配置', 1000, 2, '/system/config', 'SystemConfig', 'system/config/index', NULL, 'config', b'0', b'0', b'0', NULL, 999, 1, 1, NOW()),
(1191, '查看', 1190, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:config:list', 1, 1, 1, NOW()),
(1192, '修改', 1190, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:config:update', 2, 1, 1, NOW()),
@@ -150,7 +157,8 @@ INSERT INTO `sys_dict`
(`id`, `name`, `code`, `description`, `is_system`, `create_user`, `create_time`)
VALUES
(1, '公告类型', 'notice_type', NULL, b'1', 1, NOW()),
(2, '消息类型', 'message_type', NULL, b'1', 1, NOW());
(2, '消息类型', 'message_type', NULL, b'1', 1, NOW()),
(3, '客户端类型', 'client_type', NULL, b'1', 1, NOW());
INSERT INTO `sys_dict_item`
(`id`, `label`, `value`, `color`, `sort`, `description`, `status`, `dict_id`, `create_user`, `create_time`)
@@ -158,7 +166,10 @@ VALUES
(1, '通知', '1', 'blue', 1, NULL, 1, 1, 1, NOW()),
(2, '活动', '2', 'orangered', 2, NULL, 1, 1, 1, NOW()),
(3, '安全消息', '1', 'blue', 1, NULL, 1, 2, 1, NOW()),
(4, '活动消息', '2', 'orangered', 2, NULL, 1, 2, 1, NOW());
(4, '活动消息', '2', 'orangered', 2, NULL, 1, 2, 1, NOW()),
(5, '桌面端', 'PC', 'blue', 1, NULL, 1, 3, 1, NOW()),
(6, '安卓', 'ANDROID', '#148628', 2, NULL, 1, 3, 1, NOW()),
(7, '小程序', 'XCX', '#7930AD', 3, NULL, 1, 3, 1, NOW());
-- 初始化默认用户和角色关联数据
INSERT INTO `sys_user_role`
@@ -188,30 +199,8 @@ VALUES
(1, '开发环境', 'local_dev', 2, NULL, NULL, NULL, 'C:/continew-admin/data/file/', 'http://localhost:8000/file', '本地存储', b'1', 1, 1, 1, NOW()),
(2, '生产环境', 'local_prod', 2, NULL, NULL, NULL, '../data/file/', 'http://api.continew.top/file', '本地存储', b'0', 2, 2, 1, NOW());
-- 客户端管理管理菜单
INSERT INTO `sys_menu`
(`title`, `parent_id`, `type`, `path`, `name`, `component`, `redirect`, `icon`, `is_external`, `is_cache`, `is_hidden`, `permission`, `sort`, `status`, `create_user`, `create_time`, `update_user`, `update_time`)
-- 初始化客户端数据
INSERT INTO `sys_client`
(`id`, `client_id`, `client_key`, `client_secret`, `auth_type`, `client_type`, `active_timeout`, `timeout`, `status`, `create_user`, `create_time`)
VALUES
( '客户端管理', 1000, 2, '/system/client', 'SystemClient', 'system/client/index', NULL, 'mobile', b'0', b'0', b'0', NULL, 9, 1, 1, NOW(), NULL, NULL);
SET @parentId = LAST_INSERT_ID();
-- 客户端管理管理按钮
INSERT INTO `sys_menu`
(`title`, `parent_id`, `type`, `path`, `name`, `component`, `redirect`, `icon`, `is_external`, `is_cache`, `is_hidden`, `permission`, `sort`, `status`, `create_user`, `create_time`, `update_user`, `update_time`)
VALUES
('列表', @parentId, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:client:list', 1, 1, 1, NOW(), NULL, NULL),
('详情', @parentId, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:client:detail', 2, 1, 1, NOW(), NULL, NULL),
('新增', @parentId, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:client:add', 3, 1, 1, NOW(), NULL, NULL),
('修改', @parentId, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:client:update', 4, 1, 1, NOW(), NULL, NULL),
('删除', @parentId, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:client:delete', 5, 1, 1, NOW(), NULL, NULL),
('导出', @parentId, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:client:export', 6, 1, 1, NOW(), NULL, NULL);
-- 插入客户端字典数据
INSERT INTO `sys_dict` (`id`, `name`, `code`, `description`, `is_system`, `create_user`, `create_time`, `update_user`, `update_time`) VALUES (4, '客户端类型', 'client_type', NULL, b'0', 1, '2024-12-17 18:09:37', NULL, NULL);
INSERT INTO `sys_dict_item` (`id`, `label`, `value`, `color`, `sort`, `description`, `status`, `dict_id`, `create_user`, `create_time`, `update_user`, `update_time`) VALUES (659457796923719711, '桌面端', 'pc', 'blue', 999, NULL, 1, 4, 1, '2024-12-17 18:09:51', NULL, NULL);
INSERT INTO `sys_dict_item` (`id`, `label`, `value`, `color`, `sort`, `description`, `status`, `dict_id`, `create_user`, `create_time`, `update_user`, `update_time`) VALUES (659457877756346402, '安卓', 'android', '#148628', 999, NULL, 1, 4, 1, '2024-12-17 18:10:10', NULL, NULL);
INSERT INTO `sys_dict_item` (`id`, `label`, `value`, `color`, `sort`, `description`, `status`, `dict_id`, `create_user`, `create_time`, `update_user`, `update_time`) VALUES (659457929665052709, '小程序', 'xcx', '#7930AD', 999, NULL, 1, 4, 1, '2024-12-17 18:10:23', NULL, NULL);
-- 插入客户端数据
INSERT INTO `sys_client` (`id`, `client_id`, `client_key`, `client_secret`, `auth_type`, `client_type`, `active_timeout`, `timeout`, `status`, `create_user`, `create_time`, `update_user`, `update_time`) VALUES (1, 'ef51c9a3e9046c4f2ea45142c8a8344a', 'pc', 'dd77ab1e353a027e0d60ce3b151e8642', '[\"account\", \"socialAuth\", \"email\", \"phone\"]', 'pc', 1800, 86400, 1, 1, now(), 1, '2024-12-25 17:41:36');
(1, 'ef51c9a3e9046c4f2ea45142c8a8344a', 'pc', 'dd77ab1e353a027e0d60ce3b151e8642', '[\"ACCOUNT\", \"EMAIL\", \"PHONE\", \"SOCIAL\"]', 'PC', 1800, 86400, 1, 1, NOW());

View File

@@ -300,14 +300,14 @@ CREATE TABLE IF NOT EXISTS `sys_client` (
`client_id` varchar(50) NOT NULL COMMENT '客户端ID',
`client_key` varchar(255) NOT NULL COMMENT '客户端Key',
`client_secret` varchar(255) NOT NULL COMMENT '客户端秘钥',
`auth_type` json DEFAULT NULL COMMENT '授权类型',
`client_type` varchar(50) DEFAULT NULL COMMENT '客户端类型',
`auth_type` json DEFAULT NULL COMMENT '认证类型',
`client_type` varchar(50) NOT NULL COMMENT '客户端类型',
`active_timeout` int DEFAULT '-1' COMMENT 'Token最低活跃频率-1为不限制',
`timeout` int DEFAULT '2592000' COMMENT 'Token有效期默认30天单位',
`status` tinyint(1) UNSIGNED NOT NULL COMMENT '状态1启用2禁用',
`status` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '状态1启用2禁用',
`create_user` bigint(20) NOT NULL COMMENT '创建人',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_user` bigint(20) DEFAULT NULL COMMENT '修改人',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客户端管理';
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客户端';

View File

@@ -1,6 +1,6 @@
-- liquibase formatted sql
-- changeset Charles7c:1
-- changeset charles7c:1
-- comment 初始化表数据
-- 初始化默认菜单
INSERT INTO "sys_menu"

View File

@@ -1,6 +1,6 @@
-- liquibase formatted sql
-- changeset Charles7c:1
-- changeset charles7c:1
-- comment 初始化表结构
CREATE TABLE IF NOT EXISTS "sys_menu" (
"id" int8 NOT NULL,