Commit cee7e5072034dba7597b2d03eff448e79a530172

Authored by YunaiV
1 parent 6aca4ae9

1.【修复】定时任务刷新本地缓存时,无租户上线文,导致查询报错

2. member 模块,统一使用 member 前缀
3. 修改 Spring Security logout 配置,支持多用户类型的退出
Showing 18 changed files with 63 additions and 55 deletions
http-client.env.json
1 1 {
2 2 "local": {
3 3 "baseUrl": "http://127.0.0.1:48080/api",
4   - "userServerUrl": "http://127.0.0.1:28080/api",
5 4 "token": "test1",
6 5  
7 6 "userApi": "http://127.0.0.1:48080/app-api",
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/dept/SysDeptMapper.java
... ... @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6 6 import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.dept.SysDeptListReqVO;
7 7 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.dept.SysDeptDO;
  8 +import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
8 9 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
9 10 import org.apache.ibatis.annotations.Mapper;
10 11  
... ... @@ -28,6 +29,7 @@ public interface SysDeptMapper extends BaseMapperX<SysDeptDO> {
28 29 return selectCount(SysDeptDO::getParentId, parentId);
29 30 }
30 31  
  32 + @InterceptorIgnore(tenantLine = "on") // 该方法忽略多租户。原因:该方法被异步 task 调用,此时获取不到租户编号
31 33 default boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) {
32 34 return selectOne(new LambdaQueryWrapper<SysDeptDO>().select(SysDeptDO::getId)
33 35 .gt(SysDeptDO::getUpdateTime, maxUpdateTime).last(SqlConstants.LIMIT1)) != null;
... ...
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java
1 1 package cn.iocoder.yudao.framework.security.config;
2 2  
  3 +import cn.hutool.core.util.StrUtil;
3 4 import cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider;
4 5 import cn.iocoder.yudao.framework.security.core.filter.JWTAuthenticationTokenFilter;
5 6 import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService;
... ... @@ -21,8 +22,10 @@ import org.springframework.security.web.AuthenticationEntryPoint;
21 22 import org.springframework.security.web.access.AccessDeniedHandler;
22 23 import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
23 24 import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
  25 +import org.springframework.security.web.util.matcher.RequestMatcher;
24 26  
25 27 import javax.annotation.Resource;
  28 +import javax.servlet.http.HttpServletRequest;
26 29  
27 30 /**
28 31 * 自定义的 Spring Security 配置适配器实现
... ... @@ -106,6 +109,7 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
106 109 */
107 110 @Override
108 111 protected void configure(HttpSecurity httpSecurity) throws Exception {
  112 + // 登出
109 113 httpSecurity
110 114 // 开启跨域
111 115 .cors().and()
... ... @@ -117,7 +121,9 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
117 121 // 一堆自定义的 Spring Security 处理器
118 122 .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
119 123 .accessDeniedHandler(accessDeniedHandler).and()
120   - .logout().logoutUrl(buildAdminApi("/logout")).logoutSuccessHandler(logoutSuccessHandler); // 登出
  124 + // 登出地址的配置
  125 + .logout().logoutSuccessHandler(logoutSuccessHandler).logoutRequestMatcher(request -> // 匹配多种用户类型的登出
  126 + StrUtil.equalsAny(request.getRequestURI(), buildAdminApi("/logout"), buildAppApi("/member/logout")));
121 127  
122 128 // 设置每个请求的权限 ①:全局共享规则
123 129 httpSecurity.authorizeRequests()
... ...
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java
... ... @@ -42,17 +42,26 @@ public class SecurityFrameworkUtils {
42 42 }
43 43  
44 44 /**
45   - * 获取当前用户
  45 + * 获得当前认证信息
46 46 *
47   - * @return 当前用户
  47 + * @return 认证信息
48 48 */
49   - @Nullable
50   - public static LoginUser getLoginUser() {
  49 + public static Authentication getAuthentication() {
51 50 SecurityContext context = SecurityContextHolder.getContext();
52 51 if (context == null) {
53 52 return null;
54 53 }
55   - Authentication authentication = context.getAuthentication();
  54 + return context.getAuthentication();
  55 + }
  56 +
  57 + /**
  58 + * 获取当前用户
  59 + *
  60 + * @return 当前用户
  61 + */
  62 + @Nullable
  63 + public static LoginUser getLoginUser() {
  64 + Authentication authentication = getAuthentication();
56 65 if (authentication == null) {
57 66 return null;
58 67 }
... ... @@ -88,16 +97,22 @@ public class SecurityFrameworkUtils {
88 97 * @param request 请求
89 98 */
90 99 public static void setLoginUser(LoginUser loginUser, HttpServletRequest request) {
91   - // 创建 UsernamePasswordAuthenticationToken 对象
92   - UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
93   - loginUser, null, loginUser.getAuthorities());
94   - authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
95   - // 设置到上下文
96   - SecurityContextHolder.getContext().setAuthentication(authenticationToken);
  100 + // 创建 Authentication,并设置到上下文
  101 + Authentication authentication = buildAuthentication(loginUser, request);
  102 + SecurityContextHolder.getContext().setAuthentication(authentication);
  103 +
97 104 // 额外设置到 request 中,用于 ApiAccessLogFilter 可以获取到用户编号;
98 105 // 原因是,Spring Security 的 Filter 在 ApiAccessLogFilter 后面,在它记录访问日志时,线上上下文已经没有用户编号等信息
99 106 WebFrameworkUtils.setLoginUserId(request, loginUser.getId());
100 107 WebFrameworkUtils.setLoginUserType(request, loginUser.getUserType());
101 108 }
102 109  
  110 + private static Authentication buildAuthentication(LoginUser loginUser, HttpServletRequest request) {
  111 + // 创建 UsernamePasswordAuthenticationToken 对象
  112 + UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
  113 + loginUser, null, loginUser.getAuthorities());
  114 + authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
  115 + return authenticationToken;
  116 + }
  117 +
103 118 }
... ...
yudao-module-bpm/yudao-module-bpm-activiti/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/config/BpmActivitiConfiguration.java
... ... @@ -10,17 +10,11 @@ import cn.iocoder.yudao.coreservice.modules.bpm.api.group.BpmUserGroupServiceApi
10 10 import cn.iocoder.yudao.coreservice.modules.system.service.dept.SysDeptCoreService;
11 11 import cn.iocoder.yudao.coreservice.modules.system.service.permission.SysPermissionCoreService;
12 12 import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService;
13   -import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmUserGroupService;
14   -import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService;
15   -import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
16   -import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
17 13 import org.activiti.api.runtime.shared.identity.UserGroupManager;
18   -import org.activiti.core.common.spring.identity.ActivitiUserGroupManagerImpl;
19 14 import org.activiti.spring.boot.ProcessEngineConfigurationConfigurer;
20 15 import org.springframework.context.ApplicationEventPublisher;
21 16 import org.springframework.context.annotation.Bean;
22 17 import org.springframework.context.annotation.Configuration;
23   -import org.springframework.security.core.userdetails.UserDetailsService;
24 18  
25 19 import java.util.Collections;
26 20 import java.util.List;
... ...
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.http
1 1 ### 请求 /login 接口 => 成功
2   -POST {{userApi}}/login
  2 +POST {{userApi}}/member/login
3 3 Content-Type: application/json
4 4 tenant-id: {{userTenentId}}
5 5  
... ... @@ -9,8 +9,9 @@ tenant-id: {{userTenentId}}
9 9 }
10 10  
11 11 ### 请求 /send-sms-code 接口 => 成功
12   -POST {{userServerUrl}}/send-sms-code
  12 +POST {{userApi}}/member/send-sms-code
13 13 Content-Type: application/json
  14 +tenant-id: {{userTenentId}}
14 15  
15 16 {
16 17 "mobile": "15601691399",
... ... @@ -18,8 +19,9 @@ Content-Type: application/json
18 19 }
19 20  
20 21 ### 请求 /sms-login 接口 => 成功
21   -POST {{userServerUrl}}/sms-login
  22 +POST {{userApi}}/member/sms-login
22 23 Content-Type: application/json
  24 +tenant-id: {{userTenentId}}
23 25  
24 26 {
25 27 "mobile": "15601691301",
... ... @@ -27,6 +29,7 @@ Content-Type: application/json
27 29 }
28 30  
29 31 ### 请求 /logout 接口 => 成功
30   -POST {{userServerUrl}}/logout
  32 +POST {{userApi}}/member/logout
31 33 Content-Type: application/json
32 34 Authorization: Bearer c1b76bdaf2c146c581caa4d7fd81ee66
  35 +tenant-id: {{userTenentId}}
... ...
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.java
... ... @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
5 5 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
6 6 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
7 7 import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
  8 +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
8 9 import cn.iocoder.yudao.module.member.controller.app.auth.vo.*;
9 10 import cn.iocoder.yudao.module.member.service.auth.AuthService;
10 11 import cn.iocoder.yudao.module.member.service.sms.SysSmsCodeService;
... ... @@ -13,6 +14,7 @@ import io.swagger.annotations.ApiImplicitParam;
13 14 import io.swagger.annotations.ApiImplicitParams;
14 15 import io.swagger.annotations.ApiOperation;
15 16 import lombok.extern.slf4j.Slf4j;
  17 +import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
16 18 import org.springframework.validation.annotation.Validated;
17 19 import org.springframework.web.bind.annotation.*;
18 20  
... ... @@ -26,7 +28,7 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti
26 28  
27 29 @Api(tags = "APP 端 - 认证")
28 30 @RestController
29   -@RequestMapping("/")
  31 +@RequestMapping("/member/")
30 32 @Validated
31 33 @Slf4j
32 34 public class AppAuthController {
... ... @@ -39,6 +41,9 @@ public class AppAuthController {
39 41 @Resource
40 42 private SysSocialCoreService socialService;
41 43  
  44 + @Resource
  45 + private LogoutSuccessHandler logoutSuccessHandler;
  46 +
42 47 @PostMapping("/login")
43 48 @ApiOperation("使用手机 + 密码登录")
44 49 @OperateLog(enable = false) // 避免 Post 请求被记录操作日志
... ...
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/weixin/controller/mp/WxMpController.http renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/weixin/AppWxMpController.http
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/weixin/controller/mp/WxMpController.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/weixin/AppWxMpController.java
1   -package cn.iocoder.yudao.userserver.modules.weixin.controller.mp;
  1 +package cn.iocoder.yudao.module.member.controller.app.weixin;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
4 4 import io.swagger.annotations.Api;
... ... @@ -19,10 +19,10 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
19 19  
20 20 @Api(tags = "微信公众号")
21 21 @RestController
22   -@RequestMapping("/wx/mp")
  22 +@RequestMapping("/member/wx-mp")
23 23 @Validated
24 24 @Slf4j
25   -public class WxMpController {
  25 +public class AppWxMpController {
26 26  
27 27 @Resource
28 28 private WxMpService mpService;
... ...
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/UserDO.java
... ... @@ -16,7 +16,7 @@ import java.util.Date;
16 16 *
17 17 * @author 芋道源码
18 18 */
19   -@TableName(value = "mbr_user", autoResultMap = true)
  19 +@TableName(value = "member_user", autoResultMap = true)
20 20 @Data
21 21 @EqualsAndHashCode(callSuper = true)
22 22 @Builder
... ...
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/dal/package-info.java
... ... @@ -4,6 +4,6 @@
4 4 * 2. redis:Redis 的 CRUD 操作
5 5 * 3. mysql:MySQL 的 CRUD 操作
6 6 *
7   - * 其中,MySQL 的表以 mbr_ 作为前缀
  7 + * 其中,MySQL 的表以 member_ 作为前缀
8 8 */
9 9 package cn.iocoder.yudao.module.member.dal;
... ...
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/package-info.java
  1 +/**
  2 + * member 模块,我们放会员业务。
  3 + * 例如说:会员中心等等
  4 + *
  5 + * 1. Controller URL:以 /member/ 开头,避免和其它 Module 冲突
  6 + * 2. DataObject 表名:以 member_ 开头,方便在数据库中区分
  7 + */
1 8 package cn.iocoder.yudao.module.member;
... ...
yudao-module-member/yudao-module-member-impl/src/test/resources/sql/clean.sql
1 1 -- mbr 开头的 DB
2   -DELETE FROM "mbr_user";
3 2 \ No newline at end of file
  3 +DELETE FROM "member_user";
... ...
yudao-module-member/yudao-module-member-impl/src/test/resources/sql/create_tables.sql
1 1 -- mbr 开头的 DB
2   -CREATE TABLE IF NOT EXISTS "mbr_user" (
  2 +CREATE TABLE IF NOT EXISTS "member_user" (
3 3 "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY COMMENT '编号',
4 4 "nickname" varchar(30) NOT NULL DEFAULT '' COMMENT '用户昵称',
5 5 "avatar" varchar(255) NOT NULL DEFAULT '' COMMENT '头像',
... ...
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/UserServerApplication.java deleted
1   -package cn.iocoder.yudao.userserver;
2   -
3   -import org.springframework.boot.SpringApplication;
4   -import org.springframework.boot.autoconfigure.SpringBootApplication;
5   -
6   -@SuppressWarnings("SpringComponentScan") // 忽略 IDEA 无法识别 ${yudao.info.base-package} 和 ${yudao.core-service.base-package}
7   -@SpringBootApplication(scanBasePackages = {"${yudao.info.base-package}", "${yudao.core-service.base-package}"})
8   -public class UserServerApplication {
9   -
10   - public static void main(String[] args) {
11   - SpringApplication.run(UserServerApplication.class, args);
12   - }
13   -
14   -}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/weixin/package-info.java deleted
1   -/**
2   - * weixin 包下,我们放通用业务,支撑上层的核心业务。
3   - * 例如说:用户、部门、权限、数据字典等等
4   - *
5   - * 缩写:wx
6   - */
7   -package cn.iocoder.yudao.userserver.modules.weixin;
yudao-user-server/src/main/resources/application.yaml
... ... @@ -37,8 +37,6 @@ mybatis-plus:
37 37 mapper-locations: classpath*:mapper/*.xml
38 38 type-aliases-package: ${yudao.info.base-package}.modules.*.dal.dataobject, ${yudao.core-service.base-package}.modules.*.dal.dataobject
39 39  
40   -
41   -
42 40 --- #################### 芋道相关配置 ####################
43 41  
44 42 yudao:
... ... @@ -67,5 +65,4 @@ yudao:
67 65 - cn.iocoder.yudao.userserver.modules.member.enums.MbrErrorCodeConstants
68 66 - cn.iocoder.yudao.userserver.modules.system.enums.SysErrorCodeConstants
69 67  
70   -
71 68 debug: false
... ...
更新日志.md
... ... @@ -23,6 +23,7 @@
23 23 ### 🐞 Bug Fixes
24 24  
25 25 *【修复】用户无权限访问 指定 API 时,未返回 FORBIDDEN 结果码
  26 +*【修复】定时任务刷新本地缓存时,无租户上线文,导致查询报错
26 27  
27 28 ### 🔨 Dependency Upgrades
28 29  
... ...