Commit 6aca4ae9fd3af1861a33fbdd4d014571fa000f0f

Authored by YunaiV
2 parents 36d01371 e9efff70

Merge branch 'feature/multi-module' of https://gitee.com/zhijiantianya/ruoyi-vue…

…-pro into feature/flowable

 Conflicts:
	pom.xml
	yudao-module-bpm/yudao-module-bpm-activiti/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/config/BpmActivitiConfiguration.java
Showing 119 changed files with 1265 additions and 959 deletions

Too many changes.

To preserve performance only 100 of 119 files are displayed.

http-client.env.json
@@ -2,6 +2,10 @@ @@ -2,6 +2,10 @@
2 "local": { 2 "local": {
3 "baseUrl": "http://127.0.0.1:48080/api", 3 "baseUrl": "http://127.0.0.1:48080/api",
4 "userServerUrl": "http://127.0.0.1:28080/api", 4 "userServerUrl": "http://127.0.0.1:28080/api",
5 - "token": "test1" 5 + "token": "test1",
  6 +
  7 + "userApi": "http://127.0.0.1:48080/app-api",
  8 + "userToken": "test1",
  9 + "userTenentId": "1"
6 } 10 }
7 } 11 }
@@ -13,6 +13,7 @@ @@ -13,6 +13,7 @@
13 <module>yudao-admin-server</module> 13 <module>yudao-admin-server</module>
14 <module>yudao-user-server</module> 14 <module>yudao-user-server</module>
15 <module>yudao-core-service</module> 15 <module>yudao-core-service</module>
  16 + <module>yudao-module-member</module>
16 <module>yudao-module-bpm</module> 17 <module>yudao-module-bpm</module>
17 </modules> 18 </modules>
18 19
@@ -21,13 +22,14 @@ @@ -21,13 +22,14 @@
21 <url>https://github.com/YunaiV/ruoyi-vue-pro</url> 22 <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
22 23
23 <properties> 24 <properties>
24 - <revision>1.3.0-snapshot</revision> 25 + <revision>1.4.0-snapshot</revision>
25 <!-- Maven 相关 --> 26 <!-- Maven 相关 -->
26 <java.version>1.8</java.version> 27 <java.version>1.8</java.version>
27 <maven.compiler.source>${java.version}</maven.compiler.source> 28 <maven.compiler.source>${java.version}</maven.compiler.source>
28 <maven.compiler.target>${java.version}</maven.compiler.target> 29 <maven.compiler.target>${java.version}</maven.compiler.target>
29 <maven-surefire-plugin.version>3.0.0-M5</maven-surefire-plugin.version> 30 <maven-surefire-plugin.version>3.0.0-M5</maven-surefire-plugin.version>
30 <maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version> 31 <maven-compiler-plugin.version>3.8.0</maven-compiler-plugin.version>
  32 + <!-- 看看咋放到 bom 里 -->
31 <lombok.version>1.18.20</lombok.version> 33 <lombok.version>1.18.20</lombok.version>
32 <mapstruct.version>1.4.1.Final</mapstruct.version> 34 <mapstruct.version>1.4.1.Final</mapstruct.version>
33 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 35 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@@ -55,6 +57,7 @@ @@ -55,6 +57,7 @@
55 <artifactId>maven-surefire-plugin</artifactId> 57 <artifactId>maven-surefire-plugin</artifactId>
56 <version>${maven-surefire-plugin.version}</version> 58 <version>${maven-surefire-plugin.version}</version>
57 </plugin> 59 </plugin>
  60 + <!-- TODO 看看咋放到 bom 里 -->
58 <plugin> 61 <plugin>
59 <groupId>org.apache.maven.plugins</groupId> 62 <groupId>org.apache.maven.plugins</groupId>
60 <artifactId>maven-compiler-plugin</artifactId> 63 <artifactId>maven-compiler-plugin</artifactId>
yudao-admin-server/pom.xml
@@ -13,10 +13,21 @@ @@ -13,10 +13,21 @@
13 <packaging>jar</packaging> 13 <packaging>jar</packaging>
14 14
15 <name>yudao-admin-server</name> 15 <name>yudao-admin-server</name>
16 - <description>管理后台 Server,提供其 API 接口</description> 16 + <description>
  17 + 后端 Server 的主项目,通过引入需要 yudao-module-xxx 的依赖,
  18 + 从而实现提供 RESTful API 给 yudao-ui-admin、yudao-ui-user 等前端项目。
  19 + 本质上来说,它就是个空壳(容器)!
  20 + </description>
17 <url>https://github.com/YunaiV/ruoyi-vue-pro</url> 21 <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
18 22
19 <dependencies> 23 <dependencies>
  24 + <!-- TODO 芋艿:多模块 -->
  25 + <dependency>
  26 + <groupId>cn.iocoder.boot</groupId>
  27 + <artifactId>yudao-module-member-impl</artifactId>
  28 + <version>${revision}</version>
  29 + </dependency>
  30 +
20 <!-- 业务组件 --> 31 <!-- 业务组件 -->
21 <dependency> 32 <dependency>
22 <groupId>cn.iocoder.boot</groupId> 33 <groupId>cn.iocoder.boot</groupId>
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/AdminServerApplication.java
@@ -4,7 +4,8 @@ import org.springframework.boot.SpringApplication; @@ -4,7 +4,8 @@ import org.springframework.boot.SpringApplication;
4 import org.springframework.boot.autoconfigure.SpringBootApplication; 4 import org.springframework.boot.autoconfigure.SpringBootApplication;
5 5
6 @SuppressWarnings("SpringComponentScan") // 忽略 IDEA 无法识别 ${yudao.info.base-package} 和 ${yudao.core-service.base-package} 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}"}) 7 +@SpringBootApplication(scanBasePackages = {"${yudao.info.base-package}", "${yudao.core-service.base-package}",
  8 + "${yudao.info.member-package}"}) // TODO 芋艿:重构
