refactor: 重构获取登录用户信息方式(线程级存储)

This commit is contained in:
2024-10-10 22:33:20 +08:00
parent 8466105a9b
commit 79ea39dd07
27 changed files with 523 additions and 363 deletions

View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.config.satoken;
import cn.dev33.satoken.fun.SaParamFunction;
import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.stp.StpUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.lang.Nullable;
import top.continew.admin.common.context.UserContextHolder;
/**
* Sa-Token 扩展拦截器
*
* @author Charles7c
* @since 2024/10/10 20:25
*/
public class SaExtensionInterceptor extends SaInterceptor {
public SaExtensionInterceptor(SaParamFunction<Object> auth) {
super(auth);
}
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) throws Exception {
boolean flag = super.preHandle(request, response, handler);
if (flag && StpUtil.isLogin()) {
UserContextHolder.getContext();
UserContextHolder.getExtraContext();
}
return flag;
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
@Nullable Exception e) throws Exception {
try {
super.afterCompletion(request, response, handler, e);
} finally {
UserContextHolder.clearContext();
}
}
}

View File

@@ -19,11 +19,12 @@ package top.continew.admin.config.satoken;
import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpInterface;
import cn.dev33.satoken.stp.StpUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import top.continew.admin.common.model.dto.LoginUser;
import top.continew.admin.common.util.helper.LoginHelper;
import top.continew.admin.common.context.UserContext;
import top.continew.admin.common.context.UserContextHolder;
import top.continew.starter.auth.satoken.autoconfigure.SaTokenExtensionProperties;
import top.continew.starter.core.constant.StringConstants;
import top.continew.starter.core.util.validate.CheckUtils;
@@ -54,14 +55,15 @@ public class SaTokenConfiguration {
*/
@Bean
public SaInterceptor saInterceptor() {
return new SaInterceptor(handle -> SaRouter.match(StringConstants.PATH_PATTERN)
return new SaExtensionInterceptor(handle -> SaRouter.match(StringConstants.PATH_PATTERN)
.notMatch(properties.getSecurity().getExcludes())
.check(r -> {
LoginUser loginUser = LoginHelper.getLoginUser();
StpUtil.checkLogin();
if (SaRouter.isMatchCurrURI(loginPasswordProperties.getExcludes())) {
return;
}
CheckUtils.throwIf(loginUser.isPasswordExpired(), "密码已过期,请修改密码");
UserContext userContext = UserContextHolder.getContext();
CheckUtils.throwIf(userContext.isPasswordExpired(), "密码已过期,请修改密码");
}));
}
}

View File

@@ -17,8 +17,8 @@
package top.continew.admin.config.satoken;
import cn.dev33.satoken.stp.StpInterface;
import top.continew.admin.common.model.dto.LoginUser;
import top.continew.admin.common.util.helper.LoginHelper;
import top.continew.admin.common.context.UserContext;
import top.continew.admin.common.context.UserContextHolder;
import java.util.ArrayList;
import java.util.List;
@@ -33,13 +33,13 @@ public class SaTokenPermissionImpl implements StpInterface {
@Override
public List<String> getPermissionList(Object loginId, String loginType) {
LoginUser loginUser = LoginHelper.getLoginUser();
return new ArrayList<>(loginUser.getPermissions());
UserContext userContext = UserContextHolder.getContext();
return new ArrayList<>(userContext.getPermissions());
}
@Override
public List<String> getRoleList(Object loginId, String loginType) {
LoginUser loginUser = LoginHelper.getLoginUser();
return new ArrayList<>(loginUser.getRoleCodes());
UserContext userContext = UserContextHolder.getContext();
return new ArrayList<>(userContext.getRoleCodes());
}
}

View File

@@ -35,9 +35,9 @@ 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.common.constant.CacheConstants;
import top.continew.admin.common.model.dto.LoginUser;
import top.continew.admin.common.context.UserContext;
import top.continew.admin.common.context.UserContextHolder;
import top.continew.admin.common.util.SecureUtils;
import top.continew.admin.common.util.helper.LoginHelper;
import top.continew.admin.system.model.resp.UserDetailResp;
import top.continew.admin.system.service.UserService;
import top.continew.starter.cache.redisson.util.RedisUtils;
@@ -122,12 +122,12 @@ public class AuthController {
@Operation(summary = "获取用户信息", description = "获取登录用户信息")
@GetMapping("/user/info")
public UserInfoResp getUserInfo() {
LoginUser loginUser = LoginHelper.getLoginUser();
UserDetailResp userDetailResp = userService.get(loginUser.getId());
UserContext userContext = UserContextHolder.getContext();
UserDetailResp userDetailResp = userService.get(userContext.getId());
UserInfoResp userInfoResp = BeanUtil.copyProperties(userDetailResp, UserInfoResp.class);
userInfoResp.setPermissions(loginUser.getPermissions());
userInfoResp.setRoles(loginUser.getRoleCodes());
userInfoResp.setPwdExpired(loginUser.isPasswordExpired());
userInfoResp.setPermissions(userContext.getPermissions());
userInfoResp.setRoles(userContext.getRoleCodes());
userInfoResp.setPwdExpired(userContext.isPasswordExpired());
return userInfoResp;
}
@@ -135,6 +135,6 @@ public class AuthController {
@Operation(summary = "获取路由信息", description = "获取登录用户的路由信息")
@GetMapping("/route")
public List<RouteResp> listRoute() {
return loginService.buildRouteTree(LoginHelper.getUserId());
return loginService.buildRouteTree(UserContextHolder.getUserId());
}
}

View File

@@ -23,7 +23,7 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import top.continew.admin.common.util.helper.LoginHelper;
import top.continew.admin.common.context.UserContextHolder;
import top.continew.admin.system.model.query.MessageQuery;
import top.continew.admin.system.model.resp.MessageResp;
import top.continew.admin.system.model.resp.MessageUnreadResp;
@@ -53,7 +53,7 @@ public class MessageController {
@Operation(summary = "分页查询列表", description = "分页查询列表")
@GetMapping
public PageResp<MessageResp> page(MessageQuery query, @Validated PageQuery pageQuery) {
query.setUserId(LoginHelper.getUserId());
query.setUserId(UserContextHolder.getUserId());
return baseService.page(query, pageQuery);
}
@@ -76,6 +76,6 @@ public class MessageController {
@Parameter(name = "isDetail", description = "是否查询详情", example = "true", in = ParameterIn.QUERY)
@GetMapping("/unread")
public MessageUnreadResp countUnreadMessage(@RequestParam(required = false) Boolean detail) {
return messageUserService.countUnreadMessageByUserId(LoginHelper.getUserId(), detail);
return messageUserService.countUnreadMessageByUserId(UserContextHolder.getUserId(), detail);
}
}

View File

@@ -31,8 +31,8 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import top.continew.admin.common.constant.CacheConstants;
import top.continew.admin.common.context.UserContextHolder;
import top.continew.admin.common.util.SecureUtils;
import top.continew.admin.common.util.helper.LoginHelper;
import top.continew.admin.system.enums.SocialSourceEnum;
import top.continew.admin.system.model.entity.UserSocialDO;
import top.continew.admin.system.model.req.UserBasicInfoUpdateReq;
@@ -73,14 +73,14 @@ public class UserCenterController {
@PostMapping("/avatar")
public AvatarResp updateAvatar(@NotNull(message = "头像不能为空") MultipartFile avatarFile) throws IOException {
ValidationUtils.throwIf(avatarFile::isEmpty, "头像不能为空");
String newAvatar = userService.updateAvatar(avatarFile, LoginHelper.getUserId());
String newAvatar = userService.updateAvatar(avatarFile, UserContextHolder.getUserId());
return AvatarResp.builder().avatar(newAvatar).build();
}
@Operation(summary = "修改基础信息", description = "修改用户基础信息")
@PatchMapping("/basic/info")
public void updateBasicInfo(@Validated @RequestBody UserBasicInfoUpdateReq req) {
userService.updateBasicInfo(req, LoginHelper.getUserId());
userService.updateBasicInfo(req, UserContextHolder.getUserId());
}
@Operation(summary = "修改密码", description = "修改用户登录密码")
@@ -92,7 +92,7 @@ public class UserCenterController {
String rawNewPassword = ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(updateReq
.getNewPassword()));
ValidationUtils.throwIfNull(rawNewPassword, "新密码解密失败");
userService.updatePassword(rawOldPassword, rawNewPassword, LoginHelper.getUserId());
userService.updatePassword(rawOldPassword, rawNewPassword, UserContextHolder.getUserId());
}
@Operation(summary = "修改手机号", description = "修改手机号")
@@ -106,7 +106,7 @@ public class UserCenterController {
ValidationUtils.throwIfBlank(captcha, CAPTCHA_EXPIRED);
ValidationUtils.throwIfNotEqualIgnoreCase(updateReq.getCaptcha(), captcha, "验证码错误");
RedisUtils.delete(captchaKey);
userService.updatePhone(updateReq.getPhone(), rawOldPassword, LoginHelper.getUserId());
userService.updatePhone(updateReq.getPhone(), rawOldPassword, UserContextHolder.getUserId());
}
@Operation(summary = "修改邮箱", description = "修改用户邮箱")
@@ -120,13 +120,13 @@ public class UserCenterController {
ValidationUtils.throwIfBlank(captcha, CAPTCHA_EXPIRED);
ValidationUtils.throwIfNotEqualIgnoreCase(updateReq.getCaptcha(), captcha, "验证码错误");
RedisUtils.delete(captchaKey);
userService.updateEmail(updateReq.getEmail(), rawOldPassword, LoginHelper.getUserId());
userService.updateEmail(updateReq.getEmail(), rawOldPassword, UserContextHolder.getUserId());
}
@Operation(summary = "查询绑定的三方账号", description = "查询绑定的三方账号")
@GetMapping("/social")
public List<UserSocialBindResp> listSocialBind() {
List<UserSocialDO> userSocialList = userSocialService.listByUserId(LoginHelper.getUserId());
List<UserSocialDO> userSocialList = userSocialService.listByUserId(UserContextHolder.getUserId());
return userSocialList.stream().map(userSocial -> {
String source = userSocial.getSource();
UserSocialBindResp userSocialBind = new UserSocialBindResp();
@@ -144,13 +144,13 @@ public class UserCenterController {
AuthResponse<AuthUser> response = authRequest.login(callback);
ValidationUtils.throwIf(!response.ok(), response.getMsg());
AuthUser authUser = response.getData();
userSocialService.bind(authUser, LoginHelper.getUserId());
userSocialService.bind(authUser, UserContextHolder.getUserId());
}
@Operation(summary = "解绑三方账号", description = "解绑三方账号")
@Parameter(name = "source", description = "来源", example = "gitee", in = ParameterIn.PATH)
@DeleteMapping("/social/{source}")
public void unbindSocial(@PathVariable String source) {
userSocialService.deleteBySourceAndUserId(source, LoginHelper.getUserId());
userSocialService.deleteBySourceAndUserId(source, UserContextHolder.getUserId());
}
}