8 public class AdminServerApplication { 9 public class AdminServerApplication {
9 10
10 public static void main(String[] args) { 11 public static void main(String[] args) {
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/security/SecurityConfiguration.java
@@ -23,19 +23,28 @@ public class SecurityConfiguration { @@ -23,19 +23,28 @@ public class SecurityConfiguration {
23 public Customizer<ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry> authorizeRequestsCustomizer() { 23 public Customizer<ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry> authorizeRequestsCustomizer() {
24 return registry -> { 24 return registry -> {
25 // 验证码的接口 25 // 验证码的接口
26 - registry.antMatchers(api("/system/captcha/**")).anonymous(); 26 + registry.antMatchers(buildAdminApi("/system/captcha/**")).anonymous();
27 // 获得租户编号的接口 27 // 获得租户编号的接口
28 - registry.antMatchers(api("/system/tenant/get-id-by-name")).anonymous(); 28 + registry.antMatchers(buildAdminApi("/system/tenant/get-id-by-name")).anonymous();
29 // Spring Boot Admin Server 的安全配置 29 // Spring Boot Admin Server 的安全配置
30 registry.antMatchers(adminSeverContextPath).anonymous() 30 registry.antMatchers(adminSeverContextPath).anonymous()
31 .antMatchers(adminSeverContextPath + "/**").anonymous(); 31 .antMatchers(adminSeverContextPath + "/**").anonymous();
32 // 短信回调 API 32 // 短信回调 API
33 - registry.antMatchers(api("/system/sms/callback/**")).anonymous(); 33 + registry.antMatchers(buildAdminApi("/system/sms/callback/**")).anonymous();
  34 +
  35 + // 设置 App API 无需认证
  36 + registry.antMatchers(buildAppApi("/**")).permitAll();
34 }; 37 };
35 } 38 }
36 39
37 - private String api(String url) {  
38 - return webProperties.getApiPrefix() + url; 40 + private String buildAdminApi(String url) {
  41 + // TODO 芋艿:多模块
  42 + return webProperties.getAdminApi().getPrefix() + url;
  43 + }
  44 +
  45 + private String buildAppApi(String url) {
  46 + // TODO 芋艿:多模块
  47 + return webProperties.getAppApi().getPrefix() + url;
39 } 48 }
40 49
41 } 50 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysAuthServiceImpl.java
@@ -26,6 +26,7 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; @@ -26,6 +26,7 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
26 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; 26 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
27 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; 27 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
28 import cn.iocoder.yudao.framework.security.core.LoginUser; 28 import cn.iocoder.yudao.framework.security.core.LoginUser;
  29 +import cn.iocoder.yudao.framework.security.core.authentication.MultiUsernamePasswordAuthenticationToken;
29 import lombok.extern.slf4j.Slf4j; 30 import lombok.extern.slf4j.Slf4j;
30 import me.zhyd.oauth.model.AuthUser; 31 import me.zhyd.oauth.model.AuthUser;
31 import org.springframework.context.annotation.Lazy; 32 import org.springframework.context.annotation.Lazy;
@@ -60,8 +61,6 @@ import static java.util.Collections.singleton; @@ -60,8 +61,6 @@ import static java.util.Collections.singleton;
60 @Slf4j 61 @Slf4j
61 public class SysAuthServiceImpl implements SysAuthService { 62 public class SysAuthServiceImpl implements SysAuthService {
62 63
63 - private static final UserTypeEnum USER_TYPE_ENUM = UserTypeEnum.ADMIN;  
64 -  
65 @Resource 64 @Resource
66 @Lazy // 延迟加载,因为存在相互依赖的问题 65 @Lazy // 延迟加载,因为存在相互依赖的问题
67 private AuthenticationManager authenticationManager; 66 private AuthenticationManager authenticationManager;
@@ -83,7 +82,6 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -83,7 +82,6 @@ public class SysAuthServiceImpl implements SysAuthService {
83 @Resource 82 @Resource
84 private SysSocialCoreService socialService; 83 private SysSocialCoreService socialService;
85 84
86 -  
87 @Override 85 @Override
88 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { 86 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
89 // 获取 username 对应的 SysUserDO 87 // 获取 username 对应的 SysUserDO
@@ -157,7 +155,8 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -157,7 +155,8 @@ public class SysAuthServiceImpl implements SysAuthService {
157 try { 155 try {
158 // 调用 Spring Security 的 AuthenticationManager#authenticate(...) 方法,使用账号密码进行认证 156 // 调用 Spring Security 的 AuthenticationManager#authenticate(...) 方法,使用账号密码进行认证
159 // 在其内部,会调用到 loadUserByUsername 方法,获取 User 信息 157 // 在其内部,会调用到 loadUserByUsername 方法,获取 User 信息
160 - authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password)); 158 + authentication = authenticationManager.authenticate(new MultiUsernamePasswordAuthenticationToken(
  159 + username, password, getUserType()));
161 // org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(username); 160 // org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId(username);
162 } catch (BadCredentialsException badCredentialsException) { 161 } catch (BadCredentialsException badCredentialsException) {
163 this.createLoginLog(username, logTypeEnum, SysLoginResultEnum.BAD_CREDENTIALS); 162 this.createLoginLog(username, logTypeEnum, SysLoginResultEnum.BAD_CREDENTIALS);
@@ -216,7 +215,7 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -216,7 +215,7 @@ public class SysAuthServiceImpl implements SysAuthService {
216 215
217 // 如果未绑定 SysSocialUserDO 用户,则无法自动登录,进行报错 216 // 如果未绑定 SysSocialUserDO 用户,则无法自动登录,进行报错
218 String unionId = socialService.getAuthUserUnionId(authUser); 217 String unionId = socialService.getAuthUserUnionId(authUser);
219 - List<SysSocialUserDO> socialUsers = socialService.getAllSocialUserList(reqVO.getType(), unionId, USER_TYPE_ENUM); 218 + List<SysSocialUserDO> socialUsers = socialService.getAllSocialUserList(reqVO.getType(), unionId, getUserType());
220 if (CollUtil.isEmpty(socialUsers)) { 219 if (CollUtil.isEmpty(socialUsers)) {
221 throw exception(AUTH_THIRD_LOGIN_NOT_BIND); 220 throw exception(AUTH_THIRD_LOGIN_NOT_BIND);
222 } 221 }
@@ -232,7 +231,7 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -232,7 +231,7 @@ public class SysAuthServiceImpl implements SysAuthService {
232 LoginUser loginUser = this.buildLoginUser(user); 231 LoginUser loginUser = this.buildLoginUser(user);
233 232
234 // 绑定社交用户(更新) 233 // 绑定社交用户(更新)
235 - socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, USER_TYPE_ENUM); 234 + socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, getUserType());
236 235
237 // 缓存登录用户到 Redis 中,返回 sessionId 编号 236 // 缓存登录用户到 Redis 中,返回 sessionId 编号
238 return userSessionCoreService.createUserSession(loginUser, userIp, userAgent); 237 return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
@@ -248,7 +247,7 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -248,7 +247,7 @@ public class SysAuthServiceImpl implements SysAuthService {
248 LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword()); 247 LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword());
249 248
250 // 绑定社交用户(新增) 249 // 绑定社交用户(新增)
251 - socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, USER_TYPE_ENUM); 250 + socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, getUserType());
252 251
253 // 缓存登录用户到 Redis 中,返回 sessionId 编号 252 // 缓存登录用户到 Redis 中,返回 sessionId 编号
254 return userSessionCoreService.createUserSession(loginUser, userIp, userAgent); 253 return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
@@ -261,7 +260,7 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -261,7 +260,7 @@ public class SysAuthServiceImpl implements SysAuthService {
261 Assert.notNull(authUser, "授权用户不为空"); 260 Assert.notNull(authUser, "授权用户不为空");
262 261
263 // 绑定社交用户(新增) 262 // 绑定社交用户(新增)
264 - socialService.bindSocialUser(userId, reqVO.getType(), authUser, USER_TYPE_ENUM); 263 + socialService.bindSocialUser(userId, reqVO.getType(), authUser, getUserType());
265 } 264 }
266 265
267 @Override 266 @Override
@@ -277,12 +276,17 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -277,12 +276,17 @@ public class SysAuthServiceImpl implements SysAuthService {
277 this.createLogoutLog(loginUser.getId(), loginUser.getUsername()); 276 this.createLogoutLog(loginUser.getId(), loginUser.getUsername());
278 } 277 }
279 278
  279 + @Override
  280 + public UserTypeEnum getUserType() {
  281 + return UserTypeEnum.ADMIN;
  282 + }
  283 +
280 private void createLogoutLog(Long userId, String username) { 284 private void createLogoutLog(Long userId, String username) {
281 SysLoginLogCreateReqDTO reqDTO = new SysLoginLogCreateReqDTO(); 285 SysLoginLogCreateReqDTO reqDTO = new SysLoginLogCreateReqDTO();
282 reqDTO.setLogType(SysLoginLogTypeEnum.LOGOUT_SELF.getType()); 286 reqDTO.setLogType(SysLoginLogTypeEnum.LOGOUT_SELF.getType());
283 reqDTO.setTraceId(TracerUtils.getTraceId()); 287 reqDTO.setTraceId(TracerUtils.getTraceId());
284 reqDTO.setUserId(userId); 288 reqDTO.setUserId(userId);
285 - reqDTO.setUserType(USER_TYPE_ENUM.getValue()); 289 + reqDTO.setUserType(getUserType().getValue());
286 reqDTO.setUsername(username); 290 reqDTO.setUsername(username);
287 reqDTO.setUserAgent(ServletUtils.getUserAgent()); 291 reqDTO.setUserAgent(ServletUtils.getUserAgent());
288 reqDTO.setUserIp(ServletUtils.getClientIP()); 292 reqDTO.setUserIp(ServletUtils.getClientIP());
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/user/impl/SysUserServiceImpl.java
@@ -24,6 +24,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -24,6 +24,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
24 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 24 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
25 import com.google.common.annotations.VisibleForTesting; 25 import com.google.common.annotations.VisibleForTesting;
26 import lombok.extern.slf4j.Slf4j; 26 import lombok.extern.slf4j.Slf4j;
  27 +import org.springframework.beans.factory.annotation.Autowired;
27 import org.springframework.beans.factory.annotation.Value; 28 import org.springframework.beans.factory.annotation.Value;
28 import org.springframework.security.crypto.password.PasswordEncoder; 29 import org.springframework.security.crypto.password.PasswordEncoder;
29 import org.springframework.stereotype.Service; 30 import org.springframework.stereotype.Service;
@@ -48,7 +49,7 @@ public class SysUserServiceImpl implements SysUserService { @@ -48,7 +49,7 @@ public class SysUserServiceImpl implements SysUserService {
48 @Value("${sys.user.init-password:yudaoyuanma}") 49 @Value("${sys.user.init-password:yudaoyuanma}")
49 private String userInitPassword; 50 private String userInitPassword;
50 51
51 - @Resource 52 + @Resource(name = "sysUserMapper") // userMapper 存在重名
52 private SysUserMapper userMapper; 53 private SysUserMapper userMapper;
53 54
54 @Resource 55 @Resource
yudao-admin-server/src/main/resources/application-local.yaml
@@ -55,6 +55,19 @@ spring: @@ -55,6 +55,19 @@ spring:
55 username: root 55 username: root
56 password: 123456 56 password: 123456
57 57
  58 + activiti:
  59 + #1.false:默认值,activiti启动时,对比数据库表中保存的版本,如果不匹配。将抛出异常
  60 + #2.true:启动时会对数据库中所有表进行更新操作,如果表存在,不做处理,反之,自动创建表
  61 + #3.create_drop:启动时自动创建表,关闭时自动删除表
  62 + #4.drop_create:启动时,删除旧表,再创建新表
  63 + database-schema-update: true
  64 + #activiti7默认不生成历史信息表,需手动设置开启
  65 + db-history-used: true
  66 + check-process-definitions: true
  67 + #full:保存历史数据的最高级别,可保存全部流程相关细节,包括流程流转各节点参数
  68 + history-level: full
  69 +
  70 +
58 # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 71 # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
59 redis: 72 redis:
60 host: 127.0.0.1 # 地址 73 host: 127.0.0.1 # 地址
@@ -161,6 +174,18 @@ logging: @@ -161,6 +174,18 @@ logging:
161 cn.iocoder.yudao.coreservice.modules.system.dal.mysql: debug 174 cn.iocoder.yudao.coreservice.modules.system.dal.mysql: debug
162 cn.iocoder.yudao.coreservice.modules.tool.dal.mysql: debug 175 cn.iocoder.yudao.coreservice.modules.tool.dal.mysql: debug
163 176
  177 +--- #################### 微信公众号相关配置 ####################
  178 +wx: # 参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-mp-spring-boot-starter/README.md 文档
  179 + mp:
  180 + # 公众号配置(必填)
  181 + app-id: wx041349c6f39b268b
  182 + secret: 5abee519483bc9f8cb37ce280e814bd0
  183 + # 存储配置,解决 AccessToken 的跨节点的共享
  184 + config-storage:
  185 + type: RedisTemplate # 采用 RedisTemplate 操作 Redis,会自动从 Spring 中获取
  186 + key-prefix: wx # Redis Key 的前缀 TODO 芋艿:解决下 Redis key 管理的配置
  187 + http-client-type: HttpClient # 采用 HttpClient 请求微信公众号平台
  188 +
164 --- #################### 芋道相关配置 #################### 189 --- #################### 芋道相关配置 ####################
165 190
166 # 芋道配置项,设置当前项目所有自定义的配置 191 # 芋道配置项,设置当前项目所有自定义的配置
yudao-admin-server/src/main/resources/application.yaml
@@ -48,11 +48,17 @@ yudao: @@ -48,11 +48,17 @@ yudao:
48 info: 48 info:
49 version: 1.0.0 49 version: 1.0.0
50 base-package: cn.iocoder.yudao.adminserver 50 base-package: cn.iocoder.yudao.adminserver
  51 + member-package: cn.iocoder.yudao.module.member
51 core-service: 52 core-service:
52 base-package: cn.iocoder.yudao.coreservice 53 base-package: cn.iocoder.yudao.coreservice
53 web: 54 web:
54 - api-prefix: /api  
55 - controller-package: ${yudao.info.base-package} 55 + admin-api:
  56 + prefix: /api
  57 + controller: ${yudao.info.base-package}
  58 + app-api:
  59 + prefix: /app-api
  60 + controller: cn.iocoder.yudao.module.member.controller.app
  61 +
56 swagger: 62 swagger:
57 title: 管理后台 63 title: 管理后台
58 description: 提供管理员管理的所有功能 64 description: 提供管理员管理的所有功能
@@ -72,7 +78,13 @@ yudao: @@ -72,7 +78,13 @@ yudao:
72 - cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants 78 - cn.iocoder.yudao.adminserver.modules.bpm.enums.BpmErrorCodeConstants
73 tenant: # 多租户相关配置项 79 tenant: # 多租户相关配置项
74 tables: # 配置需要开启多租户的表;如果实体已经继承 TenantBaseDO 类,则无需重复配置 80 tables: # 配置需要开启多租户的表;如果实体已经继承 TenantBaseDO 类,则无需重复配置
75 - url: 81 + url: ## TODO 芋艿:迁移到 web 配置项下,
76 admin-ui: http://dashboard.yudao.iocoder.cn # Admin 管理后台 UI 的地址 82 admin-ui: http://dashboard.yudao.iocoder.cn # Admin 管理后台 UI 的地址
  83 + sms-code: # 短信验证码相关的配置项
  84 + expire-times: 10m
  85 + send-frequency: 1m
  86 + send-maximum-quantity-per-day: 10
  87 + begin-code: 9999 # 这里配置 9999 的原因是,测试方便。
  88 + end-code: 9999 # 这里配置 9999 的原因是,测试方便。
77 89
78 debug: false 90 debug: false
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/service/file/InfFileCoreService.java
@@ -9,7 +9,6 @@ import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO; @@ -9,7 +9,6 @@ import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file.InfFileDO;
9 */ 9 */
10 public interface InfFileCoreService { 10 public interface InfFileCoreService {
11 11
12 -  
13 /** 12 /**
14 * 保存文件,并返回文件的访问路径 13 * 保存文件,并返回文件的访问路径
15 * 14 *
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/dal/mysql/user/MbrUserCoreMapper.java deleted
1 -package cn.iocoder.yudao.coreservice.modules.member.dal.mysql.user;  
2 -  
3 -import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO;  
4 -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;  
5 -import org.apache.ibatis.annotations.Mapper;  
6 -  
7 -@Mapper  
8 -public interface MbrUserCoreMapper extends BaseMapperX<MbrUserDO> {  
9 -  
10 -}  
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/package-info.java deleted
1 -/**  
2 - * member 包下,我们放会员业务.  
3 - * 例如说:会员中心等等  
4 - *  
5 - * 缩写:mbr  
6 - */  
7 -package cn.iocoder.yudao.coreservice.modules.member;  
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/service/user/MbrUserCoreService.java deleted
1 -package cn.iocoder.yudao.coreservice.modules.member.service.user;  
2 -  
3 -import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO;  
4 -  
5 -/**  
6 - * 前台用户 Core Service 接口  
7 - *  
8 - * @author 芋道源码  
9 - */  
10 -public interface MbrUserCoreService {  
11 - /**  
12 - * 通过用户 ID 查询用户  
13 - *  
14 - * @param id 用户ID  
15 - * @return 用户对象信息  
16 - */  
17 - MbrUserDO getUser(Long id);  
18 -  
19 -}  
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/service/user/impl/MbrUserCoreServiceImpl.java deleted
1 -package cn.iocoder.yudao.coreservice.modules.member.service.user.impl;  
2 -  
3 -import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO;  
4 -import cn.iocoder.yudao.coreservice.modules.member.dal.mysql.user.MbrUserCoreMapper;  
5 -import cn.iocoder.yudao.coreservice.modules.member.service.user.MbrUserCoreService;  
6 -import lombok.extern.slf4j.Slf4j;  
7 -import org.springframework.stereotype.Service;  
8 -  
9 -import javax.annotation.Resource;  
10 -  
11 -/**  
12 - * User Core Service 实现类  
13 - *  
14 - * @author 芋道源码  
15 - */  
16 -@Service  
17 -@Slf4j  
18 -public class MbrUserCoreServiceImpl implements MbrUserCoreService {  
19 -  
20 - @Resource  
21 - private MbrUserCoreMapper userCoreMapper;  
22 -  
23 - @Override  
24 - public MbrUserDO getUser(Long id) {  
25 - return userCoreMapper.selectById(id);  
26 - }  
27 -  
28 -}  
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/service/sms/impl/SysSmsCoreServiceImpl.java
@@ -2,8 +2,6 @@ package cn.iocoder.yudao.coreservice.modules.system.service.sms.impl; @@ -2,8 +2,6 @@ package cn.iocoder.yudao.coreservice.modules.system.service.sms.impl;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.util.StrUtil; 4 import cn.hutool.core.util.StrUtil;
5 -import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO;  
6 -import cn.iocoder.yudao.coreservice.modules.member.service.user.MbrUserCoreService;  
7 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsTemplateDO; 5 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.sms.SysSmsTemplateDO;
8 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO; 6 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
9 import cn.iocoder.yudao.coreservice.modules.system.mq.message.sms.SysSmsSendMessage; 7 import cn.iocoder.yudao.coreservice.modules.system.mq.message.sms.SysSmsSendMessage;
@@ -43,8 +41,6 @@ public class SysSmsCoreServiceImpl implements SysSmsCoreService { @@ -43,8 +41,6 @@ public class SysSmsCoreServiceImpl implements SysSmsCoreService {
43 @Resource 41 @Resource
44 private SysUserCoreService sysUserCoreService; 42 private SysUserCoreService sysUserCoreService;
45 @Resource 43 @Resource
46 - private MbrUserCoreService mbrUserCoreService;  
47 - @Resource  
48 private SysSmsTemplateCoreService smsTemplateCoreService; 44 private SysSmsTemplateCoreService smsTemplateCoreService;
49 @Resource 45 @Resource
50 private SysSmsLogCoreService smsLogCoreService; 46 private SysSmsLogCoreService smsLogCoreService;
@@ -72,10 +68,11 @@ public class SysSmsCoreServiceImpl implements SysSmsCoreService { @@ -72,10 +68,11 @@ public class SysSmsCoreServiceImpl implements SysSmsCoreService {
72 public Long sendSingleSmsToMember(String mobile, Long userId, String templateCode, Map<String, Object> templateParams) { 68 public Long sendSingleSmsToMember(String mobile, Long userId, String templateCode, Map<String, Object> templateParams) {
73 // 如果 mobile 为空,则加载用户编号对应的手机号 69 // 如果 mobile 为空,则加载用户编号对应的手机号
74 if (StrUtil.isEmpty(mobile)) { 70 if (StrUtil.isEmpty(mobile)) {
75 - MbrUserDO user = mbrUserCoreService.getUser(userId);  
76 - if (user != null) {  
77 - mobile = user.getMobile();  
78 - } 71 +// MbrUserDO user = mbrUserCoreService.getUser(userId);
  72 +// if (user != null) {
  73 +// mobile = user.getMobile();
  74 +// }
  75 + // TODO 芋艿:重构
79 } 76 }
80 // 执行发送 77 // 执行发送
81 return this.sendSingleSms(mobile, userId, UserTypeEnum.MEMBER.getValue(), templateCode, templateParams); 78 return this.sendSingleSms(mobile, userId, UserTypeEnum.MEMBER.getValue(), templateCode, templateParams);
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/tool/package-info.java deleted
1 -/**  
2 - * tool 包下,我们放研发工具,提升研发效率与质量。  
3 - * 例如说:代码生成器、接口文档等等  
4 - *  
5 - * 缩写:tool  
6 - */  
7 -package cn.iocoder.yudao.coreservice.modules.tool;  
yudao-dependencies/pom.xml
@@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
14 <url>https://github.com/YunaiV/ruoyi-vue-pro</url> 14 <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
15 15
16 <properties> 16 <properties>
17 - <revision>1.3.0-snapshot</revision> 17 + <revision>1.4.0-snapshot</revision>
18 <!-- 统一依赖管理 --> 18 <!-- 统一依赖管理 -->
19 <spring.boot.version>2.4.12</spring.boot.version> 19 <spring.boot.version>2.4.12</spring.boot.version>
20 <!-- Web 相关 --> 20 <!-- Web 相关 -->
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/enums/UserTypeEnum.java
1 package cn.iocoder.yudao.framework.common.enums; 1 package cn.iocoder.yudao.framework.common.enums;
2 2
  3 +import cn.hutool.core.lang.Matcher;
  4 +import cn.hutool.core.util.ArrayUtil;
3 import lombok.AllArgsConstructor; 5 import lombok.AllArgsConstructor;
4 import lombok.Getter; 6 import lombok.Getter;
5 7
@@ -22,4 +24,8 @@ public enum UserTypeEnum { @@ -22,4 +24,8 @@ public enum UserTypeEnum {
22 */ 24 */
23 private final String name; 25 private final String name;
24 26
  27 + public static UserTypeEnum valueOf(Integer value) {
  28 + return ArrayUtil.firstMatch(userType -> userType.getValue().equals(value), UserTypeEnum.values());
  29 + }
  30 +
25 } 31 }
yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/aop/OperateLogAspect.java
@@ -149,6 +149,7 @@ public class OperateLogAspect { @@ -149,6 +149,7 @@ public class OperateLogAspect {
149 149
150 private static void fillUserFields(OperateLogCreateReqDTO operateLogDTO) { 150 private static void fillUserFields(OperateLogCreateReqDTO operateLogDTO) {
151 operateLogDTO.setUserId(WebFrameworkUtils.getLoginUserId()); 151 operateLogDTO.setUserId(WebFrameworkUtils.getLoginUserId());
  152 + operateLogDTO.setUserType(WebFrameworkUtils.getLoginUserType());
152 } 153 }
153 154
154 private static void fillModuleFields(OperateLogCreateReqDTO operateLogDTO, 155 private static void fillModuleFields(OperateLogCreateReqDTO operateLogDTO,
yudao-framework/yudao-spring-boot-starter-biz-operatelog/src/main/java/cn/iocoder/yudao/framework/operatelog/core/dto/OperateLogCreateReqDTO.java
@@ -21,6 +21,9 @@ public class OperateLogCreateReqDTO { @@ -21,6 +21,9 @@ public class OperateLogCreateReqDTO {
21 @ApiModelProperty(value = "用户编号", required = true, example = "1024") 21 @ApiModelProperty(value = "用户编号", required = true, example = "1024")
22 @NotNull(message = "用户编号不能为空") 22 @NotNull(message = "用户编号不能为空")
23 private Long userId; 23 private Long userId;
  24 + @ApiModelProperty(value = "用户类型", required = true, example = "1")
  25 + @NotNull(message = "用户类型不能为空")
  26 + private Integer userType;
24 27
25 @ApiModelProperty(value = "操作模块", required = true, example = "订单") 28 @ApiModelProperty(value = "操作模块", required = true, example = "订单")
26 @NotEmpty(message = "操作模块不能为空") 29 @NotEmpty(message = "操作模块不能为空")
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/config/YudaoMybatisAutoConfiguration.java
@@ -15,7 +15,8 @@ import org.springframework.context.annotation.Configuration; @@ -15,7 +15,8 @@ import org.springframework.context.annotation.Configuration;
15 * @author 芋道源码 15 * @author 芋道源码
16 */ 16 */
17 @Configuration 17 @Configuration
18 -@MapperScan(value = {"${yudao.info.base-package}", "${yudao.core-service.base-package}"}, annotationClass = Mapper.class, 18 +@MapperScan(value = {"${yudao.info.base-package}", "${yudao.core-service.base-package}", "${yudao.info.member-package}"},
  19 + annotationClass = Mapper.class,
19 lazyInitialization = "${mybatis.lazy-initialization:false}") // Mapper 懒加载,目前仅用于单元测试 20 lazyInitialization = "${mybatis.lazy-initialization:false}") // Mapper 懒加载,目前仅用于单元测试
20 public class YudaoMybatisAutoConfiguration { 21 public class YudaoMybatisAutoConfiguration {
21 22
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java
1 package cn.iocoder.yudao.framework.security.config; 1 package cn.iocoder.yudao.framework.security.config;
2 2
3 import cn.iocoder.yudao.framework.security.core.aop.PreAuthenticatedAspect; 3 import cn.iocoder.yudao.framework.security.core.aop.PreAuthenticatedAspect;
  4 +import cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider;
4 import cn.iocoder.yudao.framework.security.core.context.TransmittableThreadLocalSecurityContextHolderStrategy; 5 import cn.iocoder.yudao.framework.security.core.context.TransmittableThreadLocalSecurityContextHolderStrategy;
5 import cn.iocoder.yudao.framework.security.core.filter.JWTAuthenticationTokenFilter; 6 import cn.iocoder.yudao.framework.security.core.filter.JWTAuthenticationTokenFilter;
6 import cn.iocoder.yudao.framework.security.core.handler.AccessDeniedHandlerImpl; 7 import cn.iocoder.yudao.framework.security.core.handler.AccessDeniedHandlerImpl;
7 import cn.iocoder.yudao.framework.security.core.handler.AuthenticationEntryPointImpl; 8 import cn.iocoder.yudao.framework.security.core.handler.AuthenticationEntryPointImpl;
8 import cn.iocoder.yudao.framework.security.core.handler.LogoutSuccessHandlerImpl; 9 import cn.iocoder.yudao.framework.security.core.handler.LogoutSuccessHandlerImpl;
9 import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService; 10 import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService;
  11 +import cn.iocoder.yudao.framework.web.config.WebProperties;
10 import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; 12 import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
11 import org.springframework.beans.factory.config.MethodInvokingFactoryBean; 13 import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
12 import org.springframework.boot.context.properties.EnableConfigurationProperties; 14 import org.springframework.boot.context.properties.EnableConfigurationProperties;
@@ -20,6 +22,7 @@ import org.springframework.security.web.access.AccessDeniedHandler; @@ -20,6 +22,7 @@ import org.springframework.security.web.access.AccessDeniedHandler;
20 import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; 22 import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
21 23
22 import javax.annotation.Resource; 24 import javax.annotation.Resource;
  25 +import java.util.List;
23 26
24 /** 27 /**
25 * Spring Security 自动配置类,主要用于相关组件的配置 28 * Spring Security 自动配置类,主要用于相关组件的配置
@@ -29,7 +32,7 @@ import javax.annotation.Resource; @@ -29,7 +32,7 @@ import javax.annotation.Resource;
29 * 32 *
30 * @author 芋道源码 33 * @author 芋道源码
31 */ 34 */
32 -@Configuration 35 +@Configuration(proxyBeanMethods = false)
33 @EnableConfigurationProperties(SecurityProperties.class) 36 @EnableConfigurationProperties(SecurityProperties.class)
34 public class YudaoSecurityAutoConfiguration { 37 public class YudaoSecurityAutoConfiguration {
35 38
@@ -64,8 +67,8 @@ public class YudaoSecurityAutoConfiguration { @@ -64,8 +67,8 @@ public class YudaoSecurityAutoConfiguration {
64 * 退出处理类 Bean 67 * 退出处理类 Bean
65 */ 68 */
66 @Bean 69 @Bean
67 - public LogoutSuccessHandler logoutSuccessHandler(SecurityAuthFrameworkService securityFrameworkService) {  
68 - return new LogoutSuccessHandlerImpl(securityProperties, securityFrameworkService); 70 + public LogoutSuccessHandler logoutSuccessHandler(MultiUserDetailsAuthenticationProvider authenticationProvider) {
  71 + return new LogoutSuccessHandlerImpl(securityProperties, authenticationProvider);
69 } 72 }
70 73
71 /** 74 /**
@@ -83,9 +86,19 @@ public class YudaoSecurityAutoConfiguration { @@ -83,9 +86,19 @@ public class YudaoSecurityAutoConfiguration {
83 * Token 认证过滤器 Bean 86 * Token 认证过滤器 Bean
84 */ 87 */
85 @Bean 88 @Bean
86 - public JWTAuthenticationTokenFilter authenticationTokenFilter(SecurityAuthFrameworkService securityFrameworkService, 89 + public JWTAuthenticationTokenFilter authenticationTokenFilter(MultiUserDetailsAuthenticationProvider authenticationProvider,
87 GlobalExceptionHandler globalExceptionHandler) { 90 GlobalExceptionHandler globalExceptionHandler) {
88 - return new JWTAuthenticationTokenFilter(securityProperties, securityFrameworkService, globalExceptionHandler); 91 + return new JWTAuthenticationTokenFilter(securityProperties, authenticationProvider, globalExceptionHandler);
  92 + }
  93 +
  94 + /**
  95 + * 身份验证的 Provider Bean,通过它实现账号 + 密码的认证
  96 + */
  97 + @Bean
  98 + public MultiUserDetailsAuthenticationProvider authenticationProvider(
  99 + List<SecurityAuthFrameworkService> securityFrameworkServices,
  100 + WebProperties webProperties, PasswordEncoder passwordEncoder) {
  101 + return new MultiUserDetailsAuthenticationProvider(securityFrameworkServices, webProperties, passwordEncoder);
89 } 102 }
90 103
91 /** 104 /**
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java
1 package cn.iocoder.yudao.framework.security.config; 1 package cn.iocoder.yudao.framework.security.config;
2 2
  3 +import cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider;
3 import cn.iocoder.yudao.framework.security.core.filter.JWTAuthenticationTokenFilter; 4 import cn.iocoder.yudao.framework.security.core.filter.JWTAuthenticationTokenFilter;
4 import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService; 5 import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService;
5 import cn.iocoder.yudao.framework.web.config.WebProperties; 6 import cn.iocoder.yudao.framework.web.config.WebProperties;
@@ -35,16 +36,8 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap @@ -35,16 +36,8 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
35 @Resource 36 @Resource
36 private WebProperties webProperties; 37 private WebProperties webProperties;
37 38
38 - /**  
39 - * 自定义用户【认证】逻辑  
40 - */  
41 - @Resource  
42 - private SecurityAuthFrameworkService userDetailsService;  
43 - /**  
44 - * Spring Security 加密器  
45 - */  
46 @Resource 39 @Resource
47 - private PasswordEncoder passwordEncoder; 40 + private MultiUserDetailsAuthenticationProvider authenticationProvider;
48 /** 41 /**
49 * 认证失败处理类 Bean 42 * 认证失败处理类 Bean
50 */ 43 */
@@ -65,13 +58,15 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap @@ -65,13 +58,15 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
65 */ 58 */
66 @Resource 59 @Resource
67 private JWTAuthenticationTokenFilter authenticationTokenFilter; 60 private JWTAuthenticationTokenFilter authenticationTokenFilter;
  61 +
68 /** 62 /**
69 * 自定义的权限映射 Bean 63 * 自定义的权限映射 Bean
70 * 64 *
71 * @see #configure(HttpSecurity) 65 * @see #configure(HttpSecurity)
72 */ 66 */
73 @Resource 67 @Resource
74 - private Customizer<ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry> authorizeRequestsCustomizer; 68 + private Customizer<ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry>
  69 + authorizeRequestsCustomizer;
75 70
76 /** 71 /**
77 * 由于 Spring Security 创建 AuthenticationManager 对象时,没声明 @Bean 注解,导致无法被注入 72 * 由于 Spring Security 创建 AuthenticationManager 对象时,没声明 @Bean 注解,导致无法被注入
@@ -89,8 +84,7 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap @@ -89,8 +84,7 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
89 */ 84 */
90 @Override 85 @Override
91 protected void configure(AuthenticationManagerBuilder auth) throws Exception { 86 protected void configure(AuthenticationManagerBuilder auth) throws Exception {
92 - auth.userDetailsService(userDetailsService)  
93 - .passwordEncoder(passwordEncoder); 87 + auth.authenticationProvider(authenticationProvider);
94 } 88 }
95 89
96 /** 90 /**
@@ -123,16 +117,16 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap @@ -123,16 +117,16 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
123 // 一堆自定义的 Spring Security 处理器 117 // 一堆自定义的 Spring Security 处理器
124 .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint) 118 .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
125 .accessDeniedHandler(accessDeniedHandler).and() 119 .accessDeniedHandler(accessDeniedHandler).and()
126 - .logout().logoutUrl(api("/logout")).logoutSuccessHandler(logoutSuccessHandler); // 登出 120 + .logout().logoutUrl(buildAdminApi("/logout")).logoutSuccessHandler(logoutSuccessHandler); // 登出
127 121
128 // 设置每个请求的权限 ①:全局共享规则 122 // 设置每个请求的权限 ①:全局共享规则
129 httpSecurity.authorizeRequests() 123 httpSecurity.authorizeRequests()
130 // 登录的接口,可匿名访问 124 // 登录的接口,可匿名访问
131 - .antMatchers(api("/login")).anonymous() 125 + .antMatchers(buildAdminApi("/login")).anonymous()
132 // 静态资源,可匿名访问 126 // 静态资源,可匿名访问
133 .antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll() 127 .antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll()
134 // 文件的获取接口,可匿名访问 128 // 文件的获取接口,可匿名访问
135 - .antMatchers(api("/infra/file/get/**")).anonymous() 129 + .antMatchers(buildAdminApi("/infra/file/get/**")).anonymous()
136 // Swagger 接口文档 130 // Swagger 接口文档
137 .antMatchers("/swagger-ui.html").anonymous() 131 .antMatchers("/swagger-ui.html").anonymous()
138 .antMatchers("/swagger-resources/**").anonymous() 132 .antMatchers("/swagger-resources/**").anonymous()
@@ -143,11 +137,11 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap @@ -143,11 +137,11 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
143 .antMatchers("/actuator/**").anonymous() 137 .antMatchers("/actuator/**").anonymous()
144 // Druid 监控 TODO 芋艿:等对接了 druid admin 后,在调整下。 138 // Druid 监控 TODO 芋艿:等对接了 druid admin 后,在调整下。
145 .antMatchers("/druid/**").anonymous() 139 .antMatchers("/druid/**").anonymous()
146 - // oAuth2 auth2/login/gitee  
147 - .antMatchers(api("/auth2/login/**")).anonymous()  
148 - .antMatchers(api("/auth2/authorization/**")).anonymous() 140 + // oAuth2 auth2/login/gitee TODO 芋艿:貌似可以删除
  141 + .antMatchers(buildAdminApi("/auth2/login/**")).anonymous()
  142 + .antMatchers(buildAdminApi("/auth2/authorization/**")).anonymous()
149 .antMatchers("/api/callback/**").anonymous() 143 .antMatchers("/api/callback/**").anonymous()
150 - // 设置每个请求的权限 ②:每个项目的自定义规则 144 + // 设置每个请求的权限 ②:每个项目的自定义规则 TODO 芋艿:改造成多个,方便每个模块自定义规则
151 .and().authorizeRequests(authorizeRequestsCustomizer) 145 .and().authorizeRequests(authorizeRequestsCustomizer)
152 // 设置每个请求的权限 ③:兜底规则,必须认证 146 // 设置每个请求的权限 ③:兜底规则,必须认证
153 .authorizeRequests().anyRequest().authenticated() 147 .authorizeRequests().anyRequest().authenticated()
@@ -156,8 +150,14 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap @@ -156,8 +150,14 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
156 httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); 150 httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
157 } 151 }
158 152
159 - private String api(String url) {  
160 - return webProperties.getApiPrefix() + url; 153 + private String buildAdminApi(String url) {
  154 + // TODO 芋艿:多模块
  155 + return webProperties.getAdminApi().getPrefix() + url;
  156 + }
  157 +
  158 + private String buildAppApi(String url) {
  159 + // TODO 芋艿:多模块
  160 + return webProperties.getAppApi().getPrefix() + url;
161 } 161 }
162 162
163 } 163 }
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/authentication/MultiUserDetailsAuthenticationProvider.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.security.core.authentication;
  2 +
  3 +import cn.hutool.core.lang.Assert;
  4 +import cn.hutool.core.util.StrUtil;
  5 +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
  6 +import cn.iocoder.yudao.framework.security.core.LoginUser;
  7 +import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService;
  8 +import cn.iocoder.yudao.framework.web.config.WebProperties;
  9 +import org.springframework.security.authentication.AuthenticationProvider;
  10 +import org.springframework.security.authentication.BadCredentialsException;
  11 +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
  12 +import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
  13 +import org.springframework.security.core.AuthenticationException;
  14 +import org.springframework.security.core.userdetails.UserDetails;
  15 +import org.springframework.security.crypto.password.PasswordEncoder;
  16 +
  17 +import javax.servlet.http.HttpServletRequest;
  18 +import java.util.HashMap;
  19 +import java.util.List;
  20 +import java.util.Map;
  21 +
  22 +/**
  23 + * 支持多用户类型的 AuthenticationProvider 实现类
  24 + *
  25 + * 为什么不用 {@link org.springframework.security.authentication.ProviderManager} 呢?
  26 + * 原因是,需要每个用户类型实现对应的 {@link AuthenticationProvider} + authentication,略显麻烦。实际,也是可以实现的。
  27 + *
  28 + * 另外,额外支持 verifyTokenAndRefresh 校验令牌、logout 登出、mockLogin 模拟登陆等操作。
  29 + * 实际上,它就是 {@link SecurityAuthFrameworkService} 定义的三个接口。
  30 + * 因为需要支持多种类型,所以需要根据请求的 URL,判断出对应的用户类型,从而使用对应的 SecurityAuthFrameworkService 是吸纳
  31 + *
  32 + * @see cn.iocoder.yudao.framework.common.enums.UserTypeEnum
  33 + * @author 芋道源码
  34 + */
  35 +public class MultiUserDetailsAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
  36 +
  37 + private final Map<UserTypeEnum, SecurityAuthFrameworkService> services = new HashMap<>();
  38 +
  39 + private final WebProperties properties;
  40 +
  41 + private final PasswordEncoder passwordEncoder;
  42 +
  43 + public MultiUserDetailsAuthenticationProvider(List<SecurityAuthFrameworkService> serviceList,
  44 + WebProperties properties, PasswordEncoder passwordEncoder) {
  45 + serviceList.forEach(service -> services.put(service.getUserType(), service));
  46 + this.properties = properties;
  47 + this.passwordEncoder = passwordEncoder;
  48 + }
  49 +
  50 + // ========== AuthenticationProvider 相关 ==========
  51 +
  52 + @Override
  53 + protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication)
  54 + throws AuthenticationException {
  55 + // 执行用户的加载
  56 + return selectService(authentication).loadUserByUsername(username);
  57 + }
  58 +
  59 + private SecurityAuthFrameworkService selectService(UsernamePasswordAuthenticationToken authentication) {
  60 + // 第一步,获得用户类型
  61 + UserTypeEnum userType = getUserType(authentication);
  62 + // 第二步,获得 SecurityAuthFrameworkService
  63 + SecurityAuthFrameworkService service = services.get(userType);
  64 + Assert.notNull(service, "用户类型({}) 找不到 SecurityAuthFrameworkService 实现类", userType);
  65 + return service;
  66 + }
  67 +
  68 + private UserTypeEnum getUserType(UsernamePasswordAuthenticationToken authentication) {
  69 + Assert.isInstanceOf(MultiUsernamePasswordAuthenticationToken.class, authentication);
  70 + MultiUsernamePasswordAuthenticationToken multiAuthentication = (MultiUsernamePasswordAuthenticationToken) authentication;
  71 + UserTypeEnum userType = multiAuthentication.getUserType();
  72 + Assert.notNull(userType, "用户类型不能为空");
  73 + return userType;
  74 + }
  75 +
  76 + @Override // copy 自 DaoAuthenticationProvider 的 additionalAuthenticationChecks 方法
  77 + protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication)
  78 + throws AuthenticationException {
  79 + // 校验 credentials
  80 + if (authentication.getCredentials() == null) {
  81 + this.logger.debug("Failed to authenticate since no credentials provided");
  82 + throw new BadCredentialsException(this.messages.getMessage(
  83 + "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
  84 + }
  85 + // 校验 password
  86 + String presentedPassword = authentication.getCredentials().toString();
  87 + if (!this.passwordEncoder.matches(presentedPassword, userDetails.getPassword())) {
  88 + this.logger.debug("Failed to authenticate since password does not match stored value");
  89 + throw new BadCredentialsException(this.messages.getMessage(
  90 + "AbstractUserDetailsAuthenticationProvider.badCredentials", "Bad credentials"));
  91 + }
  92 + }
  93 +
  94 + // ========== SecurityAuthFrameworkService 相关 ==========
  95 +
  96 + /**
  97 + * 校验 token 的有效性,并获取用户信息
  98 + * 通过后,刷新 token 的过期时间
  99 + *
  100 + * @param request 请求
  101 + * @param token token
  102 + * @return 用户信息
  103 + */
  104 + public LoginUser verifyTokenAndRefresh(HttpServletRequest request, String token) {
  105 + return selectService(request).verifyTokenAndRefresh(token);
  106 + }
  107 +
  108 + /**
  109 + * 模拟指定用户编号的 LoginUser
  110 + *
  111 + * @param request 请求
  112 + * @param userId 用户编号
  113 + * @return 登录用户
  114 + */
  115 + public LoginUser mockLogin(HttpServletRequest request, Long userId) {
  116 + return selectService(request).mockLogin(userId);
  117 + }
  118 +
  119 + /**
  120 + * 基于 token 退出登录
  121 + *
  122 + * @param request 请求
  123 + * @param token token
  124 + */
  125 + public void logout(HttpServletRequest request, String token) {
  126 + selectService(request).logout(token);
  127 + }
  128 +
  129 + private SecurityAuthFrameworkService selectService(HttpServletRequest request) {
  130 + // 第一步,获得用户类型
  131 + UserTypeEnum userType = getUserType(request);
  132 + // 第二步,获得 SecurityAuthFrameworkService
  133 + SecurityAuthFrameworkService service = services.get(userType);
  134 + Assert.notNull(service, "URI({}) 用户类型({}) 找不到 SecurityAuthFrameworkService 实现类",
  135 + request.getRequestURI(), userType);
  136 + return service;
  137 + }
  138 +
  139 + private UserTypeEnum getUserType(HttpServletRequest request) {
  140 + if (request.getRequestURI().startsWith(properties.getAdminApi().getPrefix())) {
  141 + return UserTypeEnum.ADMIN;
  142 + }
  143 + if (request.getRequestURI().startsWith(properties.getAppApi().getPrefix())) {
  144 + return UserTypeEnum.MEMBER;
  145 + }
  146 + throw new IllegalArgumentException(StrUtil.format("URI({}) 找不到匹配的用户类型", request.getRequestURI()));
  147 + }
  148 +
  149 +}
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/authentication/MultiUsernamePasswordAuthenticationToken.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.security.core.authentication;
  2 +
  3 +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
  4 +import lombok.Getter;
  5 +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
  6 +import org.springframework.security.core.GrantedAuthority;
  7 +
  8 +import java.util.Collection;
  9 +
  10 +/**
  11 + * 支持多用户的 UsernamePasswordAuthenticationToken 实现类
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@Getter
  16 +public class MultiUsernamePasswordAuthenticationToken extends UsernamePasswordAuthenticationToken {
  17 +
  18 + /**
  19 + * 用户类型
  20 + */
  21 + private UserTypeEnum userType;
  22 +
  23 + public MultiUsernamePasswordAuthenticationToken(Object principal, Object credentials) {
  24 + super(principal, credentials);
  25 + }
  26 +
  27 + public MultiUsernamePasswordAuthenticationToken(Object principal, Object credentials,
  28 + Collection<? extends GrantedAuthority> authorities) {
  29 + super(principal, credentials, authorities);
  30 + }
  31 +
  32 + public MultiUsernamePasswordAuthenticationToken(Object principal, Object credentials, UserTypeEnum userType) {
  33 + super(principal, credentials);
  34 + this.userType = userType;
  35 + }
  36 +
  37 + public MultiUsernamePasswordAuthenticationToken(Object principal, Object credentials,
  38 + Collection<? extends GrantedAuthority> authorities, UserTypeEnum userType) {
  39 + super(principal, credentials, authorities);
  40 + this.userType = userType;
  41 + }
  42 +
  43 +}
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/filter/JWTAuthenticationTokenFilter.java
@@ -2,17 +2,15 @@ package cn.iocoder.yudao.framework.security.core.filter; @@ -2,17 +2,15 @@ package cn.iocoder.yudao.framework.security.core.filter;
2 2
3 import cn.hutool.core.util.StrUtil; 3 import cn.hutool.core.util.StrUtil;
4 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  5 +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
5 import cn.iocoder.yudao.framework.security.config.SecurityProperties; 6 import cn.iocoder.yudao.framework.security.config.SecurityProperties;
6 import cn.iocoder.yudao.framework.security.core.LoginUser; 7 import cn.iocoder.yudao.framework.security.core.LoginUser;
7 -import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService; 8 +import cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider;
8 import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; 9 import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
9 import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; 10 import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler;
10 -import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;  
11 -import lombok.AllArgsConstructor;  
12 -import org.springframework.stereotype.Component; 11 +import lombok.RequiredArgsConstructor;
13 import org.springframework.web.filter.OncePerRequestFilter; 12 import org.springframework.web.filter.OncePerRequestFilter;
14 13
15 -import javax.annotation.Resource;  
16 import javax.servlet.FilterChain; 14 import javax.servlet.FilterChain;
17 import javax.servlet.ServletException; 15 import javax.servlet.ServletException;
18 import javax.servlet.http.HttpServletRequest; 16 import javax.servlet.http.HttpServletRequest;
@@ -25,12 +23,12 @@ import java.io.IOException; @@ -25,12 +23,12 @@ import java.io.IOException;
25 * 23 *
26 * @author 芋道源码 24 * @author 芋道源码
27 */ 25 */
28 -@AllArgsConstructor 26 +@RequiredArgsConstructor
29 public class JWTAuthenticationTokenFilter extends OncePerRequestFilter { 27 public class JWTAuthenticationTokenFilter extends OncePerRequestFilter {
30 28
31 private final SecurityProperties securityProperties; 29 private final SecurityProperties securityProperties;
32 30
33 - private final SecurityAuthFrameworkService authService; 31 + private final MultiUserDetailsAuthenticationProvider authenticationProvider;
34 32
35 private final GlobalExceptionHandler globalExceptionHandler; 33 private final GlobalExceptionHandler globalExceptionHandler;
36 34
@@ -42,10 +40,10 @@ public class JWTAuthenticationTokenFilter extends OncePerRequestFilter { @@ -42,10 +40,10 @@ public class JWTAuthenticationTokenFilter extends OncePerRequestFilter {
42 if (StrUtil.isNotEmpty(token)) { 40 if (StrUtil.isNotEmpty(token)) {
43 try { 41 try {
44 // 验证 token 有效性 42 // 验证 token 有效性
45 - LoginUser loginUser = authService.verifyTokenAndRefresh(token); 43 + LoginUser loginUser = authenticationProvider.verifyTokenAndRefresh(request, token);
46 // 模拟 Login 功能,方便日常开发调试 44 // 模拟 Login 功能,方便日常开发调试
47 if (loginUser == null) { 45 if (loginUser == null) {
48 - loginUser = this.mockLoginUser(token); 46 + loginUser = this.mockLoginUser(request, token);
49 } 47 }
50 // 设置当前用户 48 // 设置当前用户
51 if (loginUser != null) { 49 if (loginUser != null) {
@@ -67,10 +65,11 @@ public class JWTAuthenticationTokenFilter extends OncePerRequestFilter { @@ -67,10 +65,11 @@ public class JWTAuthenticationTokenFilter extends OncePerRequestFilter {
67 * 65 *
68 * 注意,在线上环境下,一定要关闭该功能!!! 66 * 注意,在线上环境下,一定要关闭该功能!!!
69 * 67 *
  68 + * @param request 请求
70 * @param token 模拟的 token,格式为 {@link SecurityProperties#getTokenSecret()} + 用户编号 69 * @param token 模拟的 token,格式为 {@link SecurityProperties#getTokenSecret()} + 用户编号
71 * @return 模拟的 LoginUser 70 * @return 模拟的 LoginUser
72 */ 71 */
73 - private LoginUser mockLoginUser(String token) { 72 + private LoginUser mockLoginUser(HttpServletRequest request, String token) {
74 if (!securityProperties.getMockEnable()) { 73 if (!securityProperties.getMockEnable()) {
75 return null; 74 return null;
76 } 75 }
@@ -79,7 +78,7 @@ public class JWTAuthenticationTokenFilter extends OncePerRequestFilter { @@ -79,7 +78,7 @@ public class JWTAuthenticationTokenFilter extends OncePerRequestFilter {
79 return null; 78 return null;
80 } 79 }
81 Long userId = Long.valueOf(token.substring(securityProperties.getMockSecret().length())); 80 Long userId = Long.valueOf(token.substring(securityProperties.getMockSecret().length()));
82 - return authService.mockLogin(userId); 81 + return authenticationProvider.mockLogin(request, userId);
83 } 82 }
84 83
85 } 84 }
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AbstractSignUpUrlAuthenticationSuccessHandler.java deleted
1 -/*  
2 - * MIT License  
3 - * Copyright (c) 2020-2029 YongWu zheng (dcenter.top and gitee.com/pcore and github.com/ZeroOrInfinity)  
4 - *  
5 - * Permission is hereby granted, free of charge, to any person obtaining a copy  
6 - * of this software and associated documentation files (the "Software"), to deal  
7 - * in the Software without restriction, including without limitation the rights  
8 - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell  
9 - * copies of the Software, and to permit persons to whom the Software is  
10 - * furnished to do so, subject to the following conditions:  
11 - *  
12 - * The above copyright notice and this permission notice shall be included in all  
13 - * copies or substantial portions of the Software.  
14 - *  
15 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
16 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,  
17 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE  
18 - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER  
19 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  
20 - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  
21 - * SOFTWARE.  
22 - */  
23 -package cn.iocoder.yudao.framework.security.core.handler;  
24 -  
25 -import org.springframework.security.core.Authentication;  
26 -import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;  
27 -import org.springframework.security.web.savedrequest.HttpSessionRequestCache;  
28 -import org.springframework.security.web.savedrequest.RequestCache;  
29 -  
30 -import javax.servlet.ServletException;  
31 -import javax.servlet.http.HttpServletRequest;  
32 -import javax.servlet.http.HttpServletResponse;  
33 -import java.io.IOException;  
34 -  
35 -/**  
36 - * @author weir  
37 - */  
38 -public class AbstractSignUpUrlAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {  
39 - private RequestCache requestCache = new HttpSessionRequestCache();  
40 -  
41 - @Override  
42 - public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {  
43 - if (requestCache.getRequest(request, response) != null) {  
44 - requestCache.getRequest(request, response);  
45 - }  
46 - super.onAuthenticationSuccess(request,response,authentication);  
47 - }  
48 -  
49 - @Override  
50 - public void setRequestCache(RequestCache requestCache) {  
51 - this.requestCache = requestCache;  
52 - }  
53 -}  
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/LogoutSuccessHandlerImpl.java
@@ -2,16 +2,14 @@ package cn.iocoder.yudao.framework.security.core.handler; @@ -2,16 +2,14 @@ package cn.iocoder.yudao.framework.security.core.handler;
2 2
3 import cn.hutool.core.util.StrUtil; 3 import cn.hutool.core.util.StrUtil;
4 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  5 +import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
5 import cn.iocoder.yudao.framework.security.config.SecurityProperties; 6 import cn.iocoder.yudao.framework.security.config.SecurityProperties;
6 -import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService; 7 +import cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider;
7 import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; 8 import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
8 -import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;  
9 import lombok.AllArgsConstructor; 9 import lombok.AllArgsConstructor;
10 import org.springframework.security.core.Authentication; 10 import org.springframework.security.core.Authentication;
11 import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; 11 import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
12 -import org.springframework.stereotype.Component;  
13 12
14 -import javax.annotation.Resource;  
15 import javax.servlet.http.HttpServletRequest; 13 import javax.servlet.http.HttpServletRequest;
16 import javax.servlet.http.HttpServletResponse; 14 import javax.servlet.http.HttpServletResponse;
17 15
@@ -26,14 +24,14 @@ public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler { @@ -26,14 +24,14 @@ public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler {
26 24
27 private final SecurityProperties securityProperties; 25 private final SecurityProperties securityProperties;
28 26
29 - private final SecurityAuthFrameworkService securityFrameworkService; 27 + private final MultiUserDetailsAuthenticationProvider authenticationProvider;
30 28
31 @Override 29 @Override
32 public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { 30 public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
33 // 执行退出 31 // 执行退出
34 String token = SecurityFrameworkUtils.obtainAuthorization(request, securityProperties.getTokenHeader()); 32 String token = SecurityFrameworkUtils.obtainAuthorization(request, securityProperties.getTokenHeader());
35 if (StrUtil.isNotBlank(token)) { 33 if (StrUtil.isNotBlank(token)) {
36 - securityFrameworkService.logout(token); 34 + authenticationProvider.logout(request, token);
37 } 35 }
38 // 返回成功 36 // 返回成功
39 ServletUtils.writeJSON(response, CommonResult.success(null)); 37 ServletUtils.writeJSON(response, CommonResult.success(null));
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/service/SecurityAuthFrameworkService.java
1 package cn.iocoder.yudao.framework.security.core.service; 1 package cn.iocoder.yudao.framework.security.core.service;
2 2
  3 +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
3 import cn.iocoder.yudao.framework.security.core.LoginUser; 4 import cn.iocoder.yudao.framework.security.core.LoginUser;
4 import org.springframework.security.core.userdetails.UserDetailsService; 5 import org.springframework.security.core.userdetails.UserDetailsService;
5 6
6 /** 7 /**
7 - * Security 框架 Auth Service 接口,定义 security 组件需要的功能 8 + * Security 框架 Auth Service 接口,定义不同用户类型的 {@link UserTypeEnum} 需要实现的方法
8 * 9 *
9 * @author 芋道源码 10 * @author 芋道源码
10 */ 11 */
@@ -34,4 +35,11 @@ public interface SecurityAuthFrameworkService extends UserDetailsService { @@ -34,4 +35,11 @@ public interface SecurityAuthFrameworkService extends UserDetailsService {
34 */ 35 */
35 void logout(String token); 36 void logout(String token);
36 37
  38 + /**
  39 + * 获得用户类型。每个用户类型,对应一个 SecurityAuthFrameworkService 实现类。
  40 + *
  41 + * @return 用户类型
  42 + */
  43 + UserTypeEnum getUserType();
  44 +
37 } 45 }
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/filter/ApiAccessLogFilter.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.apilog.core.filter; @@ -2,6 +2,7 @@ package cn.iocoder.yudao.framework.apilog.core.filter;
2 2
3 import cn.hutool.core.exceptions.ExceptionUtil; 3 import cn.hutool.core.exceptions.ExceptionUtil;
4 import cn.hutool.core.map.MapUtil; 4 import cn.hutool.core.map.MapUtil;
  5 +import cn.hutool.core.util.StrUtil;
5 import cn.hutool.extra.servlet.ServletUtil; 6 import cn.hutool.extra.servlet.ServletUtil;
6 import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants; 7 import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants;
7 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 8 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
@@ -25,6 +26,8 @@ import java.io.IOException; @@ -25,6 +26,8 @@ import java.io.IOException;
25 import java.util.Date; 26 import java.util.Date;
26 import java.util.Map; 27 import java.util.Map;
27 28
  29 +import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.*;
  30 +
28 /** 31 /**
29 * API 访问日志 Filter 32 * API 访问日志 Filter
30 * 33 *
@@ -42,7 +45,8 @@ public class ApiAccessLogFilter extends OncePerRequestFilter { @@ -42,7 +45,8 @@ public class ApiAccessLogFilter extends OncePerRequestFilter {
42 @Override 45 @Override
43 protected boolean shouldNotFilter(HttpServletRequest request) { 46 protected boolean shouldNotFilter(HttpServletRequest request) {
44 // 只过滤 API 请求的地址 47 // 只过滤 API 请求的地址
45 - return !request.getRequestURI().startsWith(webProperties.getApiPrefix()); 48 + return !StrUtil.startWithAny(request.getRequestURI(), webProperties.getAppApi().getPrefix(),
  49 + webProperties.getAppApi().getPrefix());
46 } 50 }
47 51
48 @Override 52 @Override
@@ -73,7 +77,7 @@ public class ApiAccessLogFilter extends OncePerRequestFilter { @@ -73,7 +77,7 @@ public class ApiAccessLogFilter extends OncePerRequestFilter {
73 this.buildApiAccessLogDTO(accessLog, request, beginTime, queryString, requestBody, ex); 77 this.buildApiAccessLogDTO(accessLog, request, beginTime, queryString, requestBody, ex);
74 apiAccessLogFrameworkService.createApiAccessLogAsync(accessLog); 78 apiAccessLogFrameworkService.createApiAccessLogAsync(accessLog);
75 } catch (Throwable th) { 79 } catch (Throwable th) {
76 - log.error("[createApiAccessLog][url({}) log({}) 发生异常]", request.getRequestURI(), JsonUtils.toJsonString(accessLog), th); 80 + log.error("[createApiAccessLog][url({}) log({}) 发生异常]", request.getRequestURI(), toJsonString(accessLog), th);
77 } 81 }
78 } 82 }
79 83
@@ -99,7 +103,7 @@ public class ApiAccessLogFilter extends OncePerRequestFilter { @@ -99,7 +103,7 @@ public class ApiAccessLogFilter extends OncePerRequestFilter {
99 accessLog.setApplicationName(applicationName); 103 accessLog.setApplicationName(applicationName);
100 accessLog.setRequestUrl(request.getRequestURI()); 104 accessLog.setRequestUrl(request.getRequestURI());
101 Map<String, Object> requestParams = MapUtil.<String, Object>builder().put("query", queryString).put("body", requestBody).build(); 105 Map<String, Object> requestParams = MapUtil.<String, Object>builder().put("query", queryString).put("body", requestBody).build();
102 - accessLog.setRequestParams(JsonUtils.toJsonString(requestParams)); 106 + accessLog.setRequestParams(toJsonString(requestParams));
103 accessLog.setRequestMethod(request.getMethod()); 107 accessLog.setRequestMethod(request.getMethod());
104 accessLog.setUserAgent(ServletUtils.getUserAgent(request)); 108 accessLog.setUserAgent(ServletUtils.getUserAgent(request));
105 accessLog.setUserIp(ServletUtil.getClientIP(request)); 109 accessLog.setUserIp(ServletUtil.getClientIP(request));
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/WebProperties.java
@@ -5,6 +5,8 @@ import org.springframework.boot.context.properties.ConfigurationProperties; @@ -5,6 +5,8 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
5 import org.springframework.validation.annotation.Validated; 5 import org.springframework.validation.annotation.Validated;
6 import org.springframework.web.servlet.config.annotation.PathMatchConfigurer; 6 import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
7 7
  8 +import javax.validation.Valid;
  9 +import javax.validation.constraints.NotEmpty;
8 import javax.validation.constraints.NotNull; 10 import javax.validation.constraints.NotNull;
9 11
10 @ConfigurationProperties(prefix = "yudao.web") 12 @ConfigurationProperties(prefix = "yudao.web")
@@ -12,26 +14,37 @@ import javax.validation.constraints.NotNull; @@ -12,26 +14,37 @@ import javax.validation.constraints.NotNull;
12 @Data 14 @Data
13 public class WebProperties { 15 public class WebProperties {
14 16
15 - /**  
16 - * API 前缀,实现所有 Controller 提供的 RESTFul API 的统一前缀  
17 - *  
18 - *  
19 - * 意义:通过该前缀,避免 Swagger、Actuator 意外通过 Nginx 暴露出来给外部,带来安全性问题  
20 - * 这样,Nginx 只需要配置转发到 /api/* 的所有接口即可。  
21 - *  
22 - * @see YudaoWebAutoConfiguration#configurePathMatch(PathMatchConfigurer)  
23 - */  
24 - @NotNull(message = "API 前缀不能为空")  
25 - private String apiPrefix;  
26 -  
27 - /**  
28 - * Controller 所在包  
29 - *  
30 - * 主要目的是,给该 Controller 设置指定的 {@link #apiPrefix}  
31 - *  
32 - * 因为我们有多个 modules 包里会包含 Controller,所以只需要写到 cn.iocoder.yudao 这样的层级  
33 - */  
34 - @NotNull(message = "Controller 所在包不能为空")  
35 - private String controllerPackage; 17 + @NotNull(message = "APP API 不能为空")
  18 + private Api appApi;
  19 + @NotNull(message = "Admin API 不能为空")
  20 + private Api adminApi;
  21 +
  22 + @Data
  23 + @Valid
  24 + public static class Api {
  25 +
  26 + /**
  27 + * API 前缀,实现所有 Controller 提供的 RESTFul API 的统一前缀
  28 + *
  29 + *
  30 + * 意义:通过该前缀,避免 Swagger、Actuator 意外通过 Nginx 暴露出来给外部,带来安全性问题
  31 + * 这样,Nginx 只需要配置转发到 /api/* 的所有接口即可。
  32 + *
  33 + * @see YudaoWebAutoConfiguration#configurePathMatch(PathMatchConfigurer)
  34 + */
  35 + @NotEmpty(message = "API 前缀不能为空")
  36 + private String prefix;
  37 +
  38 + /**
  39 + * Controller 所在包
  40 + *
  41 + * 主要目的是,给该 Controller 设置指定的 {@link #prefix}
  42 + *
  43 + * 因为我们有多个 modules 包里会包含 Controller,所以只需要写到 cn.iocoder.yudao 这样的层级
  44 + */
  45 + @NotEmpty(message = "Controller 所在包不能为空")
  46 + private String controller;
  47 +
  48 + }
36 49
37 } 50 }
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/config/YudaoWebAutoConfiguration.java
@@ -38,10 +38,19 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer { @@ -38,10 +38,19 @@ public class YudaoWebAutoConfiguration implements WebMvcConfigurer {
38 38
39 @Override 39 @Override
40 public void configurePathMatch(PathMatchConfigurer configurer) { 40 public void configurePathMatch(PathMatchConfigurer configurer) {
41 - // 设置 API 前缀,仅仅匹配 controller 包下的  
42 - configurer.addPathPrefix(webProperties.getApiPrefix(), clazz ->  
43 - clazz.isAnnotationPresent(RestController.class)  
44 - && clazz.getPackage().getName().startsWith(webProperties.getControllerPackage())); // 仅仅匹配 controller 包 41 + configurePathMatch(configurer, webProperties.getAdminApi());
  42 + configurePathMatch(configurer, webProperties.getAppApi());
  43 + }
  44 +
  45 + /**
  46 + * 设置 API 前缀,仅仅匹配 controller 包下的
  47 + *
  48 + * @param configurer 配置
  49 + * @param api API 配置
  50 + */
  51 + private void configurePathMatch(PathMatchConfigurer configurer, WebProperties.Api api) {
  52 + configurer.addPathPrefix(api.getPrefix(), clazz -> clazz.isAnnotationPresent(RestController.class)
  53 + && clazz.getPackage().getName().startsWith(api.getController())); // 仅仅匹配 controller 包
45 } 54 }
46 55
47 @Bean 56 @Bean
yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/util/WebFrameworkUtils.java
@@ -55,6 +55,11 @@ public class WebFrameworkUtils { @@ -55,6 +55,11 @@ public class WebFrameworkUtils {
55 return (Integer) request.getAttribute(REQUEST_ATTRIBUTE_LOGIN_USER_TYPE); 55 return (Integer) request.getAttribute(REQUEST_ATTRIBUTE_LOGIN_USER_TYPE);
56 } 56 }
57 57
  58 + public static Integer getLoginUserType() {
  59 + HttpServletRequest request = getRequest();
  60 + return getLoginUserType(request);
  61 + }
  62 +
58 public static Long getLoginUserId() { 63 public static Long getLoginUserId() {
59 HttpServletRequest request = getRequest(); 64 HttpServletRequest request = getRequest();
60 return getLoginUserId(request); 65 return getLoginUserId(request);
yudao-module-bpm/yudao-module-bpm-activiti/src/main/java/cn/iocoder/yudao/adminserver/modules/bpm/framework/activiti/config/BpmActivitiConfiguration.java
@@ -10,10 +10,17 @@ import cn.iocoder.yudao.coreservice.modules.bpm.api.group.BpmUserGroupServiceApi @@ -10,10 +10,17 @@ import cn.iocoder.yudao.coreservice.modules.bpm.api.group.BpmUserGroupServiceApi
10 import cn.iocoder.yudao.coreservice.modules.system.service.dept.SysDeptCoreService; 10 import cn.iocoder.yudao.coreservice.modules.system.service.dept.SysDeptCoreService;
11 import cn.iocoder.yudao.coreservice.modules.system.service.permission.SysPermissionCoreService; 11 import cn.iocoder.yudao.coreservice.modules.system.service.permission.SysPermissionCoreService;
12 import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService; 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 +import org.activiti.api.runtime.shared.identity.UserGroupManager;
  18 +import org.activiti.core.common.spring.identity.ActivitiUserGroupManagerImpl;
13 import org.activiti.spring.boot.ProcessEngineConfigurationConfigurer; 19 import org.activiti.spring.boot.ProcessEngineConfigurationConfigurer;
14 import org.springframework.context.ApplicationEventPublisher; 20 import org.springframework.context.ApplicationEventPublisher;
15 import org.springframework.context.annotation.Bean; 21 import org.springframework.context.annotation.Bean;
16 import org.springframework.context.annotation.Configuration; 22 import org.springframework.context.annotation.Configuration;
  23 +import org.springframework.security.core.userdetails.UserDetailsService;
17 24
18 import java.util.Collections; 25 import java.util.Collections;
19 import java.util.List; 26 import java.util.List;
@@ -27,7 +34,15 @@ import static org.activiti.spring.boot.ProcessEngineAutoConfiguration.BEHAVIOR_F @@ -27,7 +34,15 @@ import static org.activiti.spring.boot.ProcessEngineAutoConfiguration.BEHAVIOR_F
27 public class BpmActivitiConfiguration { 34 public class BpmActivitiConfiguration {
28 35
29 /** 36 /**
30 - * BPM 模块的 ProcessEngineConfigurationConfigurer 实现类,主要设置各种监听器、用户组管理 37 + * 空用户组的 Bean
  38 + */
  39 + @Bean
  40 + public UserGroupManager userGroupManager() {
  41 + return new EmptyUserGroupManager();
  42 + }
  43 +
  44 + /**
  45 + * BPM 模块的 ProcessEngineConfigurationConfigurer 实现类,主要设置各种监听器
31 */ 46 */
32 @Bean 47 @Bean
33 public ProcessEngineConfigurationConfigurer bpmProcessEngineConfigurationConfigurer( 48 public ProcessEngineConfigurationConfigurer bpmProcessEngineConfigurationConfigurer(
@@ -35,8 +50,6 @@ public class BpmActivitiConfiguration { @@ -35,8 +50,6 @@ public class BpmActivitiConfiguration {
35 return configuration -> { 50 return configuration -> {
36 // 注册监听器,例如说 BpmActivitiEventListener 51 // 注册监听器,例如说 BpmActivitiEventListener
37 configuration.setEventListeners(Collections.singletonList(taskActivitiEventListener)); 52 configuration.setEventListeners(Collections.singletonList(taskActivitiEventListener));
38 - // 用户组  
39 - configuration.setUserGroupManager(new EmptyUserGroupManager());  
40 }; 53 };
41 } 54 }
42 55
yudao-module-member/pom.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <parent>
  6 + <groupId>cn.iocoder.boot</groupId>
  7 + <artifactId>yudao</artifactId>
  8 + <version>${revision}</version>
  9 + </parent>
  10 + <modelVersion>4.0.0</modelVersion>
  11 + <modules>
  12 + <module>yudao-module-member-api</module>
  13 + <module>yudao-module-member-impl</module>
  14 + </modules>
  15 + <artifactId>yudao-module-member</artifactId>
  16 + <packaging>pom</packaging>
  17 +
  18 + <name>${artifactId}</name>
  19 + <description>
  20 + member 模块,我们放会员业务。
  21 + 例如说:会员中心等等
  22 + </description>
  23 +
  24 +</project>
yudao-module-member/yudao-module-member-api/pom.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <parent>
  6 + <groupId>cn.iocoder.boot</groupId>
  7 + <artifactId>yudao-module-member</artifactId>
  8 + <version>${revision}</version>
  9 + </parent>
  10 + <modelVersion>4.0.0</modelVersion>
  11 + <artifactId>yudao-module-member-api</artifactId>
  12 + <packaging>jar</packaging>
  13 +
  14 + <name>${artifactId}</name>
  15 + <description>
  16 + member 模块 API,暴露给其它模块调用
  17 + </description>
  18 +
  19 + <dependencies>
  20 + <dependency>
  21 + <groupId>cn.iocoder.boot</groupId>
  22 + <artifactId>yudao-common</artifactId>
  23 + </dependency>
  24 + </dependencies>
  25 +
  26 +</project>
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/package-info.java renamed to yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/package-info.java
1 /** 1 /**
2 - * 占位 2 + * member API 包,定义暴露给其它模块的 API
3 */ 3 */
4 -package cn.iocoder.yudao.userserver.modules.system.controller; 4 +package cn.iocoder.yudao.module.member.api;
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/UserApi.java 0 → 100644
  1 +package cn.iocoder.yudao.module.member.api.user;
  2 +
  3 +import cn.iocoder.yudao.module.member.api.user.dto.UserRespDTO;
  4 +
  5 +/**
  6 + * 会员用户的 API 接口
  7 + *
  8 + * @author 芋道源码
  9 + */
  10 +public interface UserApi {
  11 +
  12 + /**
  13 + * 获得会员用户信息
  14 + *
  15 + * @param id 用户编号
  16 + * @return 用户信息
  17 + */
  18 + UserRespDTO getUser(Long id);
  19 +
  20 +}
yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/api/user/dto/UserRespDTO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.member.api.user.dto;
  2 +
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  4 +
  5 +/**
  6 + * 用户信息 Response DTO
  7 + *
  8 + * @author 芋道源码
  9 + */
  10 +public class UserRespDTO {
  11 +
  12 + /**
  13 + * 用户ID
  14 + */
  15 + private Long id;
  16 + /**
  17 + * 用户昵称
  18 + */
  19 + private String nickname;
  20 + /**
  21 + * 帐号状态
  22 + *
  23 + * 枚举 {@link CommonStatusEnum}
  24 + */
  25 + private Integer status;
  26 +
  27 + /**
  28 + * 手机
  29 + */
  30 + private String mobile;
  31 +
  32 +}
yudao-module-member/yudao-module-member-impl/pom.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <parent>
  6 + <groupId>cn.iocoder.boot</groupId>
  7 + <artifactId>yudao-module-member</artifactId>
  8 + <version>${revision}</version>
  9 + </parent>
  10 + <modelVersion>4.0.0</modelVersion>
  11 + <artifactId>yudao-module-member-impl</artifactId>
  12 + <packaging>jar</packaging>
  13 +
  14 + <name>${artifactId}</name>
  15 + <description>
  16 + member 模块,我们放会员业务。
  17 + 例如说:会员中心等等
  18 + </description>
  19 +
  20 + <dependencies>
  21 + <dependency>
  22 + <groupId>cn.iocoder.boot</groupId>
  23 + <artifactId>yudao-module-member-api</artifactId>
  24 + <version>${revision}</version>
  25 + </dependency>
  26 +
  27 + <!-- 业务组件 -->
  28 + <dependency>
  29 + <groupId>cn.iocoder.boot</groupId>
  30 + <artifactId>yudao-core-service</artifactId>
  31 + </dependency>
  32 +
  33 + <dependency>
  34 + <groupId>cn.iocoder.boot</groupId>
  35 + <artifactId>yudao-spring-boot-starter-biz-operatelog</artifactId>
  36 + </dependency>
  37 + <dependency>
  38 + <groupId>cn.iocoder.boot</groupId>
  39 + <artifactId>yudao-spring-boot-starter-biz-sms</artifactId>
  40 + </dependency>
  41 + <dependency>
  42 + <groupId>cn.iocoder.boot</groupId>
  43 + <artifactId>yudao-spring-boot-starter-biz-weixin</artifactId>
  44 + </dependency>
  45 +
  46 + <!-- Web 相关 -->
  47 + <dependency>
  48 + <groupId>cn.iocoder.boot</groupId>
  49 + <artifactId>yudao-spring-boot-starter-security</artifactId>
  50 + </dependency>
  51 +
  52 + <!-- DB 相关 -->
  53 + <dependency>
  54 + <groupId>cn.iocoder.boot</groupId>
  55 + <artifactId>yudao-spring-boot-starter-mybatis</artifactId>
  56 + </dependency>
  57 +
  58 + <dependency>
  59 + <groupId>cn.iocoder.boot</groupId>
  60 + <artifactId>yudao-spring-boot-starter-redis</artifactId>
  61 + </dependency>
  62 +
  63 + <!-- 消息队列相关 -->
  64 + <dependency>
  65 + <groupId>cn.iocoder.boot</groupId>
  66 + <artifactId>yudao-spring-boot-starter-mq</artifactId>
  67 + </dependency>
  68 +
  69 + <!-- Test 测试相关 -->
  70 + <dependency>
  71 + <groupId>cn.iocoder.boot</groupId>
  72 + <artifactId>yudao-spring-boot-starter-test</artifactId>
  73 + <scope>test</scope>
  74 + </dependency>
  75 + <!-- 工具类相关 -->
  76 +
  77 + </dependencies>
  78 +
  79 + <build>
  80 + <!-- 设置构建的 jar 包名 -->
  81 + <finalName>${artifactId}</finalName>
  82 + <plugins>
  83 + <!-- 打包 -->
  84 + <plugin>
  85 + <groupId>org.springframework.boot</groupId>
  86 + <artifactId>spring-boot-maven-plugin</artifactId>
  87 + <configuration>
  88 + <fork>true</fork>
  89 + </configuration>
  90 + <executions>
  91 + <execution>
  92 + <goals>
  93 + <goal>repackage</goal> <!-- 将引入的 jar 打入其中 -->
  94 + </goals>
  95 + </execution>
  96 + </executions>
  97 + </plugin>
  98 + </plugins>
  99 + </build>
  100 +
  101 +</project>
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/api/package-info.java 0 → 100644
  1 +package cn.iocoder.yudao.module.member.api;
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/api/user/UserApiImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.module.member.api.user;
  2 +
  3 +import cn.iocoder.yudao.module.member.api.user.dto.UserRespDTO;
  4 +import cn.iocoder.yudao.module.member.convert.user.UserConvert;
  5 +import cn.iocoder.yudao.module.member.dal.dataobject.user.UserDO;
  6 +import cn.iocoder.yudao.module.member.service.user.UserService;
  7 +import org.springframework.stereotype.Service;
  8 +import org.springframework.validation.annotation.Validated;
  9 +
  10 +import javax.annotation.Resource;
  11 +
  12 +/**
  13 + * 会员用户的 API 实现类
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +@Service
  18 +@Validated
  19 +public class UserApiImpl implements UserApi {
  20 +
  21 + @Resource
  22 + private UserService userService;
  23 +
  24 + @Override
  25 + public UserRespDTO getUser(Long id) {
  26 + UserDO user = userService.getUser(id);
  27 + return UserConvert.INSTANCE.convert2(user);
  28 + }
  29 +
  30 +}
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/admin/address/package-info.java 0 → 100644
  1 +package cn.iocoder.yudao.module.member.controller.admin.address;
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/admin/user/package-info.java 0 → 100644
  1 +package cn.iocoder.yudao.module.member.controller.admin.user;
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/address/package-info.java 0 → 100644
  1 +package cn.iocoder.yudao.module.member.controller.app.address;
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/SysAuthController.http renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.http
1 ### 请求 /login 接口 => 成功 1 ### 请求 /login 接口 => 成功
2 -POST {{userServerUrl}}/login 2 +POST {{userApi}}/login
3 Content-Type: application/json 3 Content-Type: application/json
  4 +tenant-id: {{userTenentId}}
4 5
5 { 6 {
6 "mobile": "15601691300", 7 "mobile": "15601691300",
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/SysAuthController.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/AppAuthController.java
1 -package cn.iocoder.yudao.userserver.modules.system.controller.auth; 1 +package cn.iocoder.yudao.module.member.controller.app.auth;
2 2
3 import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialCoreService; 3 import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialCoreService;
4 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; 4 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
5 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 5 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  6 +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
6 import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; 7 import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
7 -import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.*;  
8 -import cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsSceneEnum;  
9 -import cn.iocoder.yudao.userserver.modules.system.service.auth.SysAuthService;  
10 -import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService;  
11 -import com.alibaba.fastjson.JSON; 8 +import cn.iocoder.yudao.module.member.controller.app.auth.vo.*;
  9 +import cn.iocoder.yudao.module.member.service.auth.AuthService;
  10 +import cn.iocoder.yudao.module.member.service.sms.SysSmsCodeService;
12 import io.swagger.annotations.Api; 11 import io.swagger.annotations.Api;
13 import io.swagger.annotations.ApiImplicitParam; 12 import io.swagger.annotations.ApiImplicitParam;
14 import io.swagger.annotations.ApiImplicitParams; 13 import io.swagger.annotations.ApiImplicitParams;
@@ -18,7 +17,6 @@ import org.springframework.validation.annotation.Validated; @@ -18,7 +17,6 @@ import org.springframework.validation.annotation.Validated;
18 import org.springframework.web.bind.annotation.*; 17 import org.springframework.web.bind.annotation.*;
19 18
20 import javax.annotation.Resource; 19 import javax.annotation.Resource;
21 -import javax.servlet.http.HttpServletRequest;  
22 import javax.validation.Valid; 20 import javax.validation.Valid;
23 21
24 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 22 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@@ -26,15 +24,16 @@ import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getCli @@ -26,15 +24,16 @@ import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getCli
26 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getUserAgent; 24 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getUserAgent;
27 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; 25 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
28 26
29 -@Api(tags = "认证") 27 +@Api(tags = "APP 端 - 认证")
30 @RestController 28 @RestController
31 @RequestMapping("/") 29 @RequestMapping("/")
32 @Validated 30 @Validated
33 @Slf4j 31 @Slf4j
34 -public class SysAuthController { 32 +public class AppAuthController {
35 33
36 @Resource 34 @Resource
37 - private SysAuthService authService; 35 + private AuthService authService;
  36 +
38 @Resource 37 @Resource
39 private SysSmsCodeService smsCodeService; 38 private SysSmsCodeService smsCodeService;
40 @Resource 39 @Resource
@@ -42,35 +41,31 @@ public class SysAuthController { @@ -42,35 +41,31 @@ public class SysAuthController {
42 41
43 @PostMapping("/login") 42 @PostMapping("/login")
44 @ApiOperation("使用手机 + 密码登录") 43 @ApiOperation("使用手机 + 密码登录")
45 - public CommonResult<SysAuthLoginRespVO> login(@RequestBody @Valid SysAuthLoginReqVO reqVO) { 44 + @OperateLog(enable = false) // 避免 Post 请求被记录操作日志
  45 + public CommonResult<AppAuthLoginRespVO> login(@RequestBody @Valid AppAuthLoginReqVO reqVO) {
46 String token = authService.login(reqVO, getClientIP(), getUserAgent()); 46 String token = authService.login(reqVO, getClientIP(), getUserAgent());
47 // 返回结果 47 // 返回结果
48 - return success(SysAuthLoginRespVO.builder().token(token).build()); 48 + return success(AppAuthLoginRespVO.builder().token(token).build());
49 } 49 }
50 50
51 @PostMapping("/sms-login") 51 @PostMapping("/sms-login")
52 @ApiOperation("使用手机 + 验证码登录") 52 @ApiOperation("使用手机 + 验证码登录")
53 - public CommonResult<SysAuthLoginRespVO> smsLogin(@RequestBody @Valid SysAuthSmsLoginReqVO reqVO) { 53 + @OperateLog(enable = false) // 避免 Post 请求被记录操作日志
  54 + public CommonResult<AppAuthLoginRespVO> smsLogin(@RequestBody @Valid AppAuthSmsLoginReqVO reqVO) {
54 String token = authService.smsLogin(reqVO, getClientIP(), getUserAgent()); 55 String token = authService.smsLogin(reqVO, getClientIP(), getUserAgent());
55 // 返回结果 56 // 返回结果
56 - return success(SysAuthLoginRespVO.builder().token(token).build()); 57 + return success(AppAuthLoginRespVO.builder().token(token).build());
57 } 58 }
58 59
59 @PostMapping("/send-sms-code") 60 @PostMapping("/send-sms-code")
60 - @ApiOperation(value = "发送手机验证码",notes = "不检测该手机号是否已被注册")  
61 - public CommonResult<Boolean> sendSmsCode(@RequestBody @Valid SysAuthSendSmsReqVO reqVO) { 61 + @ApiOperation(value = "发送手机验证码")
  62 + @OperateLog(enable = false) // 避免 Post 请求被记录操作日志
  63 + public CommonResult<Boolean> sendSmsCode(@RequestBody @Valid AppAuthSendSmsReqVO reqVO) {
62 smsCodeService.sendSmsCode(reqVO.getMobile(), reqVO.getScene(), getClientIP()); 64 smsCodeService.sendSmsCode(reqVO.getMobile(), reqVO.getScene(), getClientIP());
63 return success(true); 65 return success(true);
64 } 66 }
65 67
66 - @PostMapping("/send-sms-new-code")  
67 - @ApiOperation(value = "发送手机验证码",notes = "检测该手机号是否已被注册,用于修改手机时使用")  
68 - public CommonResult<Boolean> sendSmsNewCode(@RequestBody @Valid SysAuthSendSmsReqVO reqVO) {  
69 - smsCodeService.sendSmsNewCode(reqVO);  
70 - return success(true);  
71 - }  
72 -  
73 - @GetMapping("/send-sms-code-login") 68 + @GetMapping("/send-sms-code-login") // TODO 芋艿:post 比较合理
74 @ApiOperation(value = "向已登录用户发送验证码",notes = "修改手机时验证原手机号使用") 69 @ApiOperation(value = "向已登录用户发送验证码",notes = "修改手机时验证原手机号使用")
75 public CommonResult<Boolean> sendSmsCodeLogin() { 70 public CommonResult<Boolean> sendSmsCodeLogin() {
76 smsCodeService.sendSmsCodeLogin(getLoginUserId()); 71 smsCodeService.sendSmsCodeLogin(getLoginUserId());
@@ -80,7 +75,8 @@ public class SysAuthController { @@ -80,7 +75,8 @@ public class SysAuthController {
80 @PostMapping("/reset-password") 75 @PostMapping("/reset-password")
81 @ApiOperation(value = "重置密码", notes = "用户忘记密码时使用") 76 @ApiOperation(value = "重置密码", notes = "用户忘记密码时使用")
82 @PreAuthenticated 77 @PreAuthenticated
83 - public CommonResult<Boolean> resetPassword(@RequestBody @Valid MbrAuthResetPasswordReqVO reqVO) { 78 + @OperateLog(enable = false) // 避免 Post 请求被记录操作日志
  79 + public CommonResult<Boolean> resetPassword(@RequestBody @Valid AppAuthResetPasswordReqVO reqVO) {
84 authService.resetPassword(reqVO); 80 authService.resetPassword(reqVO);
85 return success(true); 81 return success(true);
86 } 82 }
@@ -88,20 +84,11 @@ public class SysAuthController { @@ -88,20 +84,11 @@ public class SysAuthController {
88 @PostMapping("/update-password") 84 @PostMapping("/update-password")
89 @ApiOperation(value = "修改用户密码",notes = "用户修改密码时使用") 85 @ApiOperation(value = "修改用户密码",notes = "用户修改密码时使用")
90 @PreAuthenticated 86 @PreAuthenticated
91 - public CommonResult<Boolean> updatePassword(@RequestBody @Valid MbrAuthUpdatePasswordReqVO reqVO) { 87 + public CommonResult<Boolean> updatePassword(@RequestBody @Valid AppAuthUpdatePasswordReqVO reqVO) {
92 authService.updatePassword(getLoginUserId(), reqVO); 88 authService.updatePassword(getLoginUserId(), reqVO);
93 return success(true); 89 return success(true);
94 } 90 }
95 91
96 - @PostMapping("/check-sms-code")  
97 - @ApiOperation(value = "校验验证码是否正确")  
98 - @PreAuthenticated  
99 - public CommonResult<Boolean> checkSmsCode(@RequestBody @Valid SysAuthSmsLoginReqVO reqVO) {  
100 - // TODO @宋天:check 的时候,不应该使用 useSmsCode 哈,这样验证码就直接被使用了。另外,check 开头的方法,更多是校验的逻辑,不会有 update 数据的动作。这点,在方法命名上,也是要注意的  
101 - smsCodeService.useSmsCode(reqVO.getMobile(),SysSmsSceneEnum.CHECK_CODE_BY_SMS.getScene(),reqVO.getCode(),getClientIP());  
102 - return success(true);  
103 - }  
104 -  
105 // ========== 社交登录相关 ========== 92 // ========== 社交登录相关 ==========
106 93
107 @GetMapping("/social-auth-redirect") 94 @GetMapping("/social-auth-redirect")
@@ -115,32 +102,33 @@ public class SysAuthController { @@ -115,32 +102,33 @@ public class SysAuthController {
115 return CommonResult.success(socialService.getAuthorizeUrl(type, redirectUri)); 102 return CommonResult.success(socialService.getAuthorizeUrl(type, redirectUri));
116 } 103 }
117 104
118 -  
119 @PostMapping("/social-login") 105 @PostMapping("/social-login")
120 @ApiOperation("社交登录,使用 code 授权码") 106 @ApiOperation("社交登录,使用 code 授权码")
121 - public CommonResult<SysAuthLoginRespVO> socialLogin(@RequestBody @Valid MbrAuthSocialLoginReqVO reqVO) { 107 + public CommonResult<AppAuthLoginRespVO> socialLogin(@RequestBody @Valid AppAuthSocialLoginReqVO reqVO) {
122 String token = authService.socialLogin(reqVO, getClientIP(), getUserAgent()); 108 String token = authService.socialLogin(reqVO, getClientIP(), getUserAgent());
123 - return success(SysAuthLoginRespVO.builder().token(token).build()); 109 + return success(AppAuthLoginRespVO.builder().token(token).build());
124 } 110 }
125 111
126 -  
127 @PostMapping("/social-login2") 112 @PostMapping("/social-login2")
128 @ApiOperation("社交登录,使用 手机号 + 手机验证码") 113 @ApiOperation("社交登录,使用 手机号 + 手机验证码")
129 - public CommonResult<SysAuthLoginRespVO> socialLogin2(@RequestBody @Valid MbrAuthSocialLogin2ReqVO reqVO) { 114 + @OperateLog(enable = false) // 避免 Post 请求被记录操作日志
  115 + public CommonResult<AppAuthLoginRespVO> socialLogin2(@RequestBody @Valid AppAuthSocialLogin2ReqVO reqVO) {
130 String token = authService.socialLogin2(reqVO, getClientIP(), getUserAgent()); 116 String token = authService.socialLogin2(reqVO, getClientIP(), getUserAgent());
131 - return success(SysAuthLoginRespVO.builder().token(token).build()); 117 + return success(AppAuthLoginRespVO.builder().token(token).build());
132 } 118 }
133 119
134 @PostMapping("/social-bind") 120 @PostMapping("/social-bind")
135 @ApiOperation("社交绑定,使用 code 授权码") 121 @ApiOperation("社交绑定,使用 code 授权码")
136 - public CommonResult<Boolean> socialBind(@RequestBody @Valid MbrAuthSocialBindReqVO reqVO) { 122 + @PreAuthenticated
  123 + public CommonResult<Boolean> socialBind(@RequestBody @Valid AppAuthSocialBindReqVO reqVO) {
137 authService.socialBind(getLoginUserId(), reqVO); 124 authService.socialBind(getLoginUserId(), reqVO);
138 return CommonResult.success(true); 125 return CommonResult.success(true);
139 } 126 }
140 127
141 @DeleteMapping("/social-unbind") 128 @DeleteMapping("/social-unbind")
142 @ApiOperation("取消社交绑定") 129 @ApiOperation("取消社交绑定")
143 - public CommonResult<Boolean> socialUnbind(@RequestBody MbrAuthSocialUnbindReqVO reqVO) { 130 + @PreAuthenticated
  131 + public CommonResult<Boolean> socialUnbind(@RequestBody AppAuthSocialUnbindReqVO reqVO) {
144 socialService.unbindSocialUser(getLoginUserId(), reqVO.getType(), reqVO.getUnionId(), UserTypeEnum.MEMBER); 132 socialService.unbindSocialUser(getLoginUserId(), reqVO.getType(), reqVO.getUnionId(), UserTypeEnum.MEMBER);
145 return CommonResult.success(true); 133 return CommonResult.success(true);
146 } 134 }
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthCheckCodeReqVO.java 0 → 100644
  1 +package cn.iocoder.yudao.module.member.controller.app.auth.vo;
  2 +
  3 +import cn.iocoder.yudao.framework.common.validation.InEnum;
  4 +import cn.iocoder.yudao.framework.common.validation.Mobile;
  5 +import cn.iocoder.yudao.module.member.enums.sms.SysSmsSceneEnum;
  6 +import io.swagger.annotations.ApiModel;
  7 +import io.swagger.annotations.ApiModelProperty;
  8 +import lombok.AllArgsConstructor;
  9 +import lombok.Builder;
  10 +import lombok.Data;
  11 +import lombok.NoArgsConstructor;
  12 +import org.hibernate.validator.constraints.Length;
  13 +
  14 +import javax.validation.constraints.NotBlank;
  15 +import javax.validation.constraints.NotNull;
  16 +import javax.validation.constraints.Pattern;
  17 +
  18 +// TODO 芋艿:code review 相关逻辑
  19 +@ApiModel("APP 端 - 校验验证码 Request VO")
  20 +@Data
  21 +@NoArgsConstructor
  22 +@AllArgsConstructor
  23 +@Builder
  24 +public class AppAuthCheckCodeReqVO {
  25 +
  26 + @ApiModelProperty(value = "手机号", example = "15601691234")
  27 + @NotBlank(message = "手机号不能为空")
  28 + @Mobile
  29 + private String mobile;
  30 +
  31 + @ApiModelProperty(value = "手机验证码", required = true, example = "1024")
  32 + @NotBlank(message = "手机验证码不能为空")
  33 + @Length(min = 4, max = 6, message = "手机验证码长度为 4-6 位")
  34 + @Pattern(regexp = "^[0-9]+$", message = "手机验证码必须都是数字")
  35 + private String code;
  36 +
  37 + @ApiModelProperty(value = "发送场景", example = "1", notes = "对应 MbrSmsSceneEnum 枚举")
  38 + @NotNull(message = "发送场景不能为空")
  39 + @InEnum(SysSmsSceneEnum.class)
  40 + private Integer scene;
  41 +
  42 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthLoginReqVO.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginReqVO.java
1 -package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; 1 +package cn.iocoder.yudao.module.member.controller.app.auth.vo;
2 2
3 import cn.iocoder.yudao.framework.common.validation.Mobile; 3 import cn.iocoder.yudao.framework.common.validation.Mobile;
4 import io.swagger.annotations.ApiModel; 4 import io.swagger.annotations.ApiModel;
@@ -11,12 +11,12 @@ import org.hibernate.validator.constraints.Length; @@ -11,12 +11,12 @@ import org.hibernate.validator.constraints.Length;
11 11
12 import javax.validation.constraints.NotEmpty; 12 import javax.validation.constraints.NotEmpty;
13 13
14 -@ApiModel("手机 + 密码登录 Request VO") 14 +@ApiModel("APP 端 - 手机 + 密码登录 Request VO")
15 @Data 15 @Data
16 @NoArgsConstructor 16 @NoArgsConstructor
17 @AllArgsConstructor 17 @AllArgsConstructor
18 @Builder 18 @Builder
19 -public class SysAuthLoginReqVO { 19 +public class AppAuthLoginReqVO {
20 20
21 @ApiModelProperty(value = "手机号", required = true, example = "15601691300") 21 @ApiModelProperty(value = "手机号", required = true, example = "15601691300")
22 @NotEmpty(message = "手机号不能为空") 22 @NotEmpty(message = "手机号不能为空")
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthLoginRespVO.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthLoginRespVO.java
1 -package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; 1 +package cn.iocoder.yudao.module.member.controller.app.auth.vo;
2 2
3 import io.swagger.annotations.ApiModel; 3 import io.swagger.annotations.ApiModel;
4 import io.swagger.annotations.ApiModelProperty; 4 import io.swagger.annotations.ApiModelProperty;
@@ -7,12 +7,12 @@ import lombok.Builder; @@ -7,12 +7,12 @@ import lombok.Builder;
7 import lombok.Data; 7 import lombok.Data;
8 import lombok.NoArgsConstructor; 8 import lombok.NoArgsConstructor;
9 9
10 -@ApiModel("手机密码登录 Response VO") 10 +@ApiModel("APP 端 - 手机密码登录 Response VO")
11 @Data 11 @Data
12 @NoArgsConstructor 12 @NoArgsConstructor
13 @AllArgsConstructor 13 @AllArgsConstructor
14 @Builder 14 @Builder
15 -public class SysAuthLoginRespVO { 15 +public class AppAuthLoginRespVO {
16 16
17 @ApiModelProperty(value = "token", required = true, example = "yudaoyuanma") 17 @ApiModelProperty(value = "token", required = true, example = "yudaoyuanma")
18 private String token; 18 private String token;
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthResetPasswordReqVO.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthResetPasswordReqVO.java
1 -package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; 1 +package cn.iocoder.yudao.module.member.controller.app.auth.vo;
2 2
  3 +import cn.iocoder.yudao.framework.common.validation.Mobile;
3 import io.swagger.annotations.ApiModel; 4 import io.swagger.annotations.ApiModel;
4 import io.swagger.annotations.ApiModelProperty; 5 import io.swagger.annotations.ApiModelProperty;
5 import lombok.AllArgsConstructor; 6 import lombok.AllArgsConstructor;
@@ -8,15 +9,17 @@ import lombok.Data; @@ -8,15 +9,17 @@ import lombok.Data;
8 import lombok.NoArgsConstructor; 9 import lombok.NoArgsConstructor;
9 import org.hibernate.validator.constraints.Length; 10 import org.hibernate.validator.constraints.Length;
10 11
  12 +import javax.validation.constraints.NotBlank;
11 import javax.validation.constraints.NotEmpty; 13 import javax.validation.constraints.NotEmpty;
12 import javax.validation.constraints.Pattern; 14 import javax.validation.constraints.Pattern;
13 15
14 -@ApiModel("重置密码 Request VO") 16 +// TODO 芋艿:code review 相关逻辑
  17 +@ApiModel("APP 端 - 重置密码 Request VO")
15 @Data 18 @Data
16 @NoArgsConstructor 19 @NoArgsConstructor
17 @AllArgsConstructor 20 @AllArgsConstructor
18 @Builder 21 @Builder
19 -public class MbrAuthResetPasswordReqVO { 22 +public class AppAuthResetPasswordReqVO {
20 23
21 @ApiModelProperty(value = "新密码", required = true, example = "buzhidao") 24 @ApiModelProperty(value = "新密码", required = true, example = "buzhidao")
22 @NotEmpty(message = "新密码不能为空") 25 @NotEmpty(message = "新密码不能为空")
@@ -29,4 +32,9 @@ public class MbrAuthResetPasswordReqVO { @@ -29,4 +32,9 @@ public class MbrAuthResetPasswordReqVO {
29 @Pattern(regexp = "^[0-9]+$", message = "手机验证码必须都是数字") 32 @Pattern(regexp = "^[0-9]+$", message = "手机验证码必须都是数字")
30 private String code; 33 private String code;
31 34
  35 + @ApiModelProperty(value = "手机号",required = true,example = "15878962356")
  36 + @NotBlank(message = "手机号不能为空")
  37 + @Mobile
  38 + private String mobile;
  39 +
32 } 40 }
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthSendSmsReqVO.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSendSmsReqVO.java
1 -package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; 1 +package cn.iocoder.yudao.module.member.controller.app.auth.vo;
2 2
3 import cn.iocoder.yudao.framework.common.validation.InEnum; 3 import cn.iocoder.yudao.framework.common.validation.InEnum;
4 import cn.iocoder.yudao.framework.common.validation.Mobile; 4 import cn.iocoder.yudao.framework.common.validation.Mobile;
5 -import cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsSceneEnum; 5 +import cn.iocoder.yudao.module.member.enums.sms.SysSmsSceneEnum;
6 import io.swagger.annotations.ApiModel; 6 import io.swagger.annotations.ApiModel;
7 import io.swagger.annotations.ApiModelProperty; 7 import io.swagger.annotations.ApiModelProperty;
8 import lombok.Data; 8 import lombok.Data;
@@ -10,10 +10,10 @@ import lombok.experimental.Accessors; @@ -10,10 +10,10 @@ import lombok.experimental.Accessors;
10 10
11 import javax.validation.constraints.NotNull; 11 import javax.validation.constraints.NotNull;
12 12
13 -@ApiModel("发送手机验证码 Response VO") 13 +@ApiModel("APP 端 - 发送手机验证码 Response VO")
14 @Data 14 @Data
15 @Accessors(chain = true) 15 @Accessors(chain = true)
16 -public class SysAuthSendSmsReqVO { 16 +public class AppAuthSendSmsReqVO {
17 17
18 @ApiModelProperty(value = "手机号", example = "15601691234") 18 @ApiModelProperty(value = "手机号", example = "15601691234")
19 @Mobile 19 @Mobile
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/SysAuthSmsLoginReqVO.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSmsLoginReqVO.java
1 -package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; 1 +package cn.iocoder.yudao.module.member.controller.app.auth.vo;
2 2
3 import cn.iocoder.yudao.framework.common.validation.Mobile; 3 import cn.iocoder.yudao.framework.common.validation.Mobile;
4 import io.swagger.annotations.ApiModel; 4 import io.swagger.annotations.ApiModel;
@@ -12,12 +12,12 @@ import org.hibernate.validator.constraints.Length; @@ -12,12 +12,12 @@ import org.hibernate.validator.constraints.Length;
12 import javax.validation.constraints.NotEmpty; 12 import javax.validation.constraints.NotEmpty;
13 import javax.validation.constraints.Pattern; 13 import javax.validation.constraints.Pattern;
14 14
15 -@ApiModel("手机 + 验证码登录 Request VO") 15 +@ApiModel("APP 端 - 手机 + 验证码登录 Request VO")
16 @Data 16 @Data
17 @NoArgsConstructor 17 @NoArgsConstructor
18 @AllArgsConstructor 18 @AllArgsConstructor
19 @Builder 19 @Builder
20 -public class SysAuthSmsLoginReqVO { 20 +public class AppAuthSmsLoginReqVO {
21 21
22 @ApiModelProperty(value = "手机号", required = true, example = "15601691300") 22 @ApiModelProperty(value = "手机号", required = true, example = "15601691300")
23 @NotEmpty(message = "手机号不能为空") 23 @NotEmpty(message = "手机号不能为空")
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSocialBindReqVO.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSocialBindReqVO.java
1 -package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; 1 +package cn.iocoder.yudao.module.member.controller.app.auth.vo;
2 2
3 import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum; 3 import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum;
4 import cn.iocoder.yudao.framework.common.validation.InEnum; 4 import cn.iocoder.yudao.framework.common.validation.InEnum;
@@ -12,12 +12,12 @@ import lombok.NoArgsConstructor; @@ -12,12 +12,12 @@ import lombok.NoArgsConstructor;
12 import javax.validation.constraints.NotEmpty; 12 import javax.validation.constraints.NotEmpty;
13 import javax.validation.constraints.NotNull; 13 import javax.validation.constraints.NotNull;
14 14
15 -@ApiModel("社交绑定 Request VO,使用 code 授权码") 15 +@ApiModel("APP 端 - 社交绑定 Request VO,使用 code 授权码")
16 @Data 16 @Data
17 @NoArgsConstructor 17 @NoArgsConstructor
18 @AllArgsConstructor 18 @AllArgsConstructor
19 @Builder 19 @Builder
20 -public class MbrAuthSocialBindReqVO { 20 +public class AppAuthSocialBindReqVO {
21 21
22 @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 SysUserSocialTypeEnum 枚举值") 22 @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 SysUserSocialTypeEnum 枚举值")
23 @InEnum(SysSocialTypeEnum.class) 23 @InEnum(SysSocialTypeEnum.class)
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSocialLogin2ReqVO.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSocialLogin2ReqVO.java
1 -package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; 1 +package cn.iocoder.yudao.module.member.controller.app.auth.vo;
2 2
3 import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum; 3 import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum;
4 import cn.iocoder.yudao.framework.common.validation.InEnum; 4 import cn.iocoder.yudao.framework.common.validation.InEnum;
@@ -14,12 +14,12 @@ import javax.validation.constraints.NotEmpty; @@ -14,12 +14,12 @@ import javax.validation.constraints.NotEmpty;
14 import javax.validation.constraints.NotNull; 14 import javax.validation.constraints.NotNull;
15 import javax.validation.constraints.Pattern; 15 import javax.validation.constraints.Pattern;
16 16
17 -@ApiModel("社交登录 Request VO,使用 code 授权码 + 账号密码") 17 +@ApiModel("APP 端 - 社交登录 Request VO,使用 code 授权码 + 账号密码")
18 @Data 18 @Data
19 @NoArgsConstructor 19 @NoArgsConstructor
20 @AllArgsConstructor 20 @AllArgsConstructor
21 @Builder 21 @Builder
22 -public class MbrAuthSocialLogin2ReqVO { 22 +public class AppAuthSocialLogin2ReqVO {
23 23
24 @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 SysUserSocialTypeEnum 枚举值") 24 @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 SysUserSocialTypeEnum 枚举值")
25 @InEnum(SysSocialTypeEnum.class) 25 @InEnum(SysSocialTypeEnum.class)
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSocialLoginReqVO.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSocialLoginReqVO.java
1 -package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; 1 +package cn.iocoder.yudao.module.member.controller.app.auth.vo;
2 2
3 import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum; 3 import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum;
4 import cn.iocoder.yudao.framework.common.validation.InEnum; 4 import cn.iocoder.yudao.framework.common.validation.InEnum;
@@ -12,12 +12,12 @@ import lombok.NoArgsConstructor; @@ -12,12 +12,12 @@ import lombok.NoArgsConstructor;
12 import javax.validation.constraints.NotEmpty; 12 import javax.validation.constraints.NotEmpty;
13 import javax.validation.constraints.NotNull; 13 import javax.validation.constraints.NotNull;
14 14
15 -@ApiModel("社交登录 Request VO,使用 code 授权码") 15 +@ApiModel("APP 端 - 社交登录 Request VO,使用 code 授权码")
16 @Data 16 @Data
17 @NoArgsConstructor 17 @NoArgsConstructor
18 @AllArgsConstructor 18 @AllArgsConstructor
19 @Builder 19 @Builder
20 -public class MbrAuthSocialLoginReqVO { 20 +public class AppAuthSocialLoginReqVO {
21 21
22 @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 SysUserSocialTypeEnum 枚举值") 22 @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 SysUserSocialTypeEnum 枚举值")
23 @InEnum(SysSocialTypeEnum.class) 23 @InEnum(SysSocialTypeEnum.class)
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthSocialUnbindReqVO.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthSocialUnbindReqVO.java
1 -package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; 1 +package cn.iocoder.yudao.module.member.controller.app.auth.vo;
2 2
3 import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum; 3 import cn.iocoder.yudao.coreservice.modules.system.enums.social.SysSocialTypeEnum;
4 import cn.iocoder.yudao.framework.common.validation.InEnum; 4 import cn.iocoder.yudao.framework.common.validation.InEnum;
@@ -12,12 +12,12 @@ import lombok.NoArgsConstructor; @@ -12,12 +12,12 @@ import lombok.NoArgsConstructor;
12 import javax.validation.constraints.NotEmpty; 12 import javax.validation.constraints.NotEmpty;
13 import javax.validation.constraints.NotNull; 13 import javax.validation.constraints.NotNull;
14 14
15 -@ApiModel("取消社交绑定 Request VO,使用 code 授权码") 15 +@ApiModel("APP 端 - 取消社交绑定 Request VO,使用 code 授权码")
16 @Data 16 @Data
17 @NoArgsConstructor 17 @NoArgsConstructor
18 @AllArgsConstructor 18 @AllArgsConstructor
19 @Builder 19 @Builder
20 -public class MbrAuthSocialUnbindReqVO { 20 +public class AppAuthSocialUnbindReqVO {
21 21
22 @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 SysUserSocialTypeEnum 枚举值") 22 @ApiModelProperty(value = "社交平台的类型", required = true, example = "10", notes = "参见 SysUserSocialTypeEnum 枚举值")
23 @InEnum(SysSocialTypeEnum.class) 23 @InEnum(SysSocialTypeEnum.class)
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/controller/auth/vo/MbrAuthUpdatePasswordReqVO.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/auth/vo/AppAuthUpdatePasswordReqVO.java
1 -package cn.iocoder.yudao.userserver.modules.system.controller.auth.vo; 1 +package cn.iocoder.yudao.module.member.controller.app.auth.vo;
2 2
3 import io.swagger.annotations.ApiModel; 3 import io.swagger.annotations.ApiModel;
4 import io.swagger.annotations.ApiModelProperty; 4 import io.swagger.annotations.ApiModelProperty;
@@ -11,12 +11,13 @@ import org.hibernate.validator.constraints.Length; @@ -11,12 +11,13 @@ import org.hibernate.validator.constraints.Length;
11 import javax.validation.constraints.NotBlank; 11 import javax.validation.constraints.NotBlank;
12 import javax.validation.constraints.NotEmpty; 12 import javax.validation.constraints.NotEmpty;
13 13
14 -@ApiModel("修改密码 Request VO") 14 +// TODO 芋艿:code review 相关逻辑
  15 +@ApiModel("APP 端 - 修改密码 Request VO")
15 @Data 16 @Data
16 @NoArgsConstructor 17 @NoArgsConstructor
17 @AllArgsConstructor 18 @AllArgsConstructor
18 @Builder 19 @Builder
19 -public class MbrAuthUpdatePasswordReqVO { 20 +public class AppAuthUpdatePasswordReqVO {
20 21
21 @ApiModelProperty(value = "用户旧密码", required = true, example = "123456") 22 @ApiModelProperty(value = "用户旧密码", required = true, example = "123456")
22 @NotBlank(message = "旧密码不能为空") 23 @NotBlank(message = "旧密码不能为空")
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/package-info.java 0 → 100644
  1 +package cn.iocoder.yudao.module.member.controller.app;
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/controller/user/SysUserProfileController.http renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppUserController.http
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/controller/user/SysUserProfileController.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/AppUserController.java
1 -package cn.iocoder.yudao.userserver.modules.member.controller.user; 1 +package cn.iocoder.yudao.module.member.controller.app.user;
2 2
3 -import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserInfoRespVO;  
4 -import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;  
5 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 3 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
6 import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; 4 import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
7 -import cn.iocoder.yudao.userserver.modules.member.service.user.MbrUserService;  
8 -import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserUpdateMobileReqVO;  
9 -import cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsSceneEnum;  
10 -import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService; 5 +import cn.iocoder.yudao.module.member.controller.app.user.vo.AppUserInfoRespVO;
  6 +import cn.iocoder.yudao.module.member.controller.app.user.vo.AppUserUpdateMobileReqVO;
  7 +import cn.iocoder.yudao.module.member.convert.user.UserConvert;
  8 +import cn.iocoder.yudao.module.member.dal.dataobject.user.UserDO;
  9 +import cn.iocoder.yudao.module.member.service.user.UserService;
11 import io.swagger.annotations.Api; 10 import io.swagger.annotations.Api;
12 import io.swagger.annotations.ApiOperation; 11 import io.swagger.annotations.ApiOperation;
13 import lombok.extern.slf4j.Slf4j; 12 import lombok.extern.slf4j.Slf4j;
@@ -17,62 +16,55 @@ import org.springframework.web.multipart.MultipartFile; @@ -17,62 +16,55 @@ import org.springframework.web.multipart.MultipartFile;
17 16
18 import javax.annotation.Resource; 17 import javax.annotation.Resource;
19 import javax.validation.Valid; 18 import javax.validation.Valid;
20 -  
21 import java.io.IOException; 19 import java.io.IOException;
22 20
  21 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.*;
23 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 22 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
24 -import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;  
25 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; 23 import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
26 -import static cn.iocoder.yudao.userserver.modules.member.enums.MbrErrorCodeConstants.FILE_IS_EMPTY; 24 +import static cn.iocoder.yudao.module.member.enums.MemberErrorCodeConstants.FILE_IS_EMPTY;
27 25
28 -@Api(tags = "用户个人中心") 26 +@Api(tags = "APP 端 - 用户个人中心")
29 @RestController 27 @RestController
30 -@RequestMapping("/member/user/profile") 28 +@RequestMapping("/member/user")
31 @Validated 29 @Validated
32 @Slf4j 30 @Slf4j
33 -public class SysUserProfileController {  
34 -  
35 - @Resource  
36 - private MbrUserService userService; 31 +public class AppUserController {
37 32
38 @Resource 33 @Resource
39 - private SysSmsCodeService smsCodeService; 34 + private UserService userService;
40 35
41 @PutMapping("/update-nickname") 36 @PutMapping("/update-nickname")
42 @ApiOperation("修改用户昵称") 37 @ApiOperation("修改用户昵称")
43 @PreAuthenticated 38 @PreAuthenticated
44 - public CommonResult<Boolean> updateNickname(@RequestParam("nickname") String nickname) {  
45 - userService.updateNickname(getLoginUserId(), nickname); 39 + public CommonResult<Boolean> updateUserNickname(@RequestParam("nickname") String nickname) {
  40 + userService.updateUserNickname(getLoginUserId(), nickname);
46 return success(true); 41 return success(true);
47 } 42 }
48 43
49 @PutMapping("/update-avatar") 44 @PutMapping("/update-avatar")
50 @ApiOperation("修改用户头像") 45 @ApiOperation("修改用户头像")
51 @PreAuthenticated 46 @PreAuthenticated
52 - public CommonResult<String> updateAvatar(@RequestParam("avatarFile") MultipartFile file) throws IOException { 47 + public CommonResult<String> updateUserAvatar(@RequestParam("avatarFile") MultipartFile file) throws IOException {
53 if (file.isEmpty()) { 48 if (file.isEmpty()) {
54 - throw ServiceExceptionUtil.exception(FILE_IS_EMPTY); 49 + throw exception(FILE_IS_EMPTY);
55 } 50 }
56 - String avatar = userService.updateAvatar(getLoginUserId(), file.getInputStream()); 51 + String avatar = userService.updateUserAvatar(getLoginUserId(), file.getInputStream());
57 return success(avatar); 52 return success(avatar);
58 } 53 }
59 54
60 @GetMapping("/get") 55 @GetMapping("/get")
61 @ApiOperation("获得基本信息") 56 @ApiOperation("获得基本信息")
62 @PreAuthenticated 57 @PreAuthenticated
63 - public CommonResult<MbrUserInfoRespVO> getUserInfo() {  
64 - return success(userService.getUserInfo(getLoginUserId())); 58 + public CommonResult<AppUserInfoRespVO> getUserInfo() {
  59 + UserDO user = userService.getUser(getLoginUserId());
  60 + return success(UserConvert.INSTANCE.convert(user));
65 } 61 }
66 62
67 @PostMapping("/update-mobile") 63 @PostMapping("/update-mobile")
68 @ApiOperation(value = "修改用户手机") 64 @ApiOperation(value = "修改用户手机")
69 @PreAuthenticated 65 @PreAuthenticated
70 - public CommonResult<Boolean> updateMobile(@RequestBody @Valid MbrUserUpdateMobileReqVO reqVO) {  
71 - // 校验验证码  
72 - // TODO @宋天:统一到 userService.updateMobile 方法里  
73 - smsCodeService.useSmsCode(reqVO.getMobile(),SysSmsSceneEnum.CHANGE_MOBILE_BY_SMS.getScene(), reqVO.getCode(),getClientIP());  
74 -  
75 - userService.updateMobile(getLoginUserId(), reqVO); 66 + public CommonResult<Boolean> updateMobile(@RequestBody @Valid AppUserUpdateMobileReqVO reqVO) {
  67 + userService.updateUserMobile(getLoginUserId(), reqVO);
76 return success(true); 68 return success(true);
77 } 69 }
78 70
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/controller/user/vo/MbrUserInfoRespVO.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppUserInfoRespVO.java
1 -package cn.iocoder.yudao.userserver.modules.member.controller.user.vo; 1 +package cn.iocoder.yudao.module.member.controller.app.user.vo;
2 2
3 import io.swagger.annotations.ApiModel; 3 import io.swagger.annotations.ApiModel;
4 import io.swagger.annotations.ApiModelProperty; 4 import io.swagger.annotations.ApiModelProperty;
@@ -6,11 +6,11 @@ import lombok.AllArgsConstructor; @@ -6,11 +6,11 @@ import lombok.AllArgsConstructor;
6 import lombok.Data; 6 import lombok.Data;
7 import lombok.NoArgsConstructor; 7 import lombok.NoArgsConstructor;
8 8
9 -@ApiModel("用户个人信息 Response VO") 9 +@ApiModel("APP 端 - 用户个人信息 Response VO")
10 @Data 10 @Data
11 @NoArgsConstructor 11 @NoArgsConstructor
12 @AllArgsConstructor 12 @AllArgsConstructor
13 -public class MbrUserInfoRespVO { 13 +public class AppUserInfoRespVO {
14 14
15 @ApiModelProperty(value = "用户昵称", required = true, example = "芋艿") 15 @ApiModelProperty(value = "用户昵称", required = true, example = "芋艿")
16 private String nickname; 16 private String nickname;
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/controller/user/vo/MbrUserUpdateMobileReqVO.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/app/user/vo/AppUserUpdateMobileReqVO.java
1 -package cn.iocoder.yudao.userserver.modules.member.controller.user.vo; 1 +package cn.iocoder.yudao.module.member.controller.app.user.vo;
2 2
  3 +import cn.iocoder.yudao.framework.common.validation.Mobile;
3 import io.swagger.annotations.ApiModel; 4 import io.swagger.annotations.ApiModel;
4 import io.swagger.annotations.ApiModelProperty; 5 import io.swagger.annotations.ApiModelProperty;
5 import lombok.AllArgsConstructor; 6 import lombok.AllArgsConstructor;
@@ -12,12 +13,12 @@ import javax.validation.constraints.NotBlank; @@ -12,12 +13,12 @@ import javax.validation.constraints.NotBlank;
12 import javax.validation.constraints.NotEmpty; 13 import javax.validation.constraints.NotEmpty;
13 import javax.validation.constraints.Pattern; 14 import javax.validation.constraints.Pattern;
14 15
15 -@ApiModel("修改手机 Request VO") 16 +@ApiModel("APP 端 - 修改手机 Request VO")
16 @Data 17 @Data
17 @NoArgsConstructor 18 @NoArgsConstructor
18 @AllArgsConstructor 19 @AllArgsConstructor
19 @Builder 20 @Builder
20 -public class MbrUserUpdateMobileReqVO { 21 +public class AppUserUpdateMobileReqVO {
21 22
22 @ApiModelProperty(value = "手机验证码", required = true, example = "1024") 23 @ApiModelProperty(value = "手机验证码", required = true, example = "1024")
23 @NotEmpty(message = "手机验证码不能为空") 24 @NotEmpty(message = "手机验证码不能为空")
@@ -27,9 +28,22 @@ public class MbrUserUpdateMobileReqVO { @@ -27,9 +28,22 @@ public class MbrUserUpdateMobileReqVO {
27 28
28 @ApiModelProperty(value = "手机号",required = true,example = "15823654487") 29 @ApiModelProperty(value = "手机号",required = true,example = "15823654487")
29 @NotBlank(message = "手机号不能为空") 30 @NotBlank(message = "手机号不能为空")
30 - // TODO @宋天:手机校验,直接使用 @Mobile 哈  
31 @Length(min = 8, max = 11, message = "手机号码长度为 8-11 位") 31 @Length(min = 8, max = 11, message = "手机号码长度为 8-11 位")
32 - @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式错误") 32 + @Mobile
33 private String mobile; 33 private String mobile;
34 34
  35 + @ApiModelProperty(value = "原手机验证码", required = true, example = "1024")
  36 + @NotEmpty(message = "原手机验证码不能为空")
  37 + @Length(min = 4, max = 6, message = "手机验证码长度为 4-6 位")
  38 + @Pattern(regexp = "^[0-9]+$", message = "手机验证码必须都是数字")
  39 + private String oldCode;
  40 +
  41 + // TODO @芋艿:oldMobile 应该不用传递
  42 +
  43 + @ApiModelProperty(value = "原手机号",required = true,example = "15823654487")
  44 + @NotBlank(message = "手机号不能为空")
  45 + @Length(min = 8, max = 11, message = "手机号码长度为 8-11 位")
  46 + @Mobile
  47 + private String oldMobile;
  48 +
35 } 49 }
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/controller/package-info.java 0 → 100644
  1 +/**
  2 + * 提供 RESTful API 给前端:
  3 + * 1. admin 包:提供给管理后台 yudao-ui-admin 前端项目
  4 + * 2. app 包:提供给用户 APP yudao-ui-app 前端项目
  5 + */
  6 +package cn.iocoder.yudao.module.member.controller;
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/convert/auth/SysAuthConvert.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/convert/auth/AuthConvert.java
1 -package cn.iocoder.yudao.userserver.modules.system.convert.auth; 1 +package cn.iocoder.yudao.module.member.convert.auth;
2 2
3 -import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO;  
4 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; 3 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
5 import cn.iocoder.yudao.framework.security.core.LoginUser; 4 import cn.iocoder.yudao.framework.security.core.LoginUser;
  5 +import cn.iocoder.yudao.module.member.dal.dataobject.user.UserDO;
6 import org.mapstruct.Mapper; 6 import org.mapstruct.Mapper;
7 import org.mapstruct.Mapping; 7 import org.mapstruct.Mapping;
8 import org.mapstruct.factory.Mappers; 8 import org.mapstruct.factory.Mappers;
9 9
10 @Mapper 10 @Mapper
11 -public interface SysAuthConvert { 11 +public interface AuthConvert {
12 12
13 - SysAuthConvert INSTANCE = Mappers.getMapper(SysAuthConvert.class); 13 + AuthConvert INSTANCE = Mappers.getMapper(AuthConvert.class);
14 14
15 @Mapping(source = "mobile", target = "username") 15 @Mapping(source = "mobile", target = "username")
16 - LoginUser convert0(MbrUserDO bean); 16 + LoginUser convert0(UserDO bean);
17 17
18 - default LoginUser convert(MbrUserDO bean) { 18 + default LoginUser convert(UserDO bean) {
19 // 目的,为了设置 UserTypeEnum.MEMBER.getValue() 19 // 目的,为了设置 UserTypeEnum.MEMBER.getValue()
20 return convert0(bean).setUserType(UserTypeEnum.MEMBER.getValue()); 20 return convert0(bean).setUserType(UserTypeEnum.MEMBER.getValue());
21 } 21 }
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/convert/package-info.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/convert/package-info.java
@@ -3,4 +3,4 @@ @@ -3,4 +3,4 @@
3 * 3 *
4 * 目前使用 MapStruct 框架 4 * 目前使用 MapStruct 框架
5 */ 5 */
6 -package cn.iocoder.yudao.coreservice.modules.member.convert; 6 +package cn.iocoder.yudao.module.member.convert;
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/convert/user/UserConvert.java 0 → 100644
  1 +package cn.iocoder.yudao.module.member.convert.user;
  2 +
  3 +import cn.iocoder.yudao.module.member.api.user.dto.UserRespDTO;
  4 +import cn.iocoder.yudao.module.member.controller.app.user.vo.AppUserInfoRespVO;
  5 +import cn.iocoder.yudao.module.member.dal.dataobject.user.UserDO;
  6 +import org.mapstruct.Mapper;
  7 +import org.mapstruct.factory.Mappers;
  8 +
  9 +@Mapper
  10 +public interface UserConvert {
  11 +
  12 + UserConvert INSTANCE = Mappers.getMapper(UserConvert.class);
  13 +
  14 + AppUserInfoRespVO convert(UserDO bean);
  15 +
  16 + UserRespDTO convert2(UserDO bean);
  17 +}
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dal/dataobject/sms/SysSmsCodeDO.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/sms/SysSmsCodeDO.java
1 -package cn.iocoder.yudao.userserver.modules.system.dal.dataobject.sms; 1 +package cn.iocoder.yudao.module.member.dal.dataobject.sms;
2 2
3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
4 import com.baomidou.mybatisplus.annotation.TableName; 4 import com.baomidou.mybatisplus.annotation.TableName;
5 import lombok.*; 5 import lombok.*;
6 -import lombok.experimental.Accessors;  
7 6
8 import java.util.Date; 7 import java.util.Date;
9 8
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/dal/dataobject/user/MbrUserDO.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/dal/dataobject/user/UserDO.java
1 -package cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user; 1 +package cn.iocoder.yudao.module.member.dal.dataobject.user;
2 2
3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4 import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO; 4 import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
@@ -10,7 +10,7 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @@ -10,7 +10,7 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
10 import java.util.Date; 10 import java.util.Date;
11 11
12 /** 12 /**
13 - * 会员中心的用户 DO 13 + * 会员用户 DO
14 * 14 *
15 * uk_mobile 索引:基于 {@link #mobile} 字段 15 * uk_mobile 索引:基于 {@link #mobile} 字段
16 * 16 *
@@ -22,7 +22,7 @@ import java.util.Date; @@ -22,7 +22,7 @@ import java.util.Date;
22 @Builder 22 @Builder
23 @NoArgsConstructor 23 @NoArgsConstructor
24 @AllArgsConstructor 24 @AllArgsConstructor
25 -public class MbrUserDO extends TenantBaseDO { 25 +public class UserDO extends TenantBaseDO {
26 26
27 /** 27 /**
28 * 用户ID 28 * 用户ID
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dal/mysql/sms/SysSmsCodeMapper.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/sms/SysSmsCodeMapper.java
1 -package cn.iocoder.yudao.userserver.modules.system.dal.mysql.sms; 1 +package cn.iocoder.yudao.module.member.dal.mysql.sms;
2 2
3 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 3 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
4 import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; 4 import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
5 -import cn.iocoder.yudao.userserver.modules.system.dal.dataobject.sms.SysSmsCodeDO; 5 +import cn.iocoder.yudao.module.member.dal.dataobject.sms.SysSmsCodeDO;
6 import org.apache.ibatis.annotations.Mapper; 6 import org.apache.ibatis.annotations.Mapper;
7 7
  8 +// TODO @芋艿:拿到 system 模块下
8 @Mapper 9 @Mapper
9 public interface SysSmsCodeMapper extends BaseMapperX<SysSmsCodeDO> { 10 public interface SysSmsCodeMapper extends BaseMapperX<SysSmsCodeDO> {
10 11
@@ -13,14 +14,15 @@ public interface SysSmsCodeMapper extends BaseMapperX&lt;SysSmsCodeDO&gt; { @@ -13,14 +14,15 @@ public interface SysSmsCodeMapper extends BaseMapperX&lt;SysSmsCodeDO&gt; {
13 * 14 *
14 * @param mobile 手机号 15 * @param mobile 手机号
15 * @param scene 发送场景,选填 16 * @param scene 发送场景,选填
  17 + * @param code 验证码 选填
16 * @return 手机验证码 18 * @return 手机验证码
17 */ 19 */
18 - default SysSmsCodeDO selectLastByMobile(String mobile, Integer scene) { 20 + default SysSmsCodeDO selectLastByMobile(String mobile,String code,Integer scene) {
19 return selectOne(new QueryWrapperX<SysSmsCodeDO>() 21 return selectOne(new QueryWrapperX<SysSmsCodeDO>()
20 .eq("mobile", mobile) 22 .eq("mobile", mobile)
21 .eqIfPresent("scene", scene) 23 .eqIfPresent("scene", scene)
  24 + .eqIfPresent("code", code)
22 .orderByDesc("id") 25 .orderByDesc("id")
23 .last("LIMIT 1")); 26 .last("LIMIT 1"));
24 } 27 }
25 -  
26 } 28 }
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/dal/mysql/user/MbrUserMapper.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/UserMapper.java
1 -package cn.iocoder.yudao.userserver.modules.member.dal.mysql.user; 1 +package cn.iocoder.yudao.module.member.dal.mysql.user;
2 2
3 -import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO;  
4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 3 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  4 +import cn.iocoder.yudao.module.member.dal.dataobject.user.UserDO;
5 import org.apache.ibatis.annotations.Mapper; 5 import org.apache.ibatis.annotations.Mapper;
6 6
7 /** 7 /**
8 - * MbrUserDO Mapper 8 + * 会员 User Mapper
9 * 9 *
10 * @author 芋道源码 10 * @author 芋道源码
11 */ 11 */
12 @Mapper 12 @Mapper
13 -public interface MbrUserMapper extends BaseMapperX<MbrUserDO> { 13 +public interface UserMapper extends BaseMapperX<UserDO> {
14 14
15 - default MbrUserDO selectByMobile(String mobile) {  
16 - return selectOne(MbrUserDO::getMobile, mobile); 15 + default UserDO selectByMobile(String mobile) {
  16 + return selectOne(UserDO::getMobile, mobile);
17 } 17 }
18 18
19 } 19 }
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/dal/package-info.java 0 → 100644
  1 +/**
  2 + * DAL = Data Access Layer 数据访问层
  3 + * 1. data object:数据对象
  4 + * 2. redis:Redis 的 CRUD 操作
  5 + * 3. mysql:MySQL 的 CRUD 操作
  6 + *
  7 + * 其中,MySQL 的表以 mbr_ 作为前缀
  8 + */
  9 +package cn.iocoder.yudao.module.member.dal;
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/dal/redis/package-info.java 0 → 100644
  1 +/**
  2 + * 占位,后续有类后,可以删除,避免 package 无法提交到 Git 上
  3 + */
  4 +package cn.iocoder.yudao.module.member.dal.redis;
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/enums/MbrErrorCodeConstants.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/enums/MemberErrorCodeConstants.java
1 -package cn.iocoder.yudao.userserver.modules.member.enums; 1 +package cn.iocoder.yudao.module.member.enums;
2 2
3 import cn.iocoder.yudao.framework.common.exception.ErrorCode; 3 import cn.iocoder.yudao.framework.common.exception.ErrorCode;
4 4
@@ -7,11 +7,12 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; @@ -7,11 +7,12 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
7 * 7 *
8 * member 系统,使用 1-004-000-000 段 8 * member 系统,使用 1-004-000-000 段
9 */ 9 */
10 -public interface MbrErrorCodeConstants { 10 +public interface MemberErrorCodeConstants {
11 11
12 // ==========用户相关 1004001000============ 12 // ==========用户相关 1004001000============
13 ErrorCode USER_NOT_EXISTS = new ErrorCode(1004001000, "用户不存在"); 13 ErrorCode USER_NOT_EXISTS = new ErrorCode(1004001000, "用户不存在");
14 14
15 // ==========文件相关 1004002000 =========== 15 // ==========文件相关 1004002000 ===========
16 ErrorCode FILE_IS_EMPTY = new ErrorCode(1004002000, "文件为空"); 16 ErrorCode FILE_IS_EMPTY = new ErrorCode(1004002000, "文件为空");
  17 +
17 } 18 }
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/enums/SysErrorCodeConstants.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/enums/SysErrorCodeConstants.java
1 -package cn.iocoder.yudao.userserver.modules.system.enums; 1 +package cn.iocoder.yudao.module.member.enums;
2 2
3 import cn.iocoder.yudao.framework.common.exception.ErrorCode; 3 import cn.iocoder.yudao.framework.common.exception.ErrorCode;
4 4
@@ -24,9 +24,9 @@ public interface SysErrorCodeConstants { @@ -24,9 +24,9 @@ public interface SysErrorCodeConstants {
24 ErrorCode USER_SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY = new ErrorCode(1005001004, "超过每日短信发送数量"); 24 ErrorCode USER_SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY = new ErrorCode(1005001004, "超过每日短信发送数量");
25 ErrorCode USER_SMS_CODE_SEND_TOO_FAST = new ErrorCode(1005001005, "短信发送过于频率"); 25 ErrorCode USER_SMS_CODE_SEND_TOO_FAST = new ErrorCode(1005001005, "短信发送过于频率");
26 ErrorCode USER_SMS_CODE_IS_EXISTS = new ErrorCode(1005001006, "手机号已被使用"); 26 ErrorCode USER_SMS_CODE_IS_EXISTS = new ErrorCode(1005001006, "手机号已被使用");
  27 + ErrorCode USER_SMS_CODE_IS_UNUSED = new ErrorCode(1005001006, "验证码未被使用");
27 28
28 // ========== 用户模块 1005002000 ========== 29 // ========== 用户模块 1005002000 ==========
29 ErrorCode USER_NOT_EXISTS = new ErrorCode(1005002001, "用户不存在"); 30 ErrorCode USER_NOT_EXISTS = new ErrorCode(1005002001, "用户不存在");
30 - ErrorCode USER_CODE_FAILED = new ErrorCode(1005002002, "验证码不匹配");  
31 ErrorCode USER_PASSWORD_FAILED = new ErrorCode(1005002003, "密码校验失败"); 31 ErrorCode USER_PASSWORD_FAILED = new ErrorCode(1005002003, "密码校验失败");
32 } 32 }
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/enums/sms/SysSmsSceneEnum.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/enums/sms/SysSmsSceneEnum.java
1 -package cn.iocoder.yudao.userserver.modules.system.enums.sms; 1 +package cn.iocoder.yudao.module.member.enums.sms;
2 2
3 import cn.iocoder.yudao.framework.common.core.IntArrayValuable; 3 import cn.iocoder.yudao.framework.common.core.IntArrayValuable;
4 import lombok.AllArgsConstructor; 4 import lombok.AllArgsConstructor;
@@ -15,15 +15,26 @@ import java.util.Arrays; @@ -15,15 +15,26 @@ import java.util.Arrays;
15 @AllArgsConstructor 15 @AllArgsConstructor
16 public enum SysSmsSceneEnum implements IntArrayValuable { 16 public enum SysSmsSceneEnum implements IntArrayValuable {
17 17
18 - LOGIN_BY_SMS(1, "手机号登陆"),  
19 - CHANGE_MOBILE_BY_SMS(2, "更换手机号"),  
20 - FORGET_MOBILE_BY_SMS(3, "忘记密码"),  
21 - CHECK_CODE_BY_SMS(4, "审核验证码"), 18 + LOGIN_BY_SMS(1,SysSmsTemplateCodeConstants.USER_SMS_LOGIN, "手机号登陆"),
  19 + CHANGE_MOBILE_BY_SMS(2,SysSmsTemplateCodeConstants.USER_SMS_UPDATE_MOBILE, "更换手机号"),
  20 + FORGET_MOBILE_BY_SMS(3,SysSmsTemplateCodeConstants.USER_SMS_RESET_PASSWORD, "忘记密码"),
22 ; 21 ;
23 22
24 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SysSmsSceneEnum::getScene).toArray(); 23 public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(SysSmsSceneEnum::getScene).toArray();
25 24
  25 + /**
  26 + * 验证那场景编号
  27 + */
26 private final Integer scene; 28 private final Integer scene;
  29 +
  30 + /**
  31 + * 模版编码
  32 + */
  33 + private final String code;
  34 +
  35 + /**
  36 + * 描述
  37 + */
27 private final String name; 38 private final String name;
28 39
29 @Override 40 @Override
@@ -31,4 +42,13 @@ public enum SysSmsSceneEnum implements IntArrayValuable { @@ -31,4 +42,13 @@ public enum SysSmsSceneEnum implements IntArrayValuable {
31 return ARRAYS; 42 return ARRAYS;
32 } 43 }
33 44
  45 + public static String getCodeByScene(Integer scene){
  46 + for (SysSmsSceneEnum value : values()) {
  47 + if (value.getScene().equals(scene)){
  48 + return value.getCode();
  49 + }
  50 + }
  51 + return null;
  52 + }
  53 +
34 } 54 }
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/enums/sms/SysSmsTemplateCodeConstants.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/enums/sms/SysSmsTemplateCodeConstants.java
1 -package cn.iocoder.yudao.userserver.modules.system.enums.sms; 1 +package cn.iocoder.yudao.module.member.enums.sms;
2 2
3 /** 3 /**
4 * yudao-user-server 使用到的短信模板的 Code 编码的枚举 4 * yudao-user-server 使用到的短信模板的 Code 编码的枚举
@@ -12,4 +12,14 @@ public interface SysSmsTemplateCodeConstants { @@ -12,4 +12,14 @@ public interface SysSmsTemplateCodeConstants {
12 */ 12 */
13 String USER_SMS_LOGIN = "user-sms-login"; 13 String USER_SMS_LOGIN = "user-sms-login";
14 14
  15 + /**
  16 + * 用户忘记密码
  17 + */
  18 + String USER_SMS_RESET_PASSWORD = "user-sms-reset-password";
  19 +
  20 + /**
  21 + * 用户更新手机号
  22 + */
  23 + String USER_SMS_UPDATE_MOBILE = "user-sms-update-mobile";
  24 +
15 } 25 }
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/package-info.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/framework/package-info.java
1 /** 1 /**
2 - * 属于整个 yudao-user-server 的 framework 封装 2 + * 属于 yudao-module-member-impl 的封装
3 * 3 *
4 * @author 芋道源码 4 * @author 芋道源码
5 */ 5 */
6 -package cn.iocoder.yudao.userserver.framework; 6 +package cn.iocoder.yudao.module.member.framework;
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/framework/sms/SmsCodeConfiguration.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/framework/sms/SmsCodeConfiguration.java
1 -package cn.iocoder.yudao.userserver.modules.system.framework.sms; 1 +package cn.iocoder.yudao.module.member.framework.sms;
2 2
3 import org.springframework.boot.context.properties.EnableConfigurationProperties; 3 import org.springframework.boot.context.properties.EnableConfigurationProperties;
4 import org.springframework.context.annotation.Configuration; 4 import org.springframework.context.annotation.Configuration;
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/framework/sms/SmsCodeProperties.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/framework/sms/SmsCodeProperties.java
1 -package cn.iocoder.yudao.userserver.modules.system.framework.sms; 1 +package cn.iocoder.yudao.module.member.framework.sms;
2 2
3 import lombok.Data; 3 import lombok.Data;
4 import org.springframework.boot.context.properties.ConfigurationProperties; 4 import org.springframework.boot.context.properties.ConfigurationProperties;
yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/package-info.java 0 → 100644
  1 +package cn.iocoder.yudao.module.member;
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/auth/SysAuthService.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/service/auth/AuthService.java
1 -package cn.iocoder.yudao.userserver.modules.system.service.auth; 1 +package cn.iocoder.yudao.module.member.service.auth;
2 2
3 import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService; 3 import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService;
4 -import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.*; 4 +import cn.iocoder.yudao.module.member.controller.app.auth.vo.*;
5 5
6 import javax.validation.Valid; 6 import javax.validation.Valid;
7 7
8 /** 8 /**
9 - * 用户前台的认证 Service 接口 9 + * 会员的认证 Service 接口
10 * 10 *
11 * 提供用户的账号密码登录、token 的校验等认证相关的功能 11 * 提供用户的账号密码登录、token 的校验等认证相关的功能
12 * 12 *
13 * @author 芋道源码 13 * @author 芋道源码
14 */ 14 */
15 -public interface SysAuthService extends SecurityAuthFrameworkService { 15 +public interface AuthService extends SecurityAuthFrameworkService {
16 16
17 /** 17 /**
18 * 手机 + 密码登录 18 * 手机 + 密码登录
@@ -22,7 +22,7 @@ public interface SysAuthService extends SecurityAuthFrameworkService { @@ -22,7 +22,7 @@ public interface SysAuthService extends SecurityAuthFrameworkService {
22 * @param userAgent 用户 UA 22 * @param userAgent 用户 UA
23 * @return 身份令牌,使用 JWT 方式 23 * @return 身份令牌,使用 JWT 方式
24 */ 24 */
25 - String login(@Valid SysAuthLoginReqVO reqVO, String userIp, String userAgent); 25 + String login(@Valid AppAuthLoginReqVO reqVO, String userIp, String userAgent);
26 26
27 /** 27 /**
28 * 手机 + 验证码登陆 28 * 手机 + 验证码登陆
@@ -32,7 +32,7 @@ public interface SysAuthService extends SecurityAuthFrameworkService { @@ -32,7 +32,7 @@ public interface SysAuthService extends SecurityAuthFrameworkService {
32 * @param userAgent 用户 UA 32 * @param userAgent 用户 UA
33 * @return 身份令牌,使用 JWT 方式 33 * @return 身份令牌,使用 JWT 方式
34 */ 34 */
35 - String smsLogin(@Valid SysAuthSmsLoginReqVO reqVO, String userIp, String userAgent); 35 + String smsLogin(@Valid AppAuthSmsLoginReqVO reqVO, String userIp, String userAgent);
36 36
37 37
38 /** 38 /**
@@ -43,7 +43,7 @@ public interface SysAuthService extends SecurityAuthFrameworkService { @@ -43,7 +43,7 @@ public interface SysAuthService extends SecurityAuthFrameworkService {
43 * @param userAgent 用户 UA 43 * @param userAgent 用户 UA
44 * @return 身份令牌,使用 JWT 方式 44 * @return 身份令牌,使用 JWT 方式
45 */ 45 */
46 - String socialLogin(@Valid MbrAuthSocialLoginReqVO reqVO, String userIp, String userAgent); 46 + String socialLogin(@Valid AppAuthSocialLoginReqVO reqVO, String userIp, String userAgent);
47 47
48 /** 48 /**
49 * 社交登录,使用 手机号 + 手机验证码 49 * 社交登录,使用 手机号 + 手机验证码
@@ -53,7 +53,7 @@ public interface SysAuthService extends SecurityAuthFrameworkService { @@ -53,7 +53,7 @@ public interface SysAuthService extends SecurityAuthFrameworkService {
53 * @param userAgent 用户 UA 53 * @param userAgent 用户 UA
54 * @return 身份令牌,使用 JWT 方式 54 * @return 身份令牌,使用 JWT 方式
55 */ 55 */
56 - String socialLogin2(@Valid MbrAuthSocialLogin2ReqVO reqVO, String userIp, String userAgent); 56 + String socialLogin2(@Valid AppAuthSocialLogin2ReqVO reqVO, String userIp, String userAgent);
57 57
58 /** 58 /**
59 * 社交绑定,使用 code 授权码 59 * 社交绑定,使用 code 授权码
@@ -61,25 +61,19 @@ public interface SysAuthService extends SecurityAuthFrameworkService { @@ -61,25 +61,19 @@ public interface SysAuthService extends SecurityAuthFrameworkService {
61 * @param userId 用户编号 61 * @param userId 用户编号
62 * @param reqVO 绑定信息 62 * @param reqVO 绑定信息
63 */ 63 */
64 - void socialBind(Long userId, @Valid MbrAuthSocialBindReqVO reqVO); 64 + void socialBind(Long userId, @Valid AppAuthSocialBindReqVO reqVO);
65 65
66 /** 66 /**
67 * 修改用户密码 67 * 修改用户密码
68 * @param userId 用户id 68 * @param userId 用户id
69 * @param userReqVO 用户请求实体类 69 * @param userReqVO 用户请求实体类
70 */ 70 */
71 - void updatePassword(Long userId, @Valid MbrAuthUpdatePasswordReqVO userReqVO); 71 + void updatePassword(Long userId, AppAuthUpdatePasswordReqVO userReqVO);
72 72
73 /** 73 /**
74 * 忘记密码 74 * 忘记密码
75 * @param userReqVO 用户请求实体类 75 * @param userReqVO 用户请求实体类
76 */ 76 */
77 - void resetPassword(MbrAuthResetPasswordReqVO userReqVO); 77 + void resetPassword(AppAuthResetPasswordReqVO userReqVO);
78 78
79 - /**  
80 - * 检测手机与验证码是否匹配  
81 - * @param phone 手机号  
82 - * @param code 验证码  
83 - */  
84 - void checkIfMobileMatchCodeAndDeleteCode(String phone,String code);  
85 } 79 }
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/auth/impl/SysAuthServiceImpl.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/service/auth/AuthServiceImpl.java
1 -package cn.iocoder.yudao.userserver.modules.system.service.auth.impl; 1 +package cn.iocoder.yudao.module.member.service.auth;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 import cn.hutool.core.lang.Assert; 4 import cn.hutool.core.lang.Assert;
5 -import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO;  
6 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social.SysSocialUserDO; 5 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.social.SysSocialUserDO;
7 import cn.iocoder.yudao.coreservice.modules.system.enums.logger.SysLoginLogTypeEnum; 6 import cn.iocoder.yudao.coreservice.modules.system.enums.logger.SysLoginLogTypeEnum;
8 import cn.iocoder.yudao.coreservice.modules.system.enums.logger.SysLoginResultEnum; 7 import cn.iocoder.yudao.coreservice.modules.system.enums.logger.SysLoginResultEnum;
@@ -15,18 +14,18 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; @@ -15,18 +14,18 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
15 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; 14 import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
16 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; 15 import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
17 import cn.iocoder.yudao.framework.security.core.LoginUser; 16 import cn.iocoder.yudao.framework.security.core.LoginUser;
18 -import cn.iocoder.yudao.userserver.modules.member.dal.mysql.user.MbrUserMapper;  
19 -import cn.iocoder.yudao.userserver.modules.member.service.user.MbrUserService;  
20 -import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.*;  
21 -import cn.iocoder.yudao.userserver.modules.system.convert.auth.SysAuthConvert;  
22 -import cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsSceneEnum;  
23 -import cn.iocoder.yudao.userserver.modules.system.service.auth.SysAuthService;  
24 -import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService; 17 +import cn.iocoder.yudao.framework.security.core.authentication.MultiUsernamePasswordAuthenticationToken;
  18 +import cn.iocoder.yudao.module.member.controller.app.auth.vo.*;
  19 +import cn.iocoder.yudao.module.member.convert.auth.AuthConvert;
  20 +import cn.iocoder.yudao.module.member.dal.dataobject.user.UserDO;
  21 +import cn.iocoder.yudao.module.member.dal.mysql.user.UserMapper;
  22 +import cn.iocoder.yudao.module.member.enums.sms.SysSmsSceneEnum;
  23 +import cn.iocoder.yudao.module.member.service.sms.SysSmsCodeService;
  24 +import cn.iocoder.yudao.module.member.service.user.UserService;
25 import com.google.common.annotations.VisibleForTesting; 25 import com.google.common.annotations.VisibleForTesting;
26 import lombok.extern.slf4j.Slf4j; 26 import lombok.extern.slf4j.Slf4j;
27 import me.zhyd.oauth.model.AuthUser; 27 import me.zhyd.oauth.model.AuthUser;
28 import org.springframework.context.annotation.Lazy; 28 import org.springframework.context.annotation.Lazy;
29 -import org.springframework.data.redis.core.StringRedisTemplate;  
30 import org.springframework.security.authentication.AuthenticationManager; 29 import org.springframework.security.authentication.AuthenticationManager;
31 import org.springframework.security.authentication.BadCredentialsException; 30 import org.springframework.security.authentication.BadCredentialsException;
32 import org.springframework.security.authentication.DisabledException; 31 import org.springframework.security.authentication.DisabledException;
@@ -40,31 +39,28 @@ import org.springframework.stereotype.Service; @@ -40,31 +39,28 @@ import org.springframework.stereotype.Service;
40 import org.springframework.transaction.annotation.Transactional; 39 import org.springframework.transaction.annotation.Transactional;
41 40
42 import javax.annotation.Resource; 41 import javax.annotation.Resource;
43 -import javax.validation.Valid;  
44 import java.util.List; 42 import java.util.List;
45 import java.util.Objects; 43 import java.util.Objects;
46 44
47 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 45 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
48 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; 46 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
49 -import static cn.iocoder.yudao.userserver.modules.system.enums.SysErrorCodeConstants.*; 47 +import static cn.iocoder.yudao.module.member.enums.SysErrorCodeConstants.*;
50 48
51 /** 49 /**
52 - * Auth Service 实现类 50 + * 会员的认证 Service 接口
53 * 51 *
54 * @author 芋道源码 52 * @author 芋道源码
55 */ 53 */
56 @Service 54 @Service
57 @Slf4j 55 @Slf4j
58 -public class SysAuthServiceImpl implements SysAuthService {  
59 -  
60 - private static final UserTypeEnum USER_TYPE_ENUM = UserTypeEnum.MEMBER; 56 +public class AuthServiceImpl implements AuthService {
61 57
62 @Resource 58 @Resource
63 @Lazy // 延迟加载,因为存在相互依赖的问题 59 @Lazy // 延迟加载,因为存在相互依赖的问题
64 private AuthenticationManager authenticationManager; 60 private AuthenticationManager authenticationManager;
65 61
66 @Resource 62 @Resource
67 - private MbrUserService userService; 63 + private UserService userService;
68 @Resource 64 @Resource
69 private SysSmsCodeService smsCodeService; 65 private SysSmsCodeService smsCodeService;
70 @Resource 66 @Resource
@@ -75,27 +71,23 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -75,27 +71,23 @@ public class SysAuthServiceImpl implements SysAuthService {
75 private SysSocialCoreService socialService; 71 private SysSocialCoreService socialService;
76 72
77 @Resource 73 @Resource
78 - private StringRedisTemplate stringRedisTemplate;  
79 - @Resource  
80 private PasswordEncoder passwordEncoder; 74 private PasswordEncoder passwordEncoder;
81 @Resource 75 @Resource
82 - private MbrUserMapper userMapper;  
83 -  
84 - private static final UserTypeEnum userTypeEnum = UserTypeEnum.MEMBER; 76 + private UserMapper userMapper;
85 77
86 @Override 78 @Override
87 public UserDetails loadUserByUsername(String mobile) throws UsernameNotFoundException { 79 public UserDetails loadUserByUsername(String mobile) throws UsernameNotFoundException {
88 // 获取 username 对应的 SysUserDO 80 // 获取 username 对应的 SysUserDO
89 - MbrUserDO user = userService.getUserByMobile(mobile); 81 + UserDO user = userService.getUserByMobile(mobile);
90 if (user == null) { 82 if (user == null) {
91 throw new UsernameNotFoundException(mobile); 83 throw new UsernameNotFoundException(mobile);
92 } 84 }
93 // 创建 LoginUser 对象 85 // 创建 LoginUser 对象
94 - return SysAuthConvert.INSTANCE.convert(user); 86 + return AuthConvert.INSTANCE.convert(user);
95 } 87 }
96 88
97 @Override 89 @Override
98 - public String login(SysAuthLoginReqVO reqVO, String userIp, String userAgent) { 90 + public String login(AppAuthLoginReqVO reqVO, String userIp, String userAgent) {
99 // 使用手机 + 密码,进行登录。 91 // 使用手机 + 密码,进行登录。
100 LoginUser loginUser = this.login0(reqVO.getMobile(), reqVO.getPassword()); 92 LoginUser loginUser = this.login0(reqVO.getMobile(), reqVO.getPassword());
101 93
@@ -105,80 +97,77 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -105,80 +97,77 @@ public class SysAuthServiceImpl implements SysAuthService {
105 97
106 @Override 98 @Override
107 @Transactional 99 @Transactional
108 - public String smsLogin(SysAuthSmsLoginReqVO reqVO, String userIp, String userAgent) { 100 + public String smsLogin(AppAuthSmsLoginReqVO reqVO, String userIp, String userAgent) {
109 // 校验验证码 101 // 校验验证码
110 smsCodeService.useSmsCode(reqVO.getMobile(), SysSmsSceneEnum.LOGIN_BY_SMS.getScene(), 102 smsCodeService.useSmsCode(reqVO.getMobile(), SysSmsSceneEnum.LOGIN_BY_SMS.getScene(),
111 reqVO.getCode(), userIp); 103 reqVO.getCode(), userIp);
112 104
113 // 获得获得注册用户 105 // 获得获得注册用户
114 - MbrUserDO user = userService.createUserIfAbsent(reqVO.getMobile(), userIp); 106 + UserDO user = userService.createUserIfAbsent(reqVO.getMobile(), userIp);
115 Assert.notNull(user, "获取用户失败,结果为空"); 107 Assert.notNull(user, "获取用户失败,结果为空");
116 108
117 // 执行登陆 109 // 执行登陆
118 this.createLoginLog(user.getMobile(), SysLoginLogTypeEnum.LOGIN_SMS, SysLoginResultEnum.SUCCESS); 110 this.createLoginLog(user.getMobile(), SysLoginLogTypeEnum.LOGIN_SMS, SysLoginResultEnum.SUCCESS);
119 - LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user); 111 + LoginUser loginUser = AuthConvert.INSTANCE.convert(user);
120 112
121 // 缓存登录用户到 Redis 中,返回 sessionId 编号 113 // 缓存登录用户到 Redis 中,返回 sessionId 编号
122 return userSessionCoreService.createUserSession(loginUser, userIp, userAgent); 114 return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
123 } 115 }
124 116
125 @Override 117 @Override
126 - public String socialLogin(MbrAuthSocialLoginReqVO reqVO, String userIp, String userAgent) { 118 + public String socialLogin(AppAuthSocialLoginReqVO reqVO, String userIp, String userAgent) {
127 // 使用 code 授权码,进行登录 119 // 使用 code 授权码,进行登录
128 AuthUser authUser = socialService.getAuthUser(reqVO.getType(), reqVO.getCode(), reqVO.getState()); 120 AuthUser authUser = socialService.getAuthUser(reqVO.getType(), reqVO.getCode(), reqVO.getState());
129 org.springframework.util.Assert.notNull(authUser, "授权用户不为空"); 121 org.springframework.util.Assert.notNull(authUser, "授权用户不为空");
130 122
131 // 如果未绑定 SysSocialUserDO 用户,则无法自动登录,进行报错 123 // 如果未绑定 SysSocialUserDO 用户,则无法自动登录,进行报错
132 String unionId = socialService.getAuthUserUnionId(authUser); 124 String unionId = socialService.getAuthUserUnionId(authUser);
133 - List<SysSocialUserDO> socialUsers = socialService.getAllSocialUserList(reqVO.getType(), unionId, USER_TYPE_ENUM); 125 + List<SysSocialUserDO> socialUsers = socialService.getAllSocialUserList(reqVO.getType(), unionId, getUserType());
134 if (CollUtil.isEmpty(socialUsers)) { 126 if (CollUtil.isEmpty(socialUsers)) {
135 throw exception(AUTH_THIRD_LOGIN_NOT_BIND); 127 throw exception(AUTH_THIRD_LOGIN_NOT_BIND);
136 } 128 }
137 129
138 // 自动登录 130 // 自动登录
139 - MbrUserDO user = userService.getUser(socialUsers.get(0).getUserId()); 131 + UserDO user = userService.getUser(socialUsers.get(0).getUserId());
140 if (user == null) { 132 if (user == null) {
141 throw exception(USER_NOT_EXISTS); 133 throw exception(USER_NOT_EXISTS);
142 } 134 }
143 this.createLoginLog(user.getMobile(), SysLoginLogTypeEnum.LOGIN_SOCIAL, SysLoginResultEnum.SUCCESS); 135 this.createLoginLog(user.getMobile(), SysLoginLogTypeEnum.LOGIN_SOCIAL, SysLoginResultEnum.SUCCESS);
144 136
145 // 创建 LoginUser 对象 137 // 创建 LoginUser 对象
146 - LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user); 138 + LoginUser loginUser = AuthConvert.INSTANCE.convert(user);
147 139
148 // 绑定社交用户(更新) 140 // 绑定社交用户(更新)
149 - socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, USER_TYPE_ENUM); 141 + socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, getUserType());
150 142
151 // 缓存登录用户到 Redis 中,返回 sessionId 编号 143 // 缓存登录用户到 Redis 中,返回 sessionId 编号
152 return userSessionCoreService.createUserSession(loginUser, userIp, userAgent); 144 return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
153 } 145 }
154 146
155 @Override 147 @Override
156 - public String socialLogin2(MbrAuthSocialLogin2ReqVO reqVO, String userIp, String userAgent) { 148 + public String socialLogin2(AppAuthSocialLogin2ReqVO reqVO, String userIp, String userAgent) {
157 AuthUser authUser = socialService.getAuthUser(reqVO.getType(), reqVO.getCode(), reqVO.getState()); 149 AuthUser authUser = socialService.getAuthUser(reqVO.getType(), reqVO.getCode(), reqVO.getState());
158 org.springframework.util.Assert.notNull(authUser, "授权用户不为空"); 150 org.springframework.util.Assert.notNull(authUser, "授权用户不为空");
159 151
160 // 使用手机号、手机验证码登录 152 // 使用手机号、手机验证码登录
161 - SysAuthSmsLoginReqVO loginReqVO = SysAuthSmsLoginReqVO  
162 - .builder()  
163 - .mobile(reqVO.getMobile())  
164 - .code(reqVO.getSmsCode())  
165 - .build(); 153 + AppAuthSmsLoginReqVO loginReqVO = AppAuthSmsLoginReqVO.builder()
  154 + .mobile(reqVO.getMobile()).code(reqVO.getSmsCode()).build();
166 String sessionId = this.smsLogin(loginReqVO, userIp, userAgent); 155 String sessionId = this.smsLogin(loginReqVO, userIp, userAgent);
167 LoginUser loginUser = userSessionCoreService.getLoginUser(sessionId); 156 LoginUser loginUser = userSessionCoreService.getLoginUser(sessionId);
168 157
169 // 绑定社交用户(新增) 158 // 绑定社交用户(新增)
170 - socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, USER_TYPE_ENUM); 159 + socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, getUserType());
171 return sessionId; 160 return sessionId;
172 } 161 }
173 162
174 @Override 163 @Override
175 - public void socialBind(Long userId, MbrAuthSocialBindReqVO reqVO) { 164 + public void socialBind(Long userId, AppAuthSocialBindReqVO reqVO) {
176 // 使用 code 授权码,进行登录 165 // 使用 code 授权码,进行登录
177 AuthUser authUser = socialService.getAuthUser(reqVO.getType(), reqVO.getCode(), reqVO.getState()); 166 AuthUser authUser = socialService.getAuthUser(reqVO.getType(), reqVO.getCode(), reqVO.getState());
178 org.springframework.util.Assert.notNull(authUser, "授权用户不为空"); 167 org.springframework.util.Assert.notNull(authUser, "授权用户不为空");
179 168
180 // 绑定社交用户(新增) 169 // 绑定社交用户(新增)
181 - socialService.bindSocialUser(userId, reqVO.getType(), authUser, USER_TYPE_ENUM); 170 + socialService.bindSocialUser(userId, reqVO.getType(), authUser, getUserType());
182 } 171 }
183 172
184 private LoginUser login0(String username, String password) { 173 private LoginUser login0(String username, String password) {
@@ -188,7 +177,8 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -188,7 +177,8 @@ public class SysAuthServiceImpl implements SysAuthService {
188 try { 177 try {
189 // 调用 Spring Security 的 AuthenticationManager#authenticate(...) 方法,使用账号密码进行认证 178 // 调用 Spring Security 的 AuthenticationManager#authenticate(...) 方法,使用账号密码进行认证
190 // 在其内部,会调用到 loadUserByUsername 方法,获取 User 信息 179 // 在其内部,会调用到 loadUserByUsername 方法,获取 User 信息
191 - authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password)); 180 + authentication = authenticationManager.authenticate(new MultiUsernamePasswordAuthenticationToken(
  181 + username, password, getUserType()));
192 } catch (BadCredentialsException badCredentialsException) { 182 } catch (BadCredentialsException badCredentialsException) {
193 this.createLoginLog(username, logTypeEnum, SysLoginResultEnum.BAD_CREDENTIALS); 183 this.createLoginLog(username, logTypeEnum, SysLoginResultEnum.BAD_CREDENTIALS);
194 throw exception(AUTH_LOGIN_BAD_CREDENTIALS); 184 throw exception(AUTH_LOGIN_BAD_CREDENTIALS);
@@ -208,7 +198,7 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -208,7 +198,7 @@ public class SysAuthServiceImpl implements SysAuthService {
208 198
209 private void createLoginLog(String mobile, SysLoginLogTypeEnum logTypeEnum, SysLoginResultEnum loginResult) { 199 private void createLoginLog(String mobile, SysLoginLogTypeEnum logTypeEnum, SysLoginResultEnum loginResult) {
210 // 获得用户 200 // 获得用户
211 - MbrUserDO user = userService.getUserByMobile(mobile); 201 + UserDO user = userService.getUserByMobile(mobile);
212 // 插入登录日志 202 // 插入登录日志
213 SysLoginLogCreateReqDTO reqDTO = new SysLoginLogCreateReqDTO(); 203 SysLoginLogCreateReqDTO reqDTO = new SysLoginLogCreateReqDTO();
214 reqDTO.setLogType(logTypeEnum.getType()); 204 reqDTO.setLogType(logTypeEnum.getType());
@@ -246,10 +236,11 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -246,10 +236,11 @@ public class SysAuthServiceImpl implements SysAuthService {
246 return; 236 return;
247 } 237 }
248 238
249 - // 重新加载 MbrUserDO 信息  
250 - MbrUserDO user = userService.getUser(loginUser.getId()); 239 + // 重新加载 UserDO 信息
  240 + UserDO user = userService.getUser(loginUser.getId());
251 if (user == null || CommonStatusEnum.DISABLE.getStatus().equals(user.getStatus())) { 241 if (user == null || CommonStatusEnum.DISABLE.getStatus().equals(user.getStatus())) {
252 - throw exception(AUTH_TOKEN_EXPIRED); // 校验 token 时,用户被禁用的情况下,也认为 token 过期,方便前端跳转到登录界面 242 + // 校验 token 时,用户被禁用的情况下,也认为 token 过期,方便前端跳转到登录界面
  243 + throw exception(AUTH_TOKEN_EXPIRED);
253 } 244 }
254 245
255 // 刷新 LoginUser 缓存 246 // 刷新 LoginUser 缓存
@@ -258,8 +249,8 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -258,8 +249,8 @@ public class SysAuthServiceImpl implements SysAuthService {
258 249
259 @Override 250 @Override
260 public LoginUser mockLogin(Long userId) { 251 public LoginUser mockLogin(Long userId) {
261 - // 获取用户编号对应的 MbrUserDO  
262 - MbrUserDO user = userService.getUser(userId); 252 + // 获取用户编号对应的 UserDO
  253 + UserDO user = userService.getUser(userId);
263 if (user == null) { 254 if (user == null) {
264 throw new UsernameNotFoundException(String.valueOf(userId)); 255 throw new UsernameNotFoundException(String.valueOf(userId));
265 } 256 }
@@ -268,7 +259,7 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -268,7 +259,7 @@ public class SysAuthServiceImpl implements SysAuthService {
268 this.createLoginLog(user.getMobile(), SysLoginLogTypeEnum.LOGIN_MOCK, SysLoginResultEnum.SUCCESS); 259 this.createLoginLog(user.getMobile(), SysLoginLogTypeEnum.LOGIN_MOCK, SysLoginResultEnum.SUCCESS);
269 260
270 // 创建 LoginUser 对象 261 // 创建 LoginUser 对象
271 - return SysAuthConvert.INSTANCE.convert(user); 262 + return AuthConvert.INSTANCE.convert(user);
272 } 263 }
273 264
274 @Override 265 @Override
@@ -285,46 +276,35 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -285,46 +276,35 @@ public class SysAuthServiceImpl implements SysAuthService {
285 } 276 }
286 277
287 @Override 278 @Override
288 - public void updatePassword(Long userId, @Valid MbrAuthUpdatePasswordReqVO reqVO) { 279 + public UserTypeEnum getUserType() {
  280 + return UserTypeEnum.MEMBER;
  281 + }
  282 +
  283 + @Override
  284 + public void updatePassword(Long userId, AppAuthUpdatePasswordReqVO reqVO) {
289 // 检验旧密码 285 // 检验旧密码
290 - MbrUserDO userDO = checkOldPassword(userId, reqVO.getOldPassword()); 286 + UserDO userDO = checkOldPassword(userId, reqVO.getOldPassword());
291 287
292 // 更新用户密码 288 // 更新用户密码
293 - // TODO @宋天:不要更新整个对象哈  
294 - userDO.setPassword(passwordEncoder.encode(reqVO.getPassword()));  
295 - userMapper.updateById(userDO); 289 + UserDO mbrUserDO = UserDO.builder().id(userDO.getId())
  290 + .password(passwordEncoder.encode(reqVO.getPassword())).build();
  291 + userMapper.updateById(mbrUserDO);
296 } 292 }
297 293
298 @Override 294 @Override
299 - public void resetPassword(MbrAuthResetPasswordReqVO reqVO) {  
300 - // 根据验证码取出手机号,并查询用户  
301 - String mobile = stringRedisTemplate.opsForValue().get(reqVO.getCode());  
302 - MbrUserDO userDO = userMapper.selectByMobile(mobile);  
303 - if (userDO == null){  
304 - throw exception(USER_NOT_EXISTS);  
305 - }  
306 - // TODO @芋艿 这一步没必要检验验证码与手机是否匹配,因为是根据验证码去redis中查找手机号,然后根据手机号查询用户  
307 - // 也就是说 即便黑客以其他方式将验证码发送到自己手机上,最终还是会根据手机号查询用户然后进行重置密码的操作,不存在安全问题 295 + public void resetPassword(AppAuthResetPasswordReqVO reqVO) {
  296 + // 检验用户是否存在
  297 + UserDO userDO = checkUserIfExists(reqVO.getMobile());
308 298
309 - // TODO @宋天:这块微信在讨论下哈~~~  
310 -  
311 - // 校验验证码  
312 - smsCodeService.useSmsCode(userDO.getMobile(), SysSmsSceneEnum.FORGET_MOBILE_BY_SMS.getScene(), reqVO.getCode(),getClientIP()); 299 + // 使用验证码
  300 + smsCodeService.useSmsCode(reqVO.getMobile(),SysSmsSceneEnum.FORGET_MOBILE_BY_SMS.getScene(), reqVO.getCode(),
  301 + getClientIP());
313 302
314 // 更新密码 303 // 更新密码
315 - userDO.setPassword(passwordEncoder.encode(reqVO.getPassword()));  
316 - userMapper.updateById(userDO);  
317 - }  
318 -  
319 - @Override  
320 - public void checkIfMobileMatchCodeAndDeleteCode(String phone, String code) {  
321 - // 检验用户手机与验证码是否匹配  
322 - String mobile = stringRedisTemplate.opsForValue().get(code);  
323 - if (!phone.equals(mobile)){  
324 - throw exception(USER_CODE_FAILED);  
325 - }  
326 - // 销毁redis中此验证码  
327 - stringRedisTemplate.delete(code); 304 + UserDO mbrUserDO = UserDO.builder().build();
  305 + mbrUserDO.setId(userDO.getId());
  306 + mbrUserDO.setPassword(passwordEncoder.encode(reqVO.getPassword()));
  307 + userMapper.updateById(mbrUserDO);
328 } 308 }
329 309
330 /** 310 /**
@@ -332,11 +312,11 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -332,11 +312,11 @@ public class SysAuthServiceImpl implements SysAuthService {
332 * 312 *
333 * @param id 用户 id 313 * @param id 用户 id
334 * @param oldPassword 旧密码 314 * @param oldPassword 旧密码
335 - * @return MbrUserDO 用户实体 315 + * @return MemberUserDO 用户实体
336 */ 316 */
337 @VisibleForTesting 317 @VisibleForTesting
338 - public MbrUserDO checkOldPassword(Long id, String oldPassword) {  
339 - MbrUserDO user = userMapper.selectById(id); 318 + public UserDO checkOldPassword(Long id, String oldPassword) {
  319 + UserDO user = userMapper.selectById(id);
340 if (user == null) { 320 if (user == null) {
341 throw exception(USER_NOT_EXISTS); 321 throw exception(USER_NOT_EXISTS);
342 } 322 }
@@ -347,12 +327,20 @@ public class SysAuthServiceImpl implements SysAuthService { @@ -347,12 +327,20 @@ public class SysAuthServiceImpl implements SysAuthService {
347 return user; 327 return user;
348 } 328 }
349 329
  330 + public UserDO checkUserIfExists(String mobile) {
  331 + UserDO user = userMapper.selectByMobile(mobile);
  332 + if (user == null) {
  333 + throw exception(USER_NOT_EXISTS);
  334 + }
  335 + return user;
  336 + }
  337 +
350 private void createLogoutLog(Long userId, String username) { 338 private void createLogoutLog(Long userId, String username) {
351 SysLoginLogCreateReqDTO reqDTO = new SysLoginLogCreateReqDTO(); 339 SysLoginLogCreateReqDTO reqDTO = new SysLoginLogCreateReqDTO();
352 reqDTO.setLogType(SysLoginLogTypeEnum.LOGOUT_SELF.getType()); 340 reqDTO.setLogType(SysLoginLogTypeEnum.LOGOUT_SELF.getType());
353 reqDTO.setTraceId(TracerUtils.getTraceId()); 341 reqDTO.setTraceId(TracerUtils.getTraceId());
354 reqDTO.setUserId(userId); 342 reqDTO.setUserId(userId);
355 - reqDTO.setUserType(USER_TYPE_ENUM.getValue()); 343 + reqDTO.setUserType(getUserType().getValue());
356 reqDTO.setUsername(username); 344 reqDTO.setUsername(username);
357 reqDTO.setUserAgent(ServletUtils.getUserAgent()); 345 reqDTO.setUserAgent(ServletUtils.getUserAgent());
358 reqDTO.setUserIp(getClientIP()); 346 reqDTO.setUserIp(getClientIP());
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/sms/SysSmsCodeService.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/service/sms/SysSmsCodeService.java
1 -package cn.iocoder.yudao.userserver.modules.system.service.sms; 1 +package cn.iocoder.yudao.module.member.service.sms;
2 2
3 import cn.iocoder.yudao.framework.common.exception.ServiceException; 3 import cn.iocoder.yudao.framework.common.exception.ServiceException;
4 import cn.iocoder.yudao.framework.common.validation.Mobile; 4 import cn.iocoder.yudao.framework.common.validation.Mobile;
5 -import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.SysAuthSendSmsReqVO;  
6 -import cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsSceneEnum; 5 +import cn.iocoder.yudao.module.member.dal.dataobject.sms.SysSmsCodeDO;
  6 +import cn.iocoder.yudao.module.member.enums.sms.SysSmsSceneEnum;
7 7
8 /** 8 /**
9 * 短信验证码 Service 接口 9 * 短信验证码 Service 接口
@@ -15,33 +15,37 @@ public interface SysSmsCodeService { @@ -15,33 +15,37 @@ public interface SysSmsCodeService {
15 /** 15 /**
16 * 创建短信验证码,并进行发送 16 * 创建短信验证码,并进行发送
17 * 17 *
18 - * @param mobile 手机号  
19 - * @param scene 发送场景 {@link SysSmsSceneEnum} 18 + * @param mobile 手机号
  19 + * @param scene 发送场景 {@link SysSmsSceneEnum}
20 * @param createIp 发送 IP 20 * @param createIp 发送 IP
21 */ 21 */
22 void sendSmsCode(@Mobile String mobile, Integer scene, String createIp); 22 void sendSmsCode(@Mobile String mobile, Integer scene, String createIp);
23 23
24 /** 24 /**
25 - * 发送短信验证码,并检测手机号是否已被注册  
26 - * @param reqVO 请求实体  
27 - */  
28 - void sendSmsNewCode(SysAuthSendSmsReqVO reqVO);  
29 -  
30 - /**  
31 * 验证短信验证码,并进行使用 25 * 验证短信验证码,并进行使用
32 * 如果正确,则将验证码标记成已使用 26 * 如果正确,则将验证码标记成已使用
33 * 如果错误,则抛出 {@link ServiceException} 异常 27 * 如果错误,则抛出 {@link ServiceException} 异常
34 * 28 *
35 * @param mobile 手机号 29 * @param mobile 手机号
36 - * @param scene 发送场景  
37 - * @param code 验证码 30 + * @param scene 发送场景
  31 + * @param code 验证码
38 * @param usedIp 使用 IP 32 * @param usedIp 使用 IP
39 */ 33 */
40 void useSmsCode(@Mobile String mobile, Integer scene, String code, String usedIp); 34 void useSmsCode(@Mobile String mobile, Integer scene, String code, String usedIp);
41 35
42 /** 36 /**
43 * 根据用户id发送验证码 37 * 根据用户id发送验证码
  38 + *
44 * @param userId 用户id 39 * @param userId 用户id
45 */ 40 */
46 void sendSmsCodeLogin(Long userId); 41 void sendSmsCodeLogin(Long userId);
  42 +
  43 + /**
  44 + * 检查验证码是否有效
  45 + * @param mobile 手机
  46 + * @param code 验证码
  47 + * @param scene 使用场景
  48 + * @return 验证码记录
  49 + */
  50 + SysSmsCodeDO checkCodeIsExpired(String mobile, String code, Integer scene);
47 } 51 }
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/service/sms/impl/SysSmsCodeServiceImpl.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/service/sms/SysSmsCodeServiceImpl.java
1 -package cn.iocoder.yudao.userserver.modules.system.service.sms.impl; 1 +package cn.iocoder.yudao.module.member.service.sms;
2 2
3 import cn.hutool.core.map.MapUtil; 3 import cn.hutool.core.map.MapUtil;
4 -import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO;  
5 import cn.iocoder.yudao.coreservice.modules.system.service.sms.SysSmsCoreService; 4 import cn.iocoder.yudao.coreservice.modules.system.service.sms.SysSmsCoreService;
6 -import cn.iocoder.yudao.userserver.modules.member.service.user.MbrUserService;  
7 -import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.SysAuthSendSmsReqVO;  
8 -import cn.iocoder.yudao.userserver.modules.system.dal.dataobject.sms.SysSmsCodeDO;  
9 -import cn.iocoder.yudao.userserver.modules.system.dal.mysql.sms.SysSmsCodeMapper;  
10 -import cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsSceneEnum;  
11 -import cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsTemplateCodeConstants;  
12 -import cn.iocoder.yudao.userserver.modules.system.framework.sms.SmsCodeProperties;  
13 -import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService;  
14 -import org.springframework.data.redis.core.StringRedisTemplate; 5 +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
  6 +import cn.iocoder.yudao.module.member.dal.dataobject.sms.SysSmsCodeDO;
  7 +import cn.iocoder.yudao.module.member.dal.dataobject.user.UserDO;
  8 +import cn.iocoder.yudao.module.member.dal.mysql.sms.SysSmsCodeMapper;
  9 +import cn.iocoder.yudao.module.member.enums.sms.SysSmsSceneEnum;
  10 +import cn.iocoder.yudao.module.member.framework.sms.SmsCodeProperties;
  11 +import cn.iocoder.yudao.module.member.service.user.UserService;
15 import org.springframework.stereotype.Service; 12 import org.springframework.stereotype.Service;
16 import org.springframework.validation.annotation.Validated; 13 import org.springframework.validation.annotation.Validated;
17 14
18 import javax.annotation.Resource; 15 import javax.annotation.Resource;
19 import java.util.Date; 16 import java.util.Date;
20 -import java.util.concurrent.TimeUnit;  
21 17
22 import static cn.hutool.core.util.RandomUtil.randomInt; 18 import static cn.hutool.core.util.RandomUtil.randomInt;
23 -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;  
24 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; 19 import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
25 -import static cn.iocoder.yudao.userserver.modules.system.enums.SysErrorCodeConstants.*; 20 +import static cn.iocoder.yudao.module.member.enums.SysErrorCodeConstants.*;
26 21
27 /** 22 /**
28 * 短信验证码 Service 实现类 23 * 短信验证码 Service 实现类
@@ -33,11 +28,6 @@ import static cn.iocoder.yudao.userserver.modules.system.enums.SysErrorCodeConst @@ -33,11 +28,6 @@ import static cn.iocoder.yudao.userserver.modules.system.enums.SysErrorCodeConst
33 @Validated 28 @Validated
34 public class SysSmsCodeServiceImpl implements SysSmsCodeService { 29 public class SysSmsCodeServiceImpl implements SysSmsCodeService {
35 30
36 - /**  
37 - * 验证码 + 手机 在redis中存储的有效时间,单位:分钟  
38 - */  
39 - private static final Long CODE_TIME = 10L;  
40 -  
41 @Resource 31 @Resource
42 private SmsCodeProperties smsCodeProperties; 32 private SmsCodeProperties smsCodeProperties;
43 33
@@ -45,52 +35,50 @@ public class SysSmsCodeServiceImpl implements SysSmsCodeService { @@ -45,52 +35,50 @@ public class SysSmsCodeServiceImpl implements SysSmsCodeService {
45 private SysSmsCodeMapper smsCodeMapper; 35 private SysSmsCodeMapper smsCodeMapper;
46 36
47 @Resource 37 @Resource
48 - private MbrUserService mbrUserService; 38 + private UserService userService;
49 39
50 @Resource 40 @Resource
51 private SysSmsCoreService smsCoreService; 41 private SysSmsCoreService smsCoreService;
52 42
53 - @Resource  
54 - private StringRedisTemplate stringRedisTemplate;  
55 -  
56 @Override 43 @Override
57 public void sendSmsCode(String mobile, Integer scene, String createIp) { 44 public void sendSmsCode(String mobile, Integer scene, String createIp) {
58 // 创建验证码 45 // 创建验证码
59 String code = this.createSmsCode(mobile, scene, createIp); 46 String code = this.createSmsCode(mobile, scene, createIp);
  47 +
  48 + // 获取发送模板
  49 + String codeTemplate = SysSmsSceneEnum.getCodeByScene(scene);
  50 +
  51 + // 如果是更换手机号发送验证码,则需要检测手机号是否被注册
  52 + if (SysSmsSceneEnum.CHANGE_MOBILE_BY_SMS.getScene().equals(scene)){
  53 + this.checkMobileIsRegister(mobile,scene);
  54 + }
  55 +
60 // 发送验证码 56 // 发送验证码
61 - // TODO @宋天:这里可以拓展下 SysSmsSceneEnum,支持设置对应的短信模板编号(不同场景的短信文案是不同的)、是否要校验手机号已经注册。这样 Controller 就可以收口成一个接口了。相当于说,不同场景,不同策略  
62 - smsCoreService.sendSingleSmsToMember(mobile, null, SysSmsTemplateCodeConstants.USER_SMS_LOGIN, 57 + smsCoreService.sendSingleSmsToMember(mobile, null, codeTemplate,
63 MapUtil.of("code", code)); 58 MapUtil.of("code", code));
64 -  
65 - // 存储手机号与验证码到redis,用于标记  
66 - // TODO @宋天:SysSmsCodeDO 表应该足够,无需增加额外的 redis 存储哇  
67 - // TODO @宋天:Redis 相关的操作,不要散落到业务层,而是写一个它对应的 RedisDAO。这样,实现业务与技术的解耦  
68 - // TODO @宋天:直接使用 code 作为 key,会存在 2 个问题:1)code 可能会冲突,多个手机号之间;2)缺少前缀。例如说 sms_code_${code}  
69 - stringRedisTemplate.opsForValue().set(code,mobile,CODE_TIME, TimeUnit.MINUTES);  
70 } 59 }
71 60
72 - @Override  
73 - public void sendSmsNewCode(SysAuthSendSmsReqVO reqVO) { 61 + public void checkMobileIsRegister(String mobile, Integer scene) {
74 // 检测手机号是否已被使用 62 // 检测手机号是否已被使用
75 - MbrUserDO userByMobile = mbrUserService.getUserByMobile(reqVO.getMobile());  
76 - if (userByMobile != null){  
77 - throw exception(USER_SMS_CODE_IS_EXISTS); 63 + UserDO user = userService.getUserByMobile(mobile);
  64 + if (user != null) {
  65 + throw ServiceExceptionUtil.exception(USER_SMS_CODE_IS_EXISTS);
78 } 66 }
79 67
80 // 发送短信 68 // 发送短信
81 - this.sendSmsCode(reqVO.getMobile(),reqVO.getScene(),getClientIP()); 69 + this.sendSmsCode(mobile,scene,getClientIP());
82 } 70 }
83 71
84 private String createSmsCode(String mobile, Integer scene, String ip) { 72 private String createSmsCode(String mobile, Integer scene, String ip) {
85 // 校验是否可以发送验证码,不用筛选场景 73 // 校验是否可以发送验证码,不用筛选场景
86 - SysSmsCodeDO lastSmsCode = smsCodeMapper.selectLastByMobile(mobile, null); 74 + SysSmsCodeDO lastSmsCode = smsCodeMapper.selectLastByMobile(mobile, null,null);
87 if (lastSmsCode != null) { 75 if (lastSmsCode != null) {
88 if (lastSmsCode.getTodayIndex() >= smsCodeProperties.getSendMaximumQuantityPerDay()) { // 超过当天发送的上限。 76 if (lastSmsCode.getTodayIndex() >= smsCodeProperties.getSendMaximumQuantityPerDay()) { // 超过当天发送的上限。
89 - throw exception(USER_SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY); 77 + throw ServiceExceptionUtil.exception(USER_SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY);
90 } 78 }
91 if (System.currentTimeMillis() - lastSmsCode.getCreateTime().getTime() 79 if (System.currentTimeMillis() - lastSmsCode.getCreateTime().getTime()
92 < smsCodeProperties.getSendFrequency().toMillis()) { // 发送过于频繁 80 < smsCodeProperties.getSendFrequency().toMillis()) { // 发送过于频繁
93 - throw exception(USER_SMS_CODE_SEND_TOO_FAST); 81 + throw ServiceExceptionUtil.exception(USER_SMS_CODE_SEND_TOO_FAST);
94 } 82 }
95 // TODO 芋艿:提升,每个 IP 每天可发送数量 83 // TODO 芋艿:提升,每个 IP 每天可发送数量
96 // TODO 芋艿:提升,每个 IP 每小时可发送数量 84 // TODO 芋艿:提升,每个 IP 每小时可发送数量
@@ -107,20 +95,12 @@ public class SysSmsCodeServiceImpl implements SysSmsCodeService { @@ -107,20 +95,12 @@ public class SysSmsCodeServiceImpl implements SysSmsCodeService {
107 95
108 @Override 96 @Override
109 public void useSmsCode(String mobile, Integer scene, String code, String usedIp) { 97 public void useSmsCode(String mobile, Integer scene, String code, String usedIp) {
110 - // 校验验证码  
111 - SysSmsCodeDO lastSmsCode = smsCodeMapper.selectLastByMobile(mobile, scene);  
112 - if (lastSmsCode == null) { // 若验证码不存在,抛出异常  
113 - throw exception(USER_SMS_CODE_NOT_FOUND);  
114 - }  
115 - if (System.currentTimeMillis() - lastSmsCode.getCreateTime().getTime()  
116 - >= smsCodeProperties.getExpireTimes().toMillis()) { // 验证码已过期  
117 - throw exception(USER_SMS_CODE_EXPIRED);  
118 - }  
119 - if (lastSmsCode.getUsed()) { // 验证码已使用  
120 - throw exception(USER_SMS_CODE_USED);  
121 - }  
122 - if (!lastSmsCode.getCode().equals(code)) {  
123 - throw exception(USER_SMS_CODE_NOT_CORRECT); 98 + // 检测验证码是否有效
  99 + SysSmsCodeDO lastSmsCode = this.checkCodeIsExpired(mobile, code, scene);
  100 +
  101 + // 判断验证码是否已被使用
  102 + if (Boolean.TRUE.equals(lastSmsCode.getUsed())) {
  103 + throw ServiceExceptionUtil.exception(USER_SMS_CODE_USED);
124 } 104 }
125 105
126 // 使用验证码 106 // 使用验证码
@@ -130,12 +110,28 @@ public class SysSmsCodeServiceImpl implements SysSmsCodeService { @@ -130,12 +110,28 @@ public class SysSmsCodeServiceImpl implements SysSmsCodeService {
130 110
131 @Override 111 @Override
132 public void sendSmsCodeLogin(Long userId) { 112 public void sendSmsCodeLogin(Long userId) {
133 - MbrUserDO user = mbrUserService.getUser(userId); 113 + UserDO user = userService.getUser(userId);
134 if (user == null){ 114 if (user == null){
135 - throw exception(USER_NOT_EXISTS); 115 + throw ServiceExceptionUtil.exception(USER_NOT_EXISTS);
136 } 116 }
137 // 发送验证码 117 // 发送验证码
138 this.sendSmsCode(user.getMobile(),SysSmsSceneEnum.CHANGE_MOBILE_BY_SMS.getScene(), getClientIP()); 118 this.sendSmsCode(user.getMobile(),SysSmsSceneEnum.CHANGE_MOBILE_BY_SMS.getScene(), getClientIP());
139 } 119 }
140 120
  121 + @Override
  122 + public SysSmsCodeDO checkCodeIsExpired(String mobile, String code, Integer scene) {
  123 + // 校验验证码
  124 + SysSmsCodeDO lastSmsCode = smsCodeMapper.selectLastByMobile(mobile,code,scene);
  125 +
  126 + // 若验证码不存在,抛出异常
  127 + if (lastSmsCode == null) {
  128 + throw ServiceExceptionUtil.exception(USER_SMS_CODE_NOT_FOUND);
  129 + }
  130 + if (System.currentTimeMillis() - lastSmsCode.getCreateTime().getTime()
  131 + >= smsCodeProperties.getExpireTimes().toMillis()) { // 验证码已过期
  132 + throw ServiceExceptionUtil.exception(USER_SMS_CODE_EXPIRED);
  133 + }
  134 + return lastSmsCode;
  135 + }
  136 +
141 } 137 }
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/service/user/MbrUserService.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/service/user/UserService.java
1 -package cn.iocoder.yudao.userserver.modules.member.service.user; 1 +package cn.iocoder.yudao.module.member.service.user;
2 2
3 -import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO;  
4 -import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserInfoRespVO;  
5 import cn.iocoder.yudao.framework.common.validation.Mobile; 3 import cn.iocoder.yudao.framework.common.validation.Mobile;
6 -import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserUpdateMobileReqVO; 4 +import cn.iocoder.yudao.module.member.controller.app.user.vo.AppUserInfoRespVO;
  5 +import cn.iocoder.yudao.module.member.controller.app.user.vo.AppUserUpdateMobileReqVO;
  6 +import cn.iocoder.yudao.module.member.dal.dataobject.user.UserDO;
7 7
8 import java.io.InputStream; 8 import java.io.InputStream;
9 9
10 /** 10 /**
11 - * 前台用户 Service 接口 11 + * 会员用户 Service 接口
12 * 12 *
13 * @author 芋道源码 13 * @author 芋道源码
14 */ 14 */
15 -public interface MbrUserService { 15 +public interface UserService {
16 16
17 /** 17 /**
18 * 通过手机查询用户 18 * 通过手机查询用户
@@ -20,7 +20,7 @@ public interface MbrUserService { @@ -20,7 +20,7 @@ public interface MbrUserService {
20 * @param mobile 手机 20 * @param mobile 手机
21 * @return 用户对象 21 * @return 用户对象
22 */ 22 */
23 - MbrUserDO getUserByMobile(String mobile); 23 + UserDO getUserByMobile(String mobile);
24 24
25 /** 25 /**
26 * 基于手机号创建用户。 26 * 基于手机号创建用户。
@@ -30,7 +30,7 @@ public interface MbrUserService { @@ -30,7 +30,7 @@ public interface MbrUserService {
30 * @param registerIp 注册 IP 30 * @param registerIp 注册 IP
31 * @return 用户对象 31 * @return 用户对象
32 */ 32 */
33 - MbrUserDO createUserIfAbsent(@Mobile String mobile, String registerIp); 33 + UserDO createUserIfAbsent(@Mobile String mobile, String registerIp);
34 34
35 /** 35 /**
36 * 更新用户的最后登陆信息 36 * 更新用户的最后登陆信息
@@ -46,14 +46,14 @@ public interface MbrUserService { @@ -46,14 +46,14 @@ public interface MbrUserService {
46 * @param id 用户ID 46 * @param id 用户ID
47 * @return 用户对象信息 47 * @return 用户对象信息
48 */ 48 */
49 - MbrUserDO getUser(Long id); 49 + UserDO getUser(Long id);
50 50
51 /** 51 /**
52 * 修改用户昵称 52 * 修改用户昵称
53 * @param userId 用户id 53 * @param userId 用户id
54 * @param nickname 用户新昵称 54 * @param nickname 用户新昵称
55 */ 55 */
56 - void updateNickname(Long userId, String nickname); 56 + void updateUserNickname(Long userId, String nickname);
57 57
58 /** 58 /**
59 * 修改用户头像 59 * 修改用户头像
@@ -61,21 +61,13 @@ public interface MbrUserService { @@ -61,21 +61,13 @@ public interface MbrUserService {
61 * @param inputStream 头像文件 61 * @param inputStream 头像文件
62 * @return 头像url 62 * @return 头像url
63 */ 63 */
64 - String updateAvatar(Long userId, InputStream inputStream);  
65 -  
66 - /**  
67 - * 根据用户id,获取用户头像与昵称  
68 - *  
69 - * @param userId 用户id  
70 - * @return 用户响应实体类  
71 - */  
72 - MbrUserInfoRespVO getUserInfo(Long userId); 64 + String updateUserAvatar(Long userId, InputStream inputStream);
73 65
74 /** 66 /**
75 * 修改手机 67 * 修改手机
76 * @param userId 用户id 68 * @param userId 用户id
77 * @param reqVO 请求实体 69 * @param reqVO 请求实体
78 */ 70 */
79 - void updateMobile(Long userId, MbrUserUpdateMobileReqVO reqVO); 71 + void updateUserMobile(Long userId, AppUserUpdateMobileReqVO reqVO);
80 72
81 } 73 }
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/member/service/user/impl/MbrUserServiceImpl.java renamed to yudao-module-member/yudao-module-member-impl/src/main/java/cn/iocoder/yudao/module/member/service/user/UserServiceImpl.java
1 -package cn.iocoder.yudao.userserver.modules.member.service.user.impl; 1 +package cn.iocoder.yudao.module.member.service.user;
2 2
3 import cn.hutool.core.io.IoUtil; 3 import cn.hutool.core.io.IoUtil;
4 import cn.hutool.core.util.IdUtil; 4 import cn.hutool.core.util.IdUtil;
5 import cn.iocoder.yudao.coreservice.modules.infra.service.file.InfFileCoreService; 5 import cn.iocoder.yudao.coreservice.modules.infra.service.file.InfFileCoreService;
6 -import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO;  
7 -import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserInfoRespVO;  
8 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 6 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
9 -import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserUpdateMobileReqVO;  
10 -import cn.iocoder.yudao.userserver.modules.member.convert.user.UserProfileConvert;  
11 -import cn.iocoder.yudao.userserver.modules.member.dal.mysql.user.MbrUserMapper;  
12 -import cn.iocoder.yudao.userserver.modules.member.service.user.MbrUserService;  
13 -import cn.iocoder.yudao.userserver.modules.system.service.auth.SysAuthService; 7 +import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
  8 +import cn.iocoder.yudao.module.member.controller.app.user.vo.AppUserUpdateMobileReqVO;
  9 +import cn.iocoder.yudao.module.member.dal.dataobject.sms.SysSmsCodeDO;
  10 +import cn.iocoder.yudao.module.member.dal.dataobject.user.UserDO;
  11 +import cn.iocoder.yudao.module.member.dal.mysql.user.UserMapper;
  12 +import cn.iocoder.yudao.module.member.enums.SysErrorCodeConstants;
  13 +import cn.iocoder.yudao.module.member.enums.sms.SysSmsSceneEnum;
  14 +import cn.iocoder.yudao.module.member.service.sms.SysSmsCodeService;
14 import com.google.common.annotations.VisibleForTesting; 15 import com.google.common.annotations.VisibleForTesting;
15 import lombok.extern.slf4j.Slf4j; 16 import lombok.extern.slf4j.Slf4j;
16 import org.springframework.security.crypto.password.PasswordEncoder; 17 import org.springframework.security.crypto.password.PasswordEncoder;
17 import org.springframework.stereotype.Service; 18 import org.springframework.stereotype.Service;
  19 +import org.springframework.transaction.annotation.Transactional;
18 20
19 import javax.annotation.Resource; 21 import javax.annotation.Resource;
20 import javax.validation.Valid; 22 import javax.validation.Valid;
@@ -22,39 +24,39 @@ import java.io.InputStream; @@ -22,39 +24,39 @@ import java.io.InputStream;
22 import java.util.Date; 24 import java.util.Date;
23 25
24 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 26 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
25 -import static cn.iocoder.yudao.userserver.modules.member.enums.MbrErrorCodeConstants.USER_NOT_EXISTS; 27 +import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
  28 +import static cn.iocoder.yudao.module.member.enums.MemberErrorCodeConstants.USER_NOT_EXISTS;
26 29
27 /** 30 /**
28 - * User Service 实现类 31 + * 会员 User Service 实现类
29 * 32 *
30 * @author 芋道源码 33 * @author 芋道源码
31 */ 34 */
32 @Service 35 @Service
33 @Valid 36 @Valid
34 @Slf4j 37 @Slf4j
35 -public class MbrUserServiceImpl implements MbrUserService { 38 +public class UserServiceImpl implements UserService {
36 39
37 @Resource 40 @Resource
38 - private MbrUserMapper userMapper; 41 + private UserMapper memberUserMapper;
39 42
40 @Resource 43 @Resource
41 private InfFileCoreService fileCoreService; 44 private InfFileCoreService fileCoreService;
42 -  
43 @Resource 45 @Resource
44 - private PasswordEncoder passwordEncoder; 46 + private SysSmsCodeService smsCodeService;
45 47
46 @Resource 48 @Resource
47 - private SysAuthService sysAuthService; 49 + private PasswordEncoder passwordEncoder;
48 50
49 @Override 51 @Override
50 - public MbrUserDO getUserByMobile(String mobile) {  
51 - return userMapper.selectByMobile(mobile); 52 + public UserDO getUserByMobile(String mobile) {
  53 + return memberUserMapper.selectByMobile(mobile);
52 } 54 }
53 55
54 @Override 56 @Override
55 - public MbrUserDO createUserIfAbsent(String mobile, String registerIp) { 57 + public UserDO createUserIfAbsent(String mobile, String registerIp) {
56 // 用户已经存在 58 // 用户已经存在
57 - MbrUserDO user = userMapper.selectByMobile(mobile); 59 + UserDO user = memberUserMapper.selectByMobile(mobile);
58 if (user != null) { 60 if (user != null) {
59 return user; 61 return user;
60 } 62 }
@@ -62,86 +64,84 @@ public class MbrUserServiceImpl implements MbrUserService { @@ -62,86 +64,84 @@ public class MbrUserServiceImpl implements MbrUserService {
62 return this.createUser(mobile, registerIp); 64 return this.createUser(mobile, registerIp);
63 } 65 }
64 66
65 - private MbrUserDO createUser(String mobile, String registerIp) { 67 + private UserDO createUser(String mobile, String registerIp) {
66 // 生成密码 68 // 生成密码
67 String password = IdUtil.fastSimpleUUID(); 69 String password = IdUtil.fastSimpleUUID();
68 // 插入用户 70 // 插入用户
69 - MbrUserDO user = new MbrUserDO(); 71 + UserDO user = new UserDO();
70 user.setMobile(mobile); 72 user.setMobile(mobile);
71 user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启 73 user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启
72 user.setPassword(passwordEncoder.encode(password)); // 加密密码 74 user.setPassword(passwordEncoder.encode(password)); // 加密密码
73 user.setRegisterIp(registerIp); 75 user.setRegisterIp(registerIp);
74 - userMapper.insert(user); 76 + memberUserMapper.insert(user);
75 return user; 77 return user;
76 } 78 }
77 79
78 @Override 80 @Override
79 public void updateUserLogin(Long id, String loginIp) { 81 public void updateUserLogin(Long id, String loginIp) {
80 - userMapper.updateById(new MbrUserDO().setId(id).setLoginIp(loginIp).setLoginDate(new Date())); 82 + memberUserMapper.updateById(new UserDO().setId(id)
  83 + .setLoginIp(loginIp).setLoginDate(new Date()));
81 } 84 }
82 85
83 @Override 86 @Override
84 - public MbrUserDO getUser(Long id) {  
85 - return userMapper.selectById(id); 87 + public UserDO getUser(Long id) {
  88 + return memberUserMapper.selectById(id);
86 } 89 }
87 90
88 @Override 91 @Override
89 - public void updateNickname(Long userId, String nickname) {  
90 - MbrUserDO user = this.checkUserExists(userId); 92 + public void updateUserNickname(Long userId, String nickname) {
  93 + UserDO user = this.checkUserExists(userId);
91 // 仅当新昵称不等于旧昵称时进行修改 94 // 仅当新昵称不等于旧昵称时进行修改
92 if (nickname.equals(user.getNickname())){ 95 if (nickname.equals(user.getNickname())){
93 return; 96 return;
94 } 97 }
95 - MbrUserDO userDO = new MbrUserDO(); 98 + UserDO userDO = new UserDO();
96 userDO.setId(user.getId()); 99 userDO.setId(user.getId());
97 userDO.setNickname(nickname); 100 userDO.setNickname(nickname);
98 - userMapper.updateById(userDO); 101 + memberUserMapper.updateById(userDO);
99 } 102 }
100 103
101 @Override 104 @Override
102 - public String updateAvatar(Long userId, InputStream avatarFile) { 105 + public String updateUserAvatar(Long userId, InputStream avatarFile) {
103 this.checkUserExists(userId); 106 this.checkUserExists(userId);
104 // 创建文件 107 // 创建文件
105 String avatar = fileCoreService.createFile(IdUtil.fastUUID(), IoUtil.readBytes(avatarFile)); 108 String avatar = fileCoreService.createFile(IdUtil.fastUUID(), IoUtil.readBytes(avatarFile));
106 // 更新头像路径 109 // 更新头像路径
107 - MbrUserDO userDO = MbrUserDO.builder()  
108 - .id(userId)  
109 - .avatar(avatar)  
110 - .build();  
111 - userMapper.updateById(userDO); 110 + memberUserMapper.updateById(UserDO.builder().id(userId).avatar(avatar).build());
112 return avatar; 111 return avatar;
113 } 112 }
114 113
115 - @Override  
116 - public MbrUserInfoRespVO getUserInfo(Long userId) {  
117 - MbrUserDO user = this.checkUserExists(userId);  
118 - // 拼接返回结果  
119 - return UserProfileConvert.INSTANCE.convert(user);  
120 - }  
121 -  
122 - @Override  
123 - public void updateMobile(Long userId, MbrUserUpdateMobileReqVO reqVO) { 114 + @Transactional(rollbackFor = Exception.class)
  115 + public void updateUserMobile(Long userId, AppUserUpdateMobileReqVO reqVO) {
124 // 检测用户是否存在 116 // 检测用户是否存在
125 - MbrUserDO userDO = checkUserExists(userId);  
126 - // 检测手机与验证码是否匹配  
127 - // TODO @宋天:修改手机的时候。应该要校验,老手机 + 老手机 code;新手机 + 新手机 code  
128 - sysAuthService.checkIfMobileMatchCodeAndDeleteCode(userDO.getMobile(),reqVO.getCode()); 117 + checkUserExists(userId);
  118 +
  119 + // 校验旧手机和旧验证码
  120 + SysSmsCodeDO sysSmsCodeDO = smsCodeService.checkCodeIsExpired(reqVO.getOldMobile(), reqVO.getOldCode(),
  121 + SysSmsSceneEnum.CHANGE_MOBILE_BY_SMS.getScene());
  122 + // 判断旧 code 是否未被使用,如果是,抛出异常
  123 + if (Boolean.FALSE.equals(sysSmsCodeDO.getUsed())){
  124 + throw ServiceExceptionUtil.exception(SysErrorCodeConstants.USER_SMS_CODE_IS_UNUSED);
  125 + }
  126 +
  127 + // 使用新验证码
  128 + smsCodeService.useSmsCode(reqVO.getMobile(), SysSmsSceneEnum.CHANGE_MOBILE_BY_SMS.getScene(),
  129 + reqVO.getCode(),getClientIP());
  130 +
129 // 更新用户手机 131 // 更新用户手机
130 - // TODO @宋天:更新的时候,单独创建对象。直接全量更新,会可能导致属性覆盖。可以看看打印出来的 SQL 哈  
131 - userDO.setMobile(reqVO.getMobile());  
132 - userMapper.updateById(userDO); 132 + memberUserMapper.updateById(UserDO.builder().id(userId).mobile(reqVO.getMobile()).build());
133 } 133 }
134 134
135 @VisibleForTesting 135 @VisibleForTesting
136 - public MbrUserDO checkUserExists(Long id) { 136 + public UserDO checkUserExists(Long id) {
137 if (id == null) { 137 if (id == null) {
138 return null; 138 return null;
139 } 139 }
140 - MbrUserDO user = userMapper.selectById(id); 140 + UserDO user = memberUserMapper.selectById(id);
141 if (user == null) { 141 if (user == null) {
142 throw exception(USER_NOT_EXISTS); 142 throw exception(USER_NOT_EXISTS);
143 - }else{  
144 - return user;  
145 } 143 }
  144 + return user;
146 } 145 }
  146 +
147 } 147 }
yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/modules/system/service/SysAuthServiceTest.java renamed to yudao-module-member/yudao-module-member-impl/src/test/java/cn/iocoder/yudao/module/member/service/auth/SysAuthServiceTest.java
1 -package cn.iocoder.yudao.userserver.modules.system.service; 1 +package cn.iocoder.yudao.module.member.service.auth;
2 2
3 -import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO;  
4 import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService; 3 import cn.iocoder.yudao.coreservice.modules.system.service.auth.SysUserSessionCoreService;
5 import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService; 4 import cn.iocoder.yudao.coreservice.modules.system.service.logger.SysLoginLogCoreService;
6 import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialCoreService; 5 import cn.iocoder.yudao.coreservice.modules.system.service.social.SysSocialCoreService;
7 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 6 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
8 import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; 7 import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
9 import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; 8 import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
10 -import cn.iocoder.yudao.userserver.BaseDbAndRedisUnitTest;  
11 -import cn.iocoder.yudao.userserver.modules.member.dal.mysql.user.MbrUserMapper;  
12 -import cn.iocoder.yudao.userserver.modules.member.service.user.MbrUserService;  
13 -import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.MbrAuthResetPasswordReqVO;  
14 -import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.MbrAuthUpdatePasswordReqVO;  
15 -import cn.iocoder.yudao.userserver.modules.system.service.auth.SysAuthService;  
16 -import cn.iocoder.yudao.userserver.modules.system.service.auth.impl.SysAuthServiceImpl;  
17 -import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService; 9 +import cn.iocoder.yudao.module.member.controller.app.auth.vo.AppAuthResetPasswordReqVO;
  10 +import cn.iocoder.yudao.module.member.controller.app.auth.vo.AppAuthUpdatePasswordReqVO;
  11 +import cn.iocoder.yudao.module.member.dal.dataobject.user.UserDO;
  12 +import cn.iocoder.yudao.module.member.dal.mysql.user.UserMapper;
  13 +import cn.iocoder.yudao.module.member.service.sms.SysSmsCodeService;
  14 +import cn.iocoder.yudao.module.member.service.user.UserService;
  15 +import cn.iocoder.yudao.module.member.test.BaseDbAndRedisUnitTest;
18 import org.junit.jupiter.api.Test; 16 import org.junit.jupiter.api.Test;
19 import org.springframework.boot.test.mock.mockito.MockBean; 17 import org.springframework.boot.test.mock.mockito.MockBean;
20 import org.springframework.context.annotation.Import; 18 import org.springframework.context.annotation.Import;
@@ -23,7 +21,6 @@ import org.springframework.security.authentication.AuthenticationManager; @@ -23,7 +21,6 @@ import org.springframework.security.authentication.AuthenticationManager;
23 import org.springframework.security.crypto.password.PasswordEncoder; 21 import org.springframework.security.crypto.password.PasswordEncoder;
24 22
25 import javax.annotation.Resource; 23 import javax.annotation.Resource;
26 -import java.util.concurrent.TimeUnit;  
27 import java.util.function.Consumer; 24 import java.util.function.Consumer;
28 25
29 import static cn.hutool.core.util.RandomUtil.randomEle; 26 import static cn.hutool.core.util.RandomUtil.randomEle;
@@ -35,17 +32,17 @@ import static org.mockito.Mockito.when; @@ -35,17 +32,17 @@ import static org.mockito.Mockito.when;
35 32
36 // TODO @芋艿:单测的 review,等逻辑都达成一致后 33 // TODO @芋艿:单测的 review,等逻辑都达成一致后
37 /** 34 /**
38 - * {@link SysAuthService} 的单元测试类 35 + * {@link AuthService} 的单元测试类
39 * 36 *
40 * @author 宋天 37 * @author 宋天
41 */ 38 */
42 -@Import({SysAuthServiceImpl.class, YudaoRedisAutoConfiguration.class}) 39 +@Import({AuthServiceImpl.class, YudaoRedisAutoConfiguration.class})
43 public class SysAuthServiceTest extends BaseDbAndRedisUnitTest { 40 public class SysAuthServiceTest extends BaseDbAndRedisUnitTest {
44 41
45 @MockBean 42 @MockBean
46 private AuthenticationManager authenticationManager; 43 private AuthenticationManager authenticationManager;
47 @MockBean 44 @MockBean
48 - private MbrUserService userService; 45 + private UserService userService;
49 @MockBean 46 @MockBean
50 private SysSmsCodeService smsCodeService; 47 private SysSmsCodeService smsCodeService;
51 @MockBean 48 @MockBean
@@ -59,21 +56,21 @@ public class SysAuthServiceTest extends BaseDbAndRedisUnitTest { @@ -59,21 +56,21 @@ public class SysAuthServiceTest extends BaseDbAndRedisUnitTest {
59 @MockBean 56 @MockBean
60 private PasswordEncoder passwordEncoder; 57 private PasswordEncoder passwordEncoder;
61 @Resource 58 @Resource
62 - private MbrUserMapper mbrUserMapper; 59 + private UserMapper mbrUserMapper;
63 @Resource 60 @Resource
64 - private SysAuthServiceImpl authService; 61 + private AuthServiceImpl authService;
65 62
66 @Test 63 @Test
67 public void testUpdatePassword_success(){ 64 public void testUpdatePassword_success(){
68 // 准备参数 65 // 准备参数
69 - MbrUserDO userDO = randomMbrUserDO(); 66 + UserDO userDO = randomUserDO();
70 mbrUserMapper.insert(userDO); 67 mbrUserMapper.insert(userDO);
71 68
72 // 新密码 69 // 新密码
73 String newPassword = randomString(); 70 String newPassword = randomString();
74 71
75 // 请求实体 72 // 请求实体
76 - MbrAuthUpdatePasswordReqVO reqVO = MbrAuthUpdatePasswordReqVO.builder() 73 + AppAuthUpdatePasswordReqVO reqVO = AppAuthUpdatePasswordReqVO.builder()
77 .oldPassword(userDO.getPassword()) 74 .oldPassword(userDO.getPassword())
78 .password(newPassword) 75 .password(newPassword)
79 .build(); 76 .build();
@@ -84,14 +81,14 @@ public class SysAuthServiceTest extends BaseDbAndRedisUnitTest { @@ -84,14 +81,14 @@ public class SysAuthServiceTest extends BaseDbAndRedisUnitTest {
84 when(passwordEncoder.encode(newPassword)).thenReturn(newPassword); 81 when(passwordEncoder.encode(newPassword)).thenReturn(newPassword);
85 82
86 // 更新用户密码 83 // 更新用户密码
87 - authService.updatePassword(userDO.getId(),reqVO); 84 + authService.updatePassword(userDO.getId(), reqVO);
88 assertEquals(mbrUserMapper.selectById(userDO.getId()).getPassword(),newPassword); 85 assertEquals(mbrUserMapper.selectById(userDO.getId()).getPassword(),newPassword);
89 } 86 }
90 87
91 @Test 88 @Test
92 public void testResetPassword_success(){ 89 public void testResetPassword_success(){
93 // 准备参数 90 // 准备参数
94 - MbrUserDO userDO = randomMbrUserDO(); 91 + UserDO userDO = randomUserDO();
95 mbrUserMapper.insert(userDO); 92 mbrUserMapper.insert(userDO);
96 93
97 // 随机密码 94 // 随机密码
@@ -99,17 +96,15 @@ public class SysAuthServiceTest extends BaseDbAndRedisUnitTest { @@ -99,17 +96,15 @@ public class SysAuthServiceTest extends BaseDbAndRedisUnitTest {
99 // 随机验证码 96 // 随机验证码
100 String code = randomNumbers(4); 97 String code = randomNumbers(4);
101 98
102 - MbrAuthResetPasswordReqVO reqVO = MbrAuthResetPasswordReqVO.builder()  
103 - .password(password)  
104 - .code(code)  
105 - .build();  
106 - // 放入code+手机号  
107 - stringRedisTemplate.opsForValue().set(code,userDO.getMobile(),10, TimeUnit.MINUTES);  
108 -  
109 // mock 99 // mock
110 when(passwordEncoder.encode(password)).thenReturn(password); 100 when(passwordEncoder.encode(password)).thenReturn(password);
111 101
112 // 更新用户密码 102 // 更新用户密码
  103 + AppAuthResetPasswordReqVO reqVO = new AppAuthResetPasswordReqVO();
  104 + reqVO.setMobile(userDO.getMobile());
  105 + reqVO.setPassword(password);
  106 + reqVO.setCode(code);
  107 +
113 authService.resetPassword(reqVO); 108 authService.resetPassword(reqVO);
114 assertEquals(mbrUserMapper.selectById(userDO.getId()).getPassword(),password); 109 assertEquals(mbrUserMapper.selectById(userDO.getId()).getPassword(),password);
115 } 110 }
@@ -118,12 +113,12 @@ public class SysAuthServiceTest extends BaseDbAndRedisUnitTest { @@ -118,12 +113,12 @@ public class SysAuthServiceTest extends BaseDbAndRedisUnitTest {
118 // ========== 随机对象 ========== 113 // ========== 随机对象 ==========
119 114
120 @SafeVarargs 115 @SafeVarargs
121 - private static MbrUserDO randomMbrUserDO(Consumer<MbrUserDO>... consumers) {  
122 - Consumer<MbrUserDO> consumer = (o) -> { 116 + private static UserDO randomUserDO(Consumer<UserDO>... consumers) {
  117 + Consumer<UserDO> consumer = (o) -> {
123 o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围 118 o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围
124 o.setPassword(randomString()); 119 o.setPassword(randomString());
125 }; 120 };
126 - return randomPojo(MbrUserDO.class, ArrayUtils.append(consumer, consumers)); 121 + return randomPojo(UserDO.class, ArrayUtils.append(consumer, consumers));
127 } 122 }
128 123
129 124
yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/modules/member/service/MbrUserServiceImplTest.java renamed to yudao-module-member/yudao-module-member-impl/src/test/java/cn/iocoder/yudao/module/member/service/user/MbrUserServiceImplTest.java
1 -package cn.iocoder.yudao.userserver.modules.member.service; 1 +package cn.iocoder.yudao.module.member.service.user;
2 2
  3 +import cn.hutool.core.util.RandomUtil;
3 import cn.iocoder.yudao.coreservice.modules.infra.service.file.InfFileCoreService; 4 import cn.iocoder.yudao.coreservice.modules.infra.service.file.InfFileCoreService;
4 -import cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user.MbrUserDO;  
5 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 5 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
6 import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; 6 import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
7 import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; 7 import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
8 -import cn.iocoder.yudao.userserver.BaseDbAndRedisUnitTest;  
9 -import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserInfoRespVO;  
10 -import cn.iocoder.yudao.userserver.modules.member.controller.user.vo.MbrUserUpdateMobileReqVO;  
11 -import cn.iocoder.yudao.userserver.modules.member.dal.mysql.user.MbrUserMapper;  
12 -import cn.iocoder.yudao.userserver.modules.member.service.user.impl.MbrUserServiceImpl;  
13 -import cn.iocoder.yudao.userserver.modules.system.controller.auth.vo.SysAuthSendSmsReqVO;  
14 -import cn.iocoder.yudao.userserver.modules.system.enums.sms.SysSmsSceneEnum;  
15 -import cn.iocoder.yudao.userserver.modules.system.service.auth.impl.SysAuthServiceImpl;  
16 -import cn.iocoder.yudao.userserver.modules.system.service.sms.SysSmsCodeService; 8 +import cn.iocoder.yudao.module.member.controller.app.user.vo.AppUserUpdateMobileReqVO;
  9 +import cn.iocoder.yudao.module.member.dal.dataobject.sms.SysSmsCodeDO;
  10 +import cn.iocoder.yudao.module.member.dal.dataobject.user.UserDO;
  11 +import cn.iocoder.yudao.module.member.dal.mysql.user.UserMapper;
  12 +import cn.iocoder.yudao.module.member.enums.sms.SysSmsSceneEnum;
  13 +import cn.iocoder.yudao.module.member.service.auth.AuthServiceImpl;
  14 +import cn.iocoder.yudao.module.member.service.sms.SysSmsCodeService;
  15 +import cn.iocoder.yudao.module.member.test.BaseDbAndRedisUnitTest;
17 import org.junit.jupiter.api.Test; 16 import org.junit.jupiter.api.Test;
18 import org.springframework.boot.test.mock.mockito.MockBean; 17 import org.springframework.boot.test.mock.mockito.MockBean;
19 import org.springframework.context.annotation.Import; 18 import org.springframework.context.annotation.Import;
@@ -32,24 +31,24 @@ import static org.mockito.Mockito.*; @@ -32,24 +31,24 @@ import static org.mockito.Mockito.*;
32 31
33 // TODO @芋艿:单测的 review,等逻辑都达成一致后 32 // TODO @芋艿:单测的 review,等逻辑都达成一致后
34 /** 33 /**
35 - * {@link MbrUserServiceImpl} 的单元测试类 34 + * {@link UserServiceImpl} 的单元测试类
36 * 35 *
37 * @author 宋天 36 * @author 宋天
38 */ 37 */
39 -@Import({MbrUserServiceImpl.class, YudaoRedisAutoConfiguration.class}) 38 +@Import({UserServiceImpl.class, YudaoRedisAutoConfiguration.class})
40 public class MbrUserServiceImplTest extends BaseDbAndRedisUnitTest { 39 public class MbrUserServiceImplTest extends BaseDbAndRedisUnitTest {
41 40
42 @Resource 41 @Resource
43 - private MbrUserServiceImpl mbrUserService; 42 + private UserServiceImpl mbrUserService;
44 43
45 @Resource 44 @Resource
46 private StringRedisTemplate stringRedisTemplate; 45 private StringRedisTemplate stringRedisTemplate;
47 46
48 @Resource 47 @Resource
49 - private MbrUserMapper userMapper; 48 + private UserMapper userMapper;
50 49
51 @MockBean 50 @MockBean
52 - private SysAuthServiceImpl authService; 51 + private AuthServiceImpl authService;
53 52
54 @MockBean 53 @MockBean
55 private InfFileCoreService fileCoreService; 54 private InfFileCoreService fileCoreService;
@@ -63,14 +62,14 @@ public class MbrUserServiceImplTest extends BaseDbAndRedisUnitTest { @@ -63,14 +62,14 @@ public class MbrUserServiceImplTest extends BaseDbAndRedisUnitTest {
63 @Test 62 @Test
64 public void testUpdateNickName_success(){ 63 public void testUpdateNickName_success(){
65 // mock 数据 64 // mock 数据
66 - MbrUserDO userDO = randomMbrUserDO(); 65 + UserDO userDO = randomUserDO();
67 userMapper.insert(userDO); 66 userMapper.insert(userDO);
68 67
69 // 随机昵称 68 // 随机昵称
70 String newNickName = randomString(); 69 String newNickName = randomString();
71 70
72 // 调用接口修改昵称 71 // 调用接口修改昵称
73 - mbrUserService.updateNickname(userDO.getId(),newNickName); 72 + mbrUserService.updateUserNickname(userDO.getId(),newNickName);
74 // 查询新修改后的昵称 73 // 查询新修改后的昵称
75 String nickname = mbrUserService.getUser(userDO.getId()).getNickname(); 74 String nickname = mbrUserService.getUser(userDO.getId()).getNickname();
76 // 断言 75 // 断言
@@ -78,20 +77,9 @@ public class MbrUserServiceImplTest extends BaseDbAndRedisUnitTest { @@ -78,20 +77,9 @@ public class MbrUserServiceImplTest extends BaseDbAndRedisUnitTest {
78 } 77 }
79 78
80 @Test 79 @Test
81 - public void testGetUserInfo_success(){  
82 - // mock 数据  
83 - MbrUserDO userDO = randomMbrUserDO();  
84 - userMapper.insert(userDO);  
85 -  
86 - // 查询用户昵称与头像  
87 - MbrUserInfoRespVO userInfo = mbrUserService.getUserInfo(userDO.getId());  
88 - System.out.println(userInfo);  
89 - }  
90 -  
91 - @Test  
92 public void testUpdateAvatar_success(){ 80 public void testUpdateAvatar_success(){
93 // mock 数据 81 // mock 数据
94 - MbrUserDO dbUser = randomMbrUserDO(); 82 + UserDO dbUser = randomUserDO();
95 userMapper.insert(dbUser); 83 userMapper.insert(dbUser);
96 84
97 // 准备参数 85 // 准备参数
@@ -102,7 +90,7 @@ public class MbrUserServiceImplTest extends BaseDbAndRedisUnitTest { @@ -102,7 +90,7 @@ public class MbrUserServiceImplTest extends BaseDbAndRedisUnitTest {
102 String avatar = randomString(); 90 String avatar = randomString();
103 when(fileCoreService.createFile(anyString(), eq(avatarFileBytes))).thenReturn(avatar); 91 when(fileCoreService.createFile(anyString(), eq(avatarFileBytes))).thenReturn(avatar);
104 // 调用 92 // 调用
105 - String str = mbrUserService.updateAvatar(userId, avatarFile); 93 + String str = mbrUserService.updateUserAvatar(userId, avatarFile);
106 // 断言 94 // 断言
107 assertEquals(avatar, str); 95 assertEquals(avatar, str);
108 } 96 }
@@ -111,28 +99,28 @@ public class MbrUserServiceImplTest extends BaseDbAndRedisUnitTest { @@ -111,28 +99,28 @@ public class MbrUserServiceImplTest extends BaseDbAndRedisUnitTest {
111 public void updateMobile_success(){ 99 public void updateMobile_success(){
112 // mock数据 100 // mock数据
113 String oldMobile = randomNumbers(11); 101 String oldMobile = randomNumbers(11);
114 - MbrUserDO userDO = randomMbrUserDO(); 102 + UserDO userDO = randomUserDO();
115 userDO.setMobile(oldMobile); 103 userDO.setMobile(oldMobile);
116 userMapper.insert(userDO); 104 userMapper.insert(userDO);
117 105
118 - // 验证旧手机  
119 - sysSmsCodeService.sendSmsCodeLogin(userDO.getId());  
120 -  
121 - // 验证旧手机验证码是否正确  
122 - sysSmsCodeService.useSmsCode(oldMobile,SysSmsSceneEnum.CHANGE_MOBILE_BY_SMS.getScene(),"123","1.1.1.1");  
123 - // 验证新手机  
124 - SysAuthSendSmsReqVO smsReqVO = new SysAuthSendSmsReqVO();  
125 - smsReqVO.setMobile(oldMobile);  
126 - smsReqVO.setScene(SysSmsSceneEnum.CHANGE_MOBILE_BY_SMS.getScene());  
127 - sysSmsCodeService.sendSmsNewCode(smsReqVO); 106 + // 旧手机和旧验证码
  107 + SysSmsCodeDO codeDO = new SysSmsCodeDO();
  108 + String oldCode = RandomUtil.randomString(4);
  109 + codeDO.setMobile(userDO.getMobile());
  110 + codeDO.setCode(oldCode);
  111 + codeDO.setScene(SysSmsSceneEnum.CHANGE_MOBILE_BY_SMS.getScene());
  112 + codeDO.setUsed(Boolean.FALSE);
  113 + when(sysSmsCodeService.checkCodeIsExpired(codeDO.getMobile(),codeDO.getCode(),codeDO.getScene())).thenReturn(codeDO);
128 114
129 // 更新手机号 115 // 更新手机号
130 String newMobile = randomNumbers(11); 116 String newMobile = randomNumbers(11);
131 - String code = randomNumbers(4);  
132 - MbrUserUpdateMobileReqVO reqVO = new MbrUserUpdateMobileReqVO(); 117 + String newCode = randomNumbers(4);
  118 + AppUserUpdateMobileReqVO reqVO = new AppUserUpdateMobileReqVO();
133 reqVO.setMobile(newMobile); 119 reqVO.setMobile(newMobile);
134 - reqVO.setCode(code);  
135 - mbrUserService.updateMobile(userDO.getId(),reqVO); 120 + reqVO.setCode(newCode);
  121 + reqVO.setOldMobile(oldMobile);
  122 + reqVO.setOldCode(oldCode);
  123 + mbrUserService.updateUserMobile(userDO.getId(),reqVO);
136 124
137 assertEquals(mbrUserService.getUser(userDO.getId()).getMobile(),newMobile); 125 assertEquals(mbrUserService.getUser(userDO.getId()).getMobile(),newMobile);
138 } 126 }
@@ -140,11 +128,11 @@ public class MbrUserServiceImplTest extends BaseDbAndRedisUnitTest { @@ -140,11 +128,11 @@ public class MbrUserServiceImplTest extends BaseDbAndRedisUnitTest {
140 // ========== 随机对象 ========== 128 // ========== 随机对象 ==========
141 129
142 @SafeVarargs 130 @SafeVarargs
143 - private static MbrUserDO randomMbrUserDO(Consumer<MbrUserDO>... consumers) {  
144 - Consumer<MbrUserDO> consumer = (o) -> { 131 + private static UserDO randomUserDO(Consumer<UserDO>... consumers) {
  132 + Consumer<UserDO> consumer = (o) -> {
145 o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围 133 o.setStatus(randomEle(CommonStatusEnum.values()).getStatus()); // 保证 status 的范围
146 }; 134 };
147 - return randomPojo(MbrUserDO.class, ArrayUtils.append(consumer, consumers)); 135 + return randomPojo(UserDO.class, ArrayUtils.append(consumer, consumers));
148 } 136 }
149 137
150 } 138 }
yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/BaseDbAndRedisUnitTest.java renamed to yudao-module-member/yudao-module-member-impl/src/test/java/cn/iocoder/yudao/module/member/test/BaseDbAndRedisUnitTest.java
1 -package cn.iocoder.yudao.userserver; 1 +package cn.iocoder.yudao.module.member.test;
2 2
3 import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration; 3 import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration;
4 import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration; 4 import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration;
5 import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration; 5 import cn.iocoder.yudao.framework.redis.config.YudaoRedisAutoConfiguration;
6 -import cn.iocoder.yudao.userserver.config.RedisTestConfiguration;  
7 import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure; 6 import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure;
8 import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration; 7 import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
9 import org.redisson.spring.starter.RedissonAutoConfiguration; 8 import org.redisson.spring.starter.RedissonAutoConfiguration;
yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/BaseDbUnitTest.java renamed to yudao-module-member/yudao-module-member-impl/src/test/java/cn/iocoder/yudao/module/member/test/BaseDbUnitTest.java
1 -package cn.iocoder.yudao.userserver; 1 +package cn.iocoder.yudao.module.member.test;
2 2
3 import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration; 3 import cn.iocoder.yudao.framework.datasource.config.YudaoDataSourceAutoConfiguration;
4 import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration; 4 import cn.iocoder.yudao.framework.mybatis.config.YudaoMybatisAutoConfiguration;
yudao-user-server/src/test/java/cn/iocoder/yudao/userserver/config/RedisTestConfiguration.java renamed to yudao-module-member/yudao-module-member-impl/src/test/java/cn/iocoder/yudao/module/member/test/RedisTestConfiguration.java
1 -package cn.iocoder.yudao.userserver.config; 1 +package cn.iocoder.yudao.module.member.test;
2 2
3 import com.github.fppt.jedismock.RedisServer; 3 import com.github.fppt.jedismock.RedisServer;
4 import org.springframework.boot.autoconfigure.data.redis.RedisProperties; 4 import org.springframework.boot.autoconfigure.data.redis.RedisProperties;
yudao-user-server/src/test/resources/application-unit-test.yaml renamed to yudao-module-member/yudao-module-member-impl/src/test/resources/application-unit-test.yaml
@@ -42,3 +42,8 @@ mybatis: @@ -42,3 +42,8 @@ mybatis:
42 --- #################### 芋道相关配置 #################### 42 --- #################### 芋道相关配置 ####################
43 43
44 # 芋道配置项,设置当前项目所有自定义的配置 44 # 芋道配置项,设置当前项目所有自定义的配置
  45 +yudao:
  46 + info:
  47 + base-package: cn.iocoder.yudao.module.member.dal.mysql
  48 + core-service:
  49 + base-package: cn.iocoder.yudao.module.member.dal.mysql # TODO 芋艿:要清理掉
yudao-user-server/src/test/resources/file/erweima.jpg renamed to yudao-module-member/yudao-module-member-impl/src/test/resources/file/erweima.jpg

18 KB

yudao-user-server/src/test/resources/logback-spring.xml renamed to yudao-module-member/yudao-module-member-impl/src/test/resources/logback-spring.xml
yudao-user-server/src/test/resources/sql/clean.sql renamed to yudao-module-member/yudao-module-member-impl/src/test/resources/sql/clean.sql
yudao-user-server/src/test/resources/sql/create_tables.sql renamed to yudao-module-member/yudao-module-member-impl/src/test/resources/sql/create_tables.sql
yudao-user-server/pom.xml
@@ -90,15 +90,6 @@ @@ -90,15 +90,6 @@
90 <artifactId>yudao-spring-boot-starter-test</artifactId> 90 <artifactId>yudao-spring-boot-starter-test</artifactId>
91 <scope>test</scope> 91 <scope>test</scope>
92 </dependency> 92 </dependency>
93 -  
94 - <!-- TODO @宋天:junit 已经在 yudao-spring-boot-starter-test 啦,不用在引入哈 -->  
95 - <!--单元测试相关-->  
96 - <dependency>  
97 - <groupId>junit</groupId>  
98 - <artifactId>junit</artifactId>  
99 - <scope>test</scope>  
100 - </dependency>  
101 -  
102 <!-- 工具类相关 --> 93 <!-- 工具类相关 -->
103 94
104 </dependencies> 95 </dependencies>
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/security/SecurityConfiguration.java deleted
1 -package cn.iocoder.yudao.userserver.framework.security;  
2 -  
3 -import cn.iocoder.yudao.framework.web.config.WebProperties;  
4 -import org.springframework.context.annotation.Bean;  
5 -import org.springframework.context.annotation.Configuration;  
6 -import org.springframework.security.config.Customizer;  
7 -import org.springframework.security.config.annotation.web.builders.HttpSecurity;  
8 -import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;  
9 -  
10 -import javax.annotation.Resource;  
11 -  
12 -@Configuration  
13 -public class SecurityConfiguration {  
14 -  
15 - @Resource  
16 - private WebProperties webProperties;  
17 -  
18 - @Bean  
19 - public Customizer<ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry> authorizeRequestsCustomizer() {  
20 - return registry -> {  
21 - registry.antMatchers(api("/**")).permitAll(); // 默认 API 都是用户可访问  
22 - };  
23 - }  
24 -  
25 - private String api(String url) {  
26 - return webProperties.getApiPrefix() + url;  
27 - }  
28 -  
29 -}