From 930cdfe2b26ae2a2d5fc6f0d98b021fda00f0071 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 7 May 2021 00:19:07 +0800 Subject: [PATCH 01/39] =?UTF-8?q?=E5=88=9B=E5=BB=BA=20yudao-user-server?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 1 + yudao-admin-server/pom.xml | 4 - .../main/resources/META-INF/spring.factories | 2 +- yudao-user-server/pom.xml | 111 ++++++++++++++ .../userserver/UserServerApplication.java | 13 ++ .../async/config/AsyncConfiguration.java | 9 ++ .../framework/async/package-info.java | 4 + .../《芋道 Spring Boot 异步任务入门》.md | 1 + .../userserver/framework/package-info.java | 6 + .../dal/dataobject/config/InfConfigDO.java | 64 ++++++++ .../infra/dal/dataobject/file/InfFileDO.java | 43 ++++++ .../dal/mysql/config/InfConfigDAOImpl.java | 39 +++++ .../infra/dal/mysql/file/InfFileMapper.java | 10 ++ .../modules/infra/package-info.java | 7 + .../userserver/modules/package-info.java | 1 + .../src/main/resources/application-dev.yaml | 140 +++++++++++++++++ .../src/main/resources/application-local.yaml | 142 ++++++++++++++++++ .../src/main/resources/application.yaml | 60 ++++++++ .../src/main/resources/banner.txt | 17 +++ .../src/main/resources/logback-spring.xml | 76 ++++++++++ 20 files changed, 745 insertions(+), 5 deletions(-) create mode 100644 yudao-user-server/pom.xml create mode 100644 yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/UserServerApplication.java create mode 100644 yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/async/config/AsyncConfiguration.java create mode 100644 yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/async/package-info.java create mode 100644 yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/async/《芋道 Spring Boot 异步任务入门》.md create mode 100644 yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/package-info.java create mode 100644 yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/dataobject/config/InfConfigDO.java create mode 100644 yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/dataobject/file/InfFileDO.java create mode 100644 yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/mysql/config/InfConfigDAOImpl.java create mode 100644 yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/mysql/file/InfFileMapper.java create mode 100644 yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/package-info.java create mode 100644 yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/package-info.java create mode 100644 yudao-user-server/src/main/resources/application-dev.yaml create mode 100644 yudao-user-server/src/main/resources/application-local.yaml create mode 100644 yudao-user-server/src/main/resources/application.yaml create mode 100644 yudao-user-server/src/main/resources/banner.txt create mode 100644 yudao-user-server/src/main/resources/logback-spring.xml diff --git a/pom.xml b/pom.xml index eec621676..d6bb8301a 100644 --- a/pom.xml +++ b/pom.xml @@ -11,6 +11,7 @@ yudao-dependencies yudao-framework yudao-admin-server + yudao-user-server ${artifactId} diff --git a/yudao-admin-server/pom.xml b/yudao-admin-server/pom.xml index 107b67e6b..16e75eb84 100644 --- a/yudao-admin-server/pom.xml +++ b/yudao-admin-server/pom.xml @@ -110,10 +110,6 @@ cn.smallbun.screw screw-core - - cn.iocoder.boot - yudao-spring-boot-starter-mq - diff --git a/yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/resources/META-INF/spring.factories b/yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/resources/META-INF/spring.factories index 529a47663..3986b1c2b 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/resources/META-INF/spring.factories +++ b/yudao-framework/yudao-spring-boot-starter-biz-dict/src/main/resources/META-INF/spring.factories @@ -1,2 +1,2 @@ org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ - cn.iocoder.yudao.framework.operatelog.config.YudaoOperateLogAutoConfiguration + cn.iocoder.yudao.framework.dict.config.YudaoDictAutoConfiguration diff --git a/yudao-user-server/pom.xml b/yudao-user-server/pom.xml new file mode 100644 index 000000000..4bd1c5857 --- /dev/null +++ b/yudao-user-server/pom.xml @@ -0,0 +1,111 @@ + + + + cn.iocoder.boot + yudao + ${revision} + + 4.0.0 + + yudao-user-server + jar + + yudao-admin-server + 用户前台 Server,提供其 API 接口 + https://github.com/YunaiV/ruoyi-vue-pro + + + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-dict + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-sms + + + + + cn.iocoder.boot + yudao-spring-boot-starter-web + + + + cn.iocoder.boot + yudao-spring-boot-starter-security + + + + + cn.iocoder.boot + yudao-spring-boot-starter-mybatis + + + + cn.iocoder.boot + yudao-spring-boot-starter-redis + + + + + cn.iocoder.boot + yudao-spring-boot-starter-config + + + + + + + cn.iocoder.boot + yudao-spring-boot-starter-mq + + + + + cn.iocoder.boot + yudao-spring-boot-starter-protection + + + + + cn.iocoder.boot + yudao-spring-boot-starter-monitor + + + + + cn.iocoder.boot + yudao-spring-boot-starter-test + test + + + + + + + + + ${artifactId} + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + repackage + + + + + + + + diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/UserServerApplication.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/UserServerApplication.java new file mode 100644 index 000000000..edfbc63dc --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/UserServerApplication.java @@ -0,0 +1,13 @@ +package cn.iocoder.yudao.userserver; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class UserServerApplication { + + public static void main(String[] args) { + SpringApplication.run(UserServerApplication.class, args); + } + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/async/config/AsyncConfiguration.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/async/config/AsyncConfiguration.java new file mode 100644 index 000000000..ed271220c --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/async/config/AsyncConfiguration.java @@ -0,0 +1,9 @@ +package cn.iocoder.yudao.userserver.framework.async.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.EnableAsync; + +@Configuration +@EnableAsync +public class AsyncConfiguration { +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/async/package-info.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/async/package-info.java new file mode 100644 index 000000000..a06351522 --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/async/package-info.java @@ -0,0 +1,4 @@ +/** + * 异步执行,基于 Spring @Async 实现 + */ +package cn.iocoder.yudao.userserver.framework.async; diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/async/《芋道 Spring Boot 异步任务入门》.md b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/async/《芋道 Spring Boot 异步任务入门》.md new file mode 100644 index 000000000..5822b838c --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/async/《芋道 Spring Boot 异步任务入门》.md @@ -0,0 +1 @@ + diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/package-info.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/package-info.java new file mode 100644 index 000000000..db25ed2a4 --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/package-info.java @@ -0,0 +1,6 @@ +/** + * 属于整个 yudao-user-server 的 framework 封装 + * + * @author 芋道源码 + */ +package cn.iocoder.yudao.userserver.framework; diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/dataobject/config/InfConfigDO.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/dataobject/config/InfConfigDO.java new file mode 100644 index 000000000..a9ab432d6 --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/dataobject/config/InfConfigDO.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.userserver.modules.infra.dal.dataobject.config; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +/** + * 参数配置表 + * + * @author ruoyi + */ +@TableName("inf_config") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class InfConfigDO extends BaseDO { + + /** + * 参数主键 + */ + @TableId + private Long id; + /** + * 参数分组 + */ + @TableField("`group`") + private String group; + /** + * 参数名称 + */ + private String name; + /** + * 参数键名 + */ + @TableField("`key`") + private String key; + /** + * 参数键值 + */ + private String value; + /** + * 参数类型 + * + * 枚举 {@link InfConfigTypeEnum} + */ + @TableField("`type`") + private Integer type; + /** + * 是否敏感 + * + * 对于敏感配置,需要管理权限才能查看 + */ + @TableField("`sensitive`") + private Boolean sensitive; + /** + * 备注 + */ + private String remark; + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/dataobject/file/InfFileDO.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/dataobject/file/InfFileDO.java new file mode 100644 index 000000000..604a888c2 --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/dataobject/file/InfFileDO.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.userserver.modules.infra.dal.dataobject.file; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.io.InputStream; + +/** + * 文件表 + * + * @author 芋道源码 + */ +@Data +@TableName("inf_file") +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class InfFileDO extends BaseDO { + + /** + * 文件路径 + */ + @TableId(type = IdType.INPUT) + private String id; + /** + * 文件类型 + * + * 通过 {@link cn.hutool.core.io.FileTypeUtil#getType(InputStream)} 获取 + */ + @TableField(value = "`type`") + private String type; + /** + * 文件内容 + */ + private byte[] content; + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/mysql/config/InfConfigDAOImpl.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/mysql/config/InfConfigDAOImpl.java new file mode 100644 index 000000000..5453c05a2 --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/mysql/config/InfConfigDAOImpl.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.userserver.modules.infra.dal.mysql.config; + +import cn.iocoder.yudao.framework.apollo.internals.ConfigFrameworkDAO; +import cn.iocoder.yudao.framework.apollo.internals.dto.ConfigRespDTO; +import org.springframework.jdbc.core.BeanPropertyRowMapper; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.datasource.DriverManagerDataSource; + +import javax.sql.DataSource; +import java.sql.ResultSet; +import java.util.Date; +import java.util.List; + +/** + * ConfigFrameworkDAO 实现类 + * + * @author 芋道源码 + */ +public class InfConfigDAOImpl implements ConfigFrameworkDAO { + + private final JdbcTemplate jdbcTemplate; + + public InfConfigDAOImpl(String jdbcUrl, String username, String password) { + DataSource dataSource = new DriverManagerDataSource(jdbcUrl, username, password); + this.jdbcTemplate = new JdbcTemplate(dataSource); + } + + @Override + public boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) { + return jdbcTemplate.query("SELECT id FROM inf_config WHERE update_time > ? LIMIT 1", + ResultSet::next, maxUpdateTime); + } + + @Override + public List selectList() { + return jdbcTemplate.query("SELECT `key`, `value`, update_time, deleted FROM inf_config", new BeanPropertyRowMapper<>(ConfigRespDTO.class)); + } + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/mysql/file/InfFileMapper.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/mysql/file/InfFileMapper.java new file mode 100644 index 000000000..1db7d311b --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/mysql/file/InfFileMapper.java @@ -0,0 +1,10 @@ +package cn.iocoder.yudao.userserver.modules.infra.dal.mysql.file; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.userserver.modules.infra.dal.dataobject.file.InfFileDO; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface InfFileMapper extends BaseMapperX { + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/package-info.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/package-info.java new file mode 100644 index 000000000..fdf89894e --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/package-info.java @@ -0,0 +1,7 @@ +/** + * infra 包下,我们放基础设施的运维与管理,支撑上层的通用与核心业务。 + * 例如说:定时任务的管理、服务器的信息等等 + * + * 缩写:inf + */ +package cn.iocoder.yudao.userserver.modules.infra; diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/package-info.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/package-info.java new file mode 100644 index 000000000..430f6c945 --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.userserver.modules; diff --git a/yudao-user-server/src/main/resources/application-dev.yaml b/yudao-user-server/src/main/resources/application-dev.yaml new file mode 100644 index 000000000..c21eeec80 --- /dev/null +++ b/yudao-user-server/src/main/resources/application-dev.yaml @@ -0,0 +1,140 @@ +server: + port: 28080 + +--- #################### 数据库相关配置 #################### + +spring: + # 数据源配置项 + autoconfigure: + exclude: + - com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源 + datasource: + druid: # Druid 【监控】相关的全局配置 + web-stat-filter: + enabled: true + stat-view-servlet: + enabled: true + allow: # 设置白名单,不填则允许所有访问 + url-pattern: /druid/* + login-username: # 控制台管理用户名和密码 + login-password: + filter: + stat: + enabled: true + log-slow-sql: true # 慢 SQL 记录 + slow-sql-millis: 100 + merge-sql: true + wall: + config: + multi-statement-allow: true + dynamic: # 多数据源配置 + druid: # Druid 【连接池】相关的全局配置 + initial-size: 5 # 初始连接数 + min-idle: 10 # 最小连接池数量 + max-active: 20 # 最大连接池数量 + max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 + time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 + min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 + max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 + validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 + test-while-idle: true + test-on-borrow: false + test-on-return: false + primary: master + datasource: + master: + name: ruoyi-vue-pro + url: jdbc:mysql://400-infra.server.iocoder.cn:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT + driver-class-name: com.mysql.jdbc.Driver + username: root + password: 3WLiVUBEwTbvAfsh + slave: # 模拟从库,可根据自己需要修改 # 模拟从库,可根据自己需要修改 + name: ruoyi-vue-pro + url: jdbc:mysql://400-infra.server.iocoder.cn:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT + driver-class-name: com.mysql.jdbc.Driver + username: root + password: 3WLiVUBEwTbvAfsh + + # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 + redis: + host: 400-infra.server.iocoder.cn # 地址 + port: 6379 # 端口 + database: 1 # 数据库索引 + +--- #################### 定时任务相关配置 #################### + +--- #################### 配置中心相关配置 #################### + +# Apollo 配置中心 +apollo: + bootstrap: + enabled: true # 设置 Apollo 在启动阶段生效 + eagerLoad: + enabled: true # 设置 Apollo 在日志初始化前生效,可以实现日志的动态级别配置 + jdbc: # 自定义的 JDBC 配置项,用于数据库的地址 + dao: cn.iocoder.yudao.userserver.modules.infra.dal.mysql.config.InfConfigDAOImpl + url: ${spring.datasource.dynamic.datasource.master.url} + username: ${spring.datasource.dynamic.datasource.master.username} + password: ${spring.datasource.dynamic.datasource.master.password} + +--- #################### 服务保障相关配置 #################### + +# Lock4j 配置项 +lock4j: + acquire-timeout: 3000 # 获取分布式锁超时时间,默认为 3000 毫秒 + expire: 30000 # 分布式锁的超时时间,默认为 30 毫秒 + +# Resilience4j 配置项 +resilience4j: + ratelimiter: + instances: + backendA: + limit-for-period: 1 # 每个周期内,允许的请求数。默认为 50 + limit-refresh-period: 60s # 每个周期的时长,单位:微秒。默认为 500 + timeout-duration: 1s # 被限流时,阻塞等待的时长,单位:微秒。默认为 5s + register-health-indicator: true # 是否注册到健康监测 + +--- #################### 监控相关配置 #################### + +# Actuator 监控端点的配置项 +management: + endpoints: + web: + base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator + exposure: + include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。 + +# Spring Boot Admin 配置项 +spring: + boot: + admin: + # Spring Boot Admin Client 客户端的相关配置 + client: + url: http://127.0.0.1:${server.port}/${spring.boot.admin.context-path} # 设置 Spring Boot Admin Server 地址 + instance: + prefer-ip: true # 注册实例时,优先使用 IP + +# 日志文件配置 +logging: + file: + name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径 + +--- #################### 芋道相关配置 #################### + +# 芋道配置项,设置当前项目所有自定义的配置 +yudao: + security: + token-header: Authorization + token-secret: abcdefghijklmnopqrstuvwxyz + token-timeout: 1d + session-timeout: 30m + mock-enable: true + mock-secret: test + file: + base-path: http://api-dashboard.yudao.iocoder.cn${yudao.web.api-prefix}/infra/file/get/ + xss: + enable: false + exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系 + - ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求 + - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 + demo: true # 开启演示模式 diff --git a/yudao-user-server/src/main/resources/application-local.yaml b/yudao-user-server/src/main/resources/application-local.yaml new file mode 100644 index 000000000..62a53cf07 --- /dev/null +++ b/yudao-user-server/src/main/resources/application-local.yaml @@ -0,0 +1,142 @@ +server: + port: 28080 + +--- #################### 数据库相关配置 #################### + +spring: + # 数据源配置项 + autoconfigure: + exclude: + - com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源 + datasource: + druid: # Druid 【监控】相关的全局配置 + web-stat-filter: + enabled: true + stat-view-servlet: + enabled: true + allow: # 设置白名单,不填则允许所有访问 + url-pattern: /druid/* + login-username: # 控制台管理用户名和密码 + login-password: + filter: + stat: + enabled: true + log-slow-sql: true # 慢 SQL 记录 + slow-sql-millis: 100 + merge-sql: true + wall: + config: + multi-statement-allow: true + dynamic: # 多数据源配置 + druid: # Druid 【连接池】相关的全局配置 + initial-size: 5 # 初始连接数 + min-idle: 10 # 最小连接池数量 + max-active: 20 # 最大连接池数量 + max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 + time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 + min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 + max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 + validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 + test-while-idle: true + test-on-borrow: false + test-on-return: false + primary: master + datasource: + master: + name: ruoyi-vue-pro + url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT + driver-class-name: com.mysql.jdbc.Driver + username: root + password: 123456 + slave: # 模拟从库,可根据自己需要修改 + name: ruoyi-vue-pro + url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT + driver-class-name: com.mysql.jdbc.Driver + username: root + password: 123456 + + # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 + redis: + host: 127.0.0.1 # 地址 + port: 6379 # 端口 + database: 0 # 数据库索引 + +--- #################### 定时任务相关配置 #################### + +--- #################### 配置中心相关配置 #################### + +# Apollo 配置中心 +apollo: + bootstrap: + enabled: true # 设置 Apollo 在启动阶段生效 + eagerLoad: + enabled: true # 设置 Apollo 在日志初始化前生效,可以实现日志的动态级别配置 + jdbc: # 自定义的 JDBC 配置项,用于数据库的地址 + dao: cn.iocoder.yudao.userserver.modules.infra.dal.mysql.config.InfConfigDAOImpl + url: ${spring.datasource.dynamic.datasource.master.url} + username: ${spring.datasource.dynamic.datasource.master.username} + password: ${spring.datasource.dynamic.datasource.master.password} + +--- #################### 服务保障相关配置 #################### + +# Lock4j 配置项 +lock4j: + acquire-timeout: 3000 # 获取分布式锁超时时间,默认为 3000 毫秒 + expire: 30000 # 分布式锁的超时时间,默认为 30 毫秒 + +# Resilience4j 配置项 +resilience4j: + ratelimiter: + instances: + backendA: + limit-for-period: 1 # 每个周期内,允许的请求数。默认为 50 + limit-refresh-period: 60s # 每个周期的时长,单位:微秒。默认为 500 + timeout-duration: 1s # 被限流时,阻塞等待的时长,单位:微秒。默认为 5s + register-health-indicator: true # 是否注册到健康监测 + +--- #################### 监控相关配置 #################### + +# Actuator 监控端点的配置项 +management: + endpoints: + web: + base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator + exposure: + include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。 + +# Spring Boot Admin 配置项 +spring: + boot: + admin: + # Spring Boot Admin Client 客户端的相关配置 + client: + url: http://127.0.0.1:${server.port}/${spring.boot.admin.context-path} # 设置 Spring Boot Admin Server 地址 + instance: + prefer-ip: true # 注册实例时,优先使用 IP + # Spring Boot Admin Server 服务端的相关配置 + context-path: /admin # 配置 Spring + +# 日志文件配置 +logging: + file: + name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径 + +--- #################### 芋道相关配置 #################### + +# 芋道配置项,设置当前项目所有自定义的配置 +yudao: + security: + token-header: Authorization + token-secret: abcdefghijklmnopqrstuvwxyz + token-timeout: 1d + session-timeout: 30m + mock-enable: true + mock-secret: test + file: + base-path: http://127.0.0.1:${server.port}${yudao.web.api-prefix}/infra/file/get/ + xss: + enable: false + exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系 + - ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求 + - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 + demo: false # 关闭演示模式 diff --git a/yudao-user-server/src/main/resources/application.yaml b/yudao-user-server/src/main/resources/application.yaml new file mode 100644 index 000000000..573a9a5e1 --- /dev/null +++ b/yudao-user-server/src/main/resources/application.yaml @@ -0,0 +1,60 @@ +spring: + application: + name: yudao-user-server + + profiles: + active: local + + # Servlet 配置 + servlet: + # 文件上传相关配置项 + multipart: + max-file-size: 16MB # 单个文件大小 + max-request-size: 32MB # 设置总上传的文件大小 + + # Jackson 配置项 + jackson: + serialization: + write-dates-as-timestamps: true # 设置 Date 的格式,使用时间戳 + write-date-timestamps-as-nanoseconds: false # 设置不使用 nanoseconds 的格式。例如说 1611460870.401,而是直接 1611460870401 + write-durations-as-timestamps: true # 设置 Duration 的格式,使用时间戳 + fail-on-empty-beans: false # 允许序列化无属性的 Bean + +# MyBatis Plus 的配置项 +mybatis-plus: + configuration: + map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。 + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印日志 + global-config: + db-config: + id-type: AUTO # 自增 ID + logic-delete-value: 1 # 逻辑已删除值(默认为 1) + logic-not-delete-value: 0 # 逻辑未删除值(默认为 0) + mapper-locations: classpath*:mapper/*.xml + type-aliases-package: ${yudao.info.base-package}.modules.*.dal.dataobject + +--- #################### 芋道相关配置 #################### + +yudao: + info: + version: 1.0.0 + base-package: cn.iocoder.yudao.userserver + web: + api-prefix: /api + controller-package: ${yudao.info.base-package} + swagger: + title: 管理后台 + description: 提供管理员管理的所有功能 + version: ${yudao.info.version} + base-package: ${yudao.info.base-package}.modules + captcha: + timeout: 5m + width: 160 + height: 60 + codegen: + base-package: ${yudao.info.base-package} + db-schemas: ${spring.datasource.dynamic.datasource.master.name} + error-code: # 错误码相关配置项 + constants-class-list: + +debug: false diff --git a/yudao-user-server/src/main/resources/banner.txt b/yudao-user-server/src/main/resources/banner.txt new file mode 100644 index 000000000..39a441d7d --- /dev/null +++ b/yudao-user-server/src/main/resources/banner.txt @@ -0,0 +1,17 @@ +芋道源码 http://www.iocoder.cn +Application Version: ${yudao.info.version} +Spring Boot Version: ${spring-boot.version} + +.__ __. ______ .______ __ __ _______ +| \ | | / __ \ | _ \ | | | | / _____| +| \| | | | | | | |_) | | | | | | | __ +| . ` | | | | | | _ < | | | | | | |_ | +| |\ | | `--' | | |_) | | `--' | | |__| | +|__| \__| \______/ |______/ \______/ \______| + +███╗ ██╗ ██████╗ ██████╗ ██╗ ██╗ ██████╗ +████╗ ██║██╔═══██╗ ██╔══██╗██║ ██║██╔════╝ +██╔██╗ ██║██║ ██║ ██████╔╝██║ ██║██║ ███╗ +██║╚██╗██║██║ ██║ ██╔══██╗██║ ██║██║ ██║ +██║ ╚████║╚██████╔╝ ██████╔╝╚██████╔╝╚██████╔╝ +╚═╝ ╚═══╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═════╝ diff --git a/yudao-user-server/src/main/resources/logback-spring.xml b/yudao-user-server/src/main/resources/logback-spring.xml new file mode 100644 index 000000000..5bc181fd2 --- /dev/null +++ b/yudao-user-server/src/main/resources/logback-spring.xml @@ -0,0 +1,76 @@ + + + + + + + + + +       + + + ${PATTERN_DEFAULT} + + + + + + + + + + ${PATTERN_DEFAULT} + + + + ${LOG_FILE} + + + ${LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN:-${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz} + + ${LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START:-false} + + ${LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE:-10MB} + + ${LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP:-0} + + ${LOGBACK_ROLLINGPOLICY_MAX_HISTORY:-30} + + + + + + 0 + + 256 + + + + + + + + ${PATTERN_DEFAULT} + + + + + + + + + + + + + + + + + + + + + + From 3a5da7d0a30bddc82e7367739fffcb84789d1374 Mon Sep 17 00:00:00 2001 From: fourcows Date: Wed, 26 May 2021 22:08:21 +0800 Subject: [PATCH 02/39] =?UTF-8?q?fix:=20updateUserStatus=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E7=9A=84=E6=B3=A8=E9=87=8A=E6=9C=89=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adminserver/modules/system/service/user/SysUserService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/user/SysUserService.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/user/SysUserService.java index 16c815ace..78071d246 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/user/SysUserService.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/user/SysUserService.java @@ -74,7 +74,7 @@ public interface SysUserService { void updateUserPassword(Long id, String password); /** - * 修改密码 + * 修改状态 * * @param id 用户编号 * @param status 状态 From c588a4d975f8880ecbfc3d8884680232dccb5fb3 Mon Sep 17 00:00:00 2001 From: weir <1261174789@qq.com> Date: Fri, 30 Jul 2021 23:42:29 +0800 Subject: [PATCH 03/39] =?UTF-8?q?=E6=B5=8B=E8=AF=95=E9=83=A8=E7=BD=B2?= =?UTF-8?q?=E5=B9=B6=E4=BF=AE=E6=94=B9=E7=AB=AF=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-admin-ui/.env.production | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-admin-ui/.env.production b/yudao-admin-ui/.env.production index 5c64ef413..cb6a54180 100644 --- a/yudao-admin-ui/.env.production +++ b/yudao-admin-ui/.env.production @@ -4,7 +4,7 @@ ENV = 'production' # 芋道管理系统/生产环境 VUE_APP_BASE_API = '/prod-api' # 根据服务器或域名修改 -PUBLIC_PATH = 'http://you_ip.cn/yudao-admin/' +PUBLIC_PATH = 'http://my-pi.com:8888/yudao-admin/' # 二级部署路径 VUE_APP_APP_NAME ='yudao-admin' From 133cb49c42cd22ce71ddf51bb8288fc69558a8fe Mon Sep 17 00:00:00 2001 From: weir <1261174789@qq.com> Date: Fri, 13 Aug 2021 23:44:52 +0800 Subject: [PATCH 04/39] =?UTF-8?q?=E6=8E=A5=E5=85=A5=E7=AC=AC=E4=B8=89?= =?UTF-8?q?=E6=96=B9=E7=99=BB=E5=BD=95=EF=BC=88=E5=B7=B2=E6=8E=A5=E5=85=A5?= =?UTF-8?q?Gitee[=E7=90=86=E8=AE=BAjustAuth=E6=94=AF=E6=8C=81=E9=83=BD?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E6=8E=A5=E5=85=A5]--=E6=8A=A2=E5=85=88?= =?UTF-8?q?=E9=A2=84=E8=A7=88=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/ruoyi-vue-pro.sql | 18 ++ .../controller/auth/SysAuthController.java | 16 ++ .../controller/user/vo/user/AuthUser.java | 7 + .../system/convert/auth/SysAuthConvert.java | 41 ++- .../convert/auth/config/AuthConfig.java | 19 ++ ...SignUpUrlAuthenticationSuccessHandler.java | 112 +++++++++ .../dal/dataobject/social/SocialUserDO.java | 13 + .../dataobject/social/SysUserSocialDO.java | 31 +++ .../mysql/social/SysSysUserSocialMapper.java | 11 + .../dal/mysql/social/SysUserSocialMapper.java | 11 + .../system/enums/common/SysSexEnum.java | 10 +- .../service/auth/SysUserSessionService.java | 7 + .../auth/impl/SysUserSessionServiceImpl.java | 14 ++ .../auth/impl/UserDetailsServiceImpl.java | 237 ++++++++++++++++++ .../system/service/user/SysUserService.java | 8 + .../service/user/SysUserServiceImpl.java | 13 + .../src/main/resources/application-local.yaml | 218 ++++++++++++++++ yudao-admin-ui/src/api/login.js | 16 ++ yudao-admin-ui/src/permission.js | 2 +- yudao-admin-ui/src/router/index.js | 5 + yudao-admin-ui/src/views/login.vue | 15 +- yudao-admin-ui/src/views/oauthLogin.vue | 27 ++ yudao-dependencies/pom.xml | 2 +- .../pom.xml | 13 + .../YudaoWebSecurityConfigurerAdapter.java | 100 +++++--- .../security/core/Auth2LoginUser.java | 66 +++++ ...SignUpUrlAuthenticationSuccessHandler.java | 61 +++++ 27 files changed, 1049 insertions(+), 44 deletions(-) create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/AuthUser.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/auth/config/AuthConfig.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/auth/handler/DefaultSignUpUrlAuthenticationSuccessHandler.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/social/SocialUserDO.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/social/SysUserSocialDO.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/social/SysSysUserSocialMapper.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/social/SysUserSocialMapper.java create mode 100644 yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/UserDetailsServiceImpl.java create mode 100644 yudao-admin-ui/src/views/oauthLogin.vue create mode 100644 yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/Auth2LoginUser.java create mode 100644 yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/handler/AbstractSignUpUrlAuthenticationSuccessHandler.java diff --git a/sql/ruoyi-vue-pro.sql b/sql/ruoyi-vue-pro.sql index 35b521bb1..16b08f2cc 100644 --- a/sql/ruoyi-vue-pro.sql +++ b/sql/ruoyi-vue-pro.sql @@ -2426,3 +2426,21 @@ INSERT INTO `tool_test_demo` VALUES (107, '哈哈哈哈', 1, 0, 1, 'biubiubui', COMMIT; SET FOREIGN_KEY_CHECKS = 1; + +-- ---------------------------- +-- Table structure for sys_user_social +-- ---------------------------- +DROP TABLE IF EXISTS `sys_user_social`; +CREATE TABLE `sys_user_social` ( + `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键(自增策略)', + `user_id` bigint NOT NULL COMMENT '系统用户ID', + `social_user_id` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '第三用户ID', + `creator` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '创建者', + `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间', + `updater` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT '' COMMENT '更新者', + `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间', + `deleted` bit(1) NULL DEFAULT b'0' COMMENT '是否删除', + PRIMARY KEY (`id`) USING BTREE +) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = DYNAMIC; + +SET FOREIGN_KEY_CHECKS = 1; \ No newline at end of file diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysAuthController.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysAuthController.java index 059e37c15..f90446484 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysAuthController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysAuthController.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.adminserver.modules.system.controller.auth; +import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysUserSessionService; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; @@ -19,6 +20,8 @@ import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; import cn.iocoder.yudao.framework.common.util.collection.SetUtils; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -46,6 +49,8 @@ public class SysAuthController { private SysRoleService roleService; @Resource private SysPermissionService permissionService; + @Resource + private SysUserSessionService sysUserSessionService; @PostMapping("/login") @ApiOperation("使用账号密码登录") @@ -56,6 +61,17 @@ public class SysAuthController { return success(SysAuthLoginRespVO.builder().token(token).build()); } + @RequestMapping("/auth2/login/{oauthType}") + @ApiOperation("第三方登录") + @OperateLog(enable = false) // 避免 Post 请求被记录操作日志 + public CommonResult login(@PathVariable String oauthType) { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + //TODO NPE + String token = sysUserSessionService.getSessionId(authentication.getName()); + // 返回结果 + return success(SysAuthLoginRespVO.builder().token(token).build()); + } + @GetMapping("/get-permission-info") @ApiOperation("获取登陆用户的权限信息") public CommonResult getPermissionInfo() { diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/AuthUser.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/AuthUser.java new file mode 100644 index 000000000..3d1c7680e --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/vo/user/AuthUser.java @@ -0,0 +1,7 @@ +package cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user; + +/** + * @author weir + */ +public class AuthUser { +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/auth/SysAuthConvert.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/auth/SysAuthConvert.java index 84a56ac17..f68ff3b6b 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/auth/SysAuthConvert.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/auth/SysAuthConvert.java @@ -1,5 +1,8 @@ package cn.iocoder.yudao.adminserver.modules.system.convert.auth; +import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.SysUserCreateReqVO; +import cn.iocoder.yudao.adminserver.modules.system.enums.common.SysSexEnum; +import cn.iocoder.yudao.framework.security.core.Auth2LoginUser; import cn.iocoder.yudao.framework.security.core.LoginUser; import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthMenuRespVO; import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthPermissionInfoRespVO; @@ -10,8 +13,9 @@ import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.Sys import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO; import cn.iocoder.yudao.adminserver.modules.system.enums.permission.MenuIdEnum; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; +import me.zhyd.oauth.enums.AuthUserGender; +import me.zhyd.oauth.model.AuthUser; +import org.mapstruct.*; import org.mapstruct.factory.Mappers; import org.slf4j.LoggerFactory; @@ -21,7 +25,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -@Mapper +@Mapper(uses = SysAuthConvert.UserSexTransform.class) public interface SysAuthConvert { SysAuthConvert INSTANCE = Mappers.getMapper(SysAuthConvert.class); @@ -29,6 +33,7 @@ public interface SysAuthConvert { @Mapping(source = "updateTime", target = "updateTime", ignore = true) // 字段相同,但是含义不同,忽略 LoginUser convert(SysUserDO bean); + Auth2LoginUser getAuth2LoginUser(SysUserDO bean); default SysAuthPermissionInfoRespVO convert(SysUserDO user, List roleList, List menuList) { return SysAuthPermissionInfoRespVO.builder() @@ -44,6 +49,16 @@ public interface SysAuthConvert { LoginUser convert(SysUserProfileUpdatePasswordReqVO reqVO); + @Mappings( + @Mapping(target = "sex", source = "gender") + ) + SysUserCreateReqVO convert(AuthUser authUser); + + @Mappings( + @Mapping(target = "thirdPartyUserId", source = "uuid") + ) + Auth2LoginUser getLoginUser(AuthUser authUser); + /** * 将菜单列表,构建成菜单树 * @@ -76,4 +91,24 @@ public interface SysAuthConvert { return CollectionUtils.filterList(treeNodeMap.values(), node -> MenuIdEnum.ROOT.getId().equals(node.getParentId())); } + public class UserSexTransform { + + public int toInt (AuthUserGender gender){ + switch (gender) { + case MALE: + return SysSexEnum.MALE.getSex(); + case FEMALE: + return SysSexEnum.FEMALE.getSex(); + default: + return SysSexEnum.UNKNOWN.getSex(); + } + } + + public AuthUserGender strToBoolean(int sex){ + if(sex == SysSexEnum.UNKNOWN.getSex()) { + return AuthUserGender.UNKNOWN; + } + return AuthUserGender.getRealGender(String.valueOf(sex)); + } + } } diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/auth/config/AuthConfig.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/auth/config/AuthConfig.java new file mode 100644 index 000000000..7c43c88d5 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/auth/config/AuthConfig.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.adminserver.modules.system.convert.auth.config; + +import cn.iocoder.yudao.adminserver.modules.system.convert.auth.handler.DefaultSignUpUrlAuthenticationSuccessHandler; +import cn.iocoder.yudao.framework.security.core.handler.AbstractSignUpUrlAuthenticationSuccessHandler; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author weir + */ +@Configuration +public class AuthConfig { + @Bean + public AbstractSignUpUrlAuthenticationSuccessHandler authenticationSuccessHandler() { + AbstractSignUpUrlAuthenticationSuccessHandler successHandler = new DefaultSignUpUrlAuthenticationSuccessHandler(); + successHandler.setDefaultTargetUrl("/api/callback"); + return successHandler; + } +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/auth/handler/DefaultSignUpUrlAuthenticationSuccessHandler.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/auth/handler/DefaultSignUpUrlAuthenticationSuccessHandler.java new file mode 100644 index 000000000..71e7e96ce --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/auth/handler/DefaultSignUpUrlAuthenticationSuccessHandler.java @@ -0,0 +1,112 @@ +/* + * MIT License + * Copyright (c) 2020-2029 YongWu zheng (dcenter.top and gitee.com/pcore and github.com/ZeroOrInfinity) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package cn.iocoder.yudao.adminserver.modules.system.convert.auth.handler; + +import cn.iocoder.yudao.adminserver.modules.system.controller.auth.vo.auth.SysAuthLoginRespVO; +import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysUserSessionService; +import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.security.core.Auth2LoginUser; +import cn.iocoder.yudao.framework.security.core.LoginUser; +import cn.iocoder.yudao.framework.security.core.handler.AbstractSignUpUrlAuthenticationSuccessHandler; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.DefaultRedirectStrategy; +import org.springframework.security.web.savedrequest.HttpSessionRequestCache; +import org.springframework.security.web.savedrequest.RequestCache; + +import javax.annotation.Resource; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.Set; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP; +import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getUserAgent; +import static java.util.Collections.singleton; +import static top.dcenter.ums.security.core.oauth.util.MvcUtil.*; + +/** + * @author weir + */ +public class DefaultSignUpUrlAuthenticationSuccessHandler extends AbstractSignUpUrlAuthenticationSuccessHandler { + private RequestCache requestCache = new HttpSessionRequestCache(); + @Autowired + private SysUserSessionService userSessionService; + @Resource + private SysPermissionService permissionService; + + @Override + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException { + final Object principal = authentication.getPrincipal(); + String token = userSessionService.createUserSession(defaultHandleUserRoles((LoginUser) principal), getClientIP(), getUserAgent()); + if(StringUtils.isNotBlank(token)) { + SecurityContextHolder.getContext().setAuthentication(authentication); + } + if (principal instanceof Auth2LoginUser) { + new DefaultRedirectStrategy().sendRedirect(request, response, getUrl() + token); + return; + } + if (isAjaxOrJson(request)) { + responseWithJson(response, HttpStatus.OK.value(), toJsonString(success(SysAuthLoginRespVO.builder().token(token).build()))); + return; + } + try { + requestCache.saveRequest(request, response); + super.setRequestCache(requestCache); + super.onAuthenticationSuccess(request, response, authentication); + } catch (ServletException e) { + e.printStackTrace(); + } + + } + + private String getUrl() { + return "http://localhost/oauthLogin/gitee?token="; + } + + /** + * 默认处理方式处理用户角色列表;建议角色权限前置到 UserDetails + * + * @param loginUser 用户 + * @return + */ + private LoginUser defaultHandleUserRoles(LoginUser loginUser) { + Set roleIds = loginUser.getRoleIds(); + if (roleIds == null || roleIds.isEmpty()) { + Set userRoleIds = permissionService.getUserRoleIds(loginUser.getId(), singleton(CommonStatusEnum.ENABLE.getStatus())); + loginUser.setRoleIds(userRoleIds); + } + return loginUser; + } + + @Override + public void setRequestCache(RequestCache requestCache) { + this.requestCache = requestCache; + } +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/social/SocialUserDO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/social/SocialUserDO.java new file mode 100644 index 000000000..0ef286669 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/social/SocialUserDO.java @@ -0,0 +1,13 @@ +package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.social; + +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import me.zhyd.oauth.model.AuthUser; + +/** + * @author weir + */ +@Data +@TableName("user_connection") +public class SocialUserDO extends AuthUser { +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/social/SysUserSocialDO.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/social/SysUserSocialDO.java new file mode 100644 index 000000000..41afba076 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/social/SysUserSocialDO.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.social; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 系统用户和第三方用户关联表 + * @author weir + */ +@TableName("sys_user_social") +@Data +public class SysUserSocialDO extends BaseDO { + /** + * 自增主键 + */ + @TableId + private Long id; + /** + * 用户 ID + */ + private Long userId; + /** + * 角色 ID + */ + private String socialUserId; +} + + diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/social/SysSysUserSocialMapper.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/social/SysSysUserSocialMapper.java new file mode 100644 index 000000000..72690eb10 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/social/SysSysUserSocialMapper.java @@ -0,0 +1,11 @@ +package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.social; + +import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.social.SysUserSocialDO; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface SysSysUserSocialMapper extends BaseMapperX { + + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/social/SysUserSocialMapper.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/social/SysUserSocialMapper.java new file mode 100644 index 000000000..a0df1ac7c --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/social/SysUserSocialMapper.java @@ -0,0 +1,11 @@ +package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.social; + +import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.social.SysUserSocialDO; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface SysUserSocialMapper extends BaseMapperX { + + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/common/SysSexEnum.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/common/SysSexEnum.java index c764a0f72..f5f55e7dd 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/common/SysSexEnum.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/common/SysSexEnum.java @@ -11,10 +11,12 @@ import lombok.Getter; @Getter @AllArgsConstructor public enum SysSexEnum { - - MALE(1), // 男 - FEMALE(2); // 女 - + /** 男 */ + MALE(1), + /** 女 */ + FEMALE(2), + /* 未知 */ + UNKNOWN(3); /** * 性别 */ diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysUserSessionService.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysUserSessionService.java index 11558e956..4be724fde 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysUserSessionService.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/SysUserSessionService.java @@ -45,6 +45,13 @@ public interface SysUserSessionService { */ LoginUser getLoginUser(String sessionId); + /** + * 获取当前登录用户信息 + * @param username 用户名称 + * @return 在线用户 + */ + String getSessionId(String username); + /** * 获得 Session 超时时间,单位:毫秒 * diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysUserSessionServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysUserSessionServiceImpl.java index ca95fe07b..a715971d8 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysUserSessionServiceImpl.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/SysUserSessionServiceImpl.java @@ -18,7 +18,11 @@ import cn.iocoder.yudao.adminserver.modules.system.enums.logger.SysLoginResultEn import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysUserSessionService; import cn.iocoder.yudao.adminserver.modules.system.service.logger.SysLoginLogService; import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.google.common.collect.Lists; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import javax.annotation.Resource; @@ -34,6 +38,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.addTime; * * @author 芋道源码 */ +@Slf4j @Service public class SysUserSessionServiceImpl implements SysUserSessionService { @@ -91,6 +96,15 @@ public class SysUserSessionServiceImpl implements SysUserSessionService { return loginUserRedisDAO.get(sessionId); } + @Override + public String getSessionId(String username) { + QueryWrapper wrapper = new QueryWrapper<>(); + wrapper.eq("username", username); + wrapper.orderByDesc("create_time"); + SysUserSessionDO sysUserSessionDO = userSessionMapper.selectOne(wrapper); + return sysUserSessionDO.getId(); + } + @Override public Long getSessionTimeoutMillis() { return securityProperties.getSessionTimeout().toMillis(); diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/UserDetailsServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/UserDetailsServiceImpl.java new file mode 100644 index 000000000..1ccffc9f9 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/auth/impl/UserDetailsServiceImpl.java @@ -0,0 +1,237 @@ +/* + * MIT License + * Copyright (c) 2020-2029 YongWu zheng (dcenter.top and gitee.com/pcore and github.com/ZeroOrInfinity) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package cn.iocoder.yudao.adminserver.modules.system.service.auth.impl; + +import cn.iocoder.yudao.adminserver.modules.system.controller.user.vo.user.SysUserCreateReqVO; +import cn.iocoder.yudao.adminserver.modules.system.convert.auth.SysAuthConvert; +import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO; +import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService; +import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService; +import cn.iocoder.yudao.framework.security.core.Auth2LoginUser; +import cn.iocoder.yudao.framework.security.core.LoginUser; +import com.google.common.collect.Sets; +import me.zhyd.oauth.model.AuthUser; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.lang.NonNull; +import org.springframework.security.core.authority.AuthorityUtils; +import org.springframework.security.core.userdetails.User; +import org.springframework.security.core.userdetails.UserCache; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import top.dcenter.ums.security.core.oauth.enums.ErrorCodeEnum; +import top.dcenter.ums.security.core.oauth.exception.RegisterUserFailureException; +import top.dcenter.ums.security.core.oauth.exception.UserNotExistException; +import top.dcenter.ums.security.core.oauth.service.UmsUserDetailsService; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * 用户密码与手机短信登录与注册服务:

+ * 1. 用于第三方登录与手机短信登录逻辑。

+ * 2. 用于用户密码登录逻辑。

+ * 3. 用户注册逻辑。

+ * @author YongWu zheng + * @version V1.0 Created by 2020/9/20 11:06 + */ +@Service +public class UserDetailsServiceImpl implements UmsUserDetailsService { + + private final Logger log = LoggerFactory.getLogger(this.getClass()); + + @SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection") + @Autowired(required = false) + private UserCache userCache; + + @Resource + private SysUserService userService; + + /** + * 用于密码加解密 + */ + @SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection") + @Autowired + private PasswordEncoder passwordEncoder; + @Autowired + private SysPermissionService permissionService; + + @SuppressWarnings("AlibabaUndefineMagicConstant") + @Override + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { + + try + { + // 从缓存中查询用户信息: + // 从缓存中查询用户信息 + if (this.userCache != null) + { + UserDetails userDetails = this.userCache.getUserFromCache(username); + if (userDetails != null) + { + return userDetails; + } + } + // 根据用户名获取用户信息 + // 获取 username 对应的 SysUserDO + SysUserDO user = userService.getUserByUsername(username); + if (user == null) { + throw new UsernameNotFoundException(username); + } + // 创建 LoginUser 对象 + Auth2LoginUser loginUser = SysAuthConvert.INSTANCE.getAuth2LoginUser(user); + //TODO 登录日志等可以和用户名密码等兼容处理 + return loginUser; + } + catch (Exception e) + { + String msg = String.format("第三方登录 ======>: 登录用户名:%s, 登录失败: %s", username, e.getMessage()); + log.error(msg); + throw new UserNotExistException(ErrorCodeEnum.QUERY_USER_INFO_ERROR, e, username); + } + } + + @Override + public UserDetails registerUser(@NonNull AuthUser authUser, @NonNull String username, + @NonNull String defaultAuthority, String decodeState) throws RegisterUserFailureException { + + // 这里的 decodeState 可以根据自己实现的 top.dcenter.ums.security.core.oauth.service.Auth2StateCoder 接口的逻辑来传递必要的参数. + // 比如: 第三方登录成功后的跳转地址 + final RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); + // 假设 decodeState 就是 redirectUrl, 我们直接把 redirectUrl 设置到 request 上 + // 后续经过成功处理器时直接从 requestAttributes.getAttribute("redirectUrl", RequestAttributes.SCOPE_REQUEST) 获取并跳转 + if (requestAttributes != null) { + requestAttributes.setAttribute("redirectUrl", decodeState, RequestAttributes.SCOPE_REQUEST); + } + //返回用户 + LoginUser loginUser = doRegistUser(authUser); + + log.info("第三方用户注册 ======>: 用户名:{}, 注册成功", username); + + // 把用户信息存入缓存 + if (userCache != null) + { + userCache.putUserInCache(loginUser); + } + + return loginUser; + } + + private LoginUser doRegistUser(AuthUser authUser) { + SysUserCreateReqVO reqVO = SysAuthConvert.INSTANCE.convert(authUser); + if (StringUtils.isEmpty(reqVO.getPassword())) { + reqVO.setPassword(getDefaultPassword()); + } + //添加用户 + Long sysUserId = userService.createUser(reqVO); + //关联第三方用户 + Long userId = userService.bindSocialUSer(sysUserId, authUser.getUuid()); + //赋予默认角色权限;三方登录默认部分 + permissionService.assignUserRole(userId, getDefaultRoles()); + LoginUser loginUser = SysAuthConvert.INSTANCE.getLoginUser(authUser); + loginUser.setRoleIds(getDefaultRoles()); + loginUser.setPassword(getDefaultPassword()); + loginUser.setId(sysUserId); + return loginUser; + } + + private String getDefaultPassword() { + return "123456"; + } + + protected Set getDefaultRoles() { + return Sets.newHashSet(1L); + } + + @NonNull + public UserDetails registerUser(@NonNull String mobile, Map otherParamMap) throws RegisterUserFailureException { + + // 用户信息持久化逻辑。。。 + // ... + + log.info("Demo ======>: 手机短信登录用户 {}:注册成功", mobile); + + User user = new User(mobile, + passwordEncoder.encode("admin"), + true, + true, + true, + true, + AuthorityUtils.commaSeparatedStringToAuthorityList("admin, ROLE_USER") + ); + + // 把用户信息存入缓存 + if (userCache != null) + { + userCache.putUserInCache(user); + } + + return user; + } + + /** + * {@link #existedByUsernames(String...)} usernames 生成规则. + * 如需自定义重新实现此逻辑 + * @param authUser 第三方用户信息 + * @return 返回一个 username 数组 + */ + @Override + public String[] generateUsernames(AuthUser authUser) { + return new String[]{ + authUser.getUsername(), + // providerId = authUser.getSource() + authUser.getUsername() + "_" + authUser.getSource(), + // providerUserId = authUser.getUuid() + authUser.getUsername() + "_" + authUser.getSource() + "_" + authUser.getUuid() + }; + } + + @Override + public UserDetails loadUserByUserId(String userId) throws UsernameNotFoundException { + UserDetails userDetails = loadUserByUsername(userId); + User.withUserDetails(userDetails); + return userDetails; + } + + @Override + public List existedByUsernames(String... usernames) throws UsernameNotFoundException { + // ... 在本地账户上查询 userIds 是否已被使用 + List list = new ArrayList<>(); + for (String username : usernames) { + SysUserDO userDO = userService.getUserByUsername(username); + list.add(userDO != null); + } + return list; + } + +} \ No newline at end of file diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/user/SysUserService.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/user/SysUserService.java index 16c815ace..ac2d2e78d 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/user/SysUserService.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/user/SysUserService.java @@ -34,6 +34,14 @@ public interface SysUserService { */ Long createUser(SysUserCreateReqVO reqVO); + /** + * 绑定第三方用户 + * @param sysUserId 系统用户ID + * @param socialUSerId 第三方唯一标识 + * @return + */ + Long bindSocialUSer(Long sysUserId, String socialUSerId); + /** * 修改用户 * diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/user/SysUserServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/user/SysUserServiceImpl.java index 9c344e92d..f515685fc 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/user/SysUserServiceImpl.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/user/SysUserServiceImpl.java @@ -4,6 +4,8 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.social.SysUserSocialDO; +import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.social.SysUserSocialMapper; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -49,6 +51,8 @@ public class SysUserServiceImpl implements SysUserService { @Resource private SysUserMapper userMapper; + @Resource + private SysUserSocialMapper userSocialMapper; @Resource private SysDeptService deptService; @@ -74,6 +78,15 @@ public class SysUserServiceImpl implements SysUserService { return user.getId(); } + @Override + public Long bindSocialUSer(Long sysUserId, String socialUSerId) { + SysUserSocialDO userSocialDO = new SysUserSocialDO(); + userSocialDO.setUserId(sysUserId); + userSocialDO.setSocialUserId(socialUSerId); + userSocialMapper.insert(userSocialDO); + return userSocialDO.getUserId(); + } + @Override public void updateUser(SysUserUpdateReqVO reqVO) { // 校验正确性 diff --git a/yudao-admin-server/src/main/resources/application-local.yaml b/yudao-admin-server/src/main/resources/application-local.yaml index 53ab06560..176c8dc09 100644 --- a/yudao-admin-server/src/main/resources/application-local.yaml +++ b/yudao-admin-server/src/main/resources/application-local.yaml @@ -167,3 +167,221 @@ yudao: - ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求 - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 demo: false # 关闭演示模式 + + +# ums core +ums: + one-click-login: + # 一键登录是否开启, 默认 false + enable: true + # 一键登录请求处理 url, 默认 /authentication/one-click + login-processing-url: /authentication/one-click + # token 参数名称, 默认: accessToken + token-param-name: accessToken + # 其他请求参数名称列表(包括请求头名称), 此参数会传递到 OneClickLoginService.callback(String, Map) + # 与 UserDetailsRegisterService.registerUser(String, Map); 默认为: 空 + other-param-names: + - imei + # ================ 第三方授权登录相关配置 ================ + oauth: + # 第三方授权登录后如未注册用户是否支持自动注册功能, 默认: true + auto-sign-up: true + # 第三方授权登录后如未注册用户不支持自动注册功能, 则跳转到此 url 进行注册逻辑, 此 url 必须开发者自己实现; 默认: /signUp.html; + # 注意: 当 autoSignUp = false 时, 此属性才生效. + # 例如: 1. 设置值 "/signUp", 则跳转指定到 "/signUp" 进行注册. + # 2. 想返回自定义 json 数据到前端, 这里要设置 null , 在 Auth2LoginAuthenticationFilter 设置的 AuthenticationSuccessHandler + # 上处理返回 json; 判断是否为临时用户的条件是: Authentication.getPrincipal() 是否为 TemporaryUser 类型. + sign-up-url: null + # 用于第三方授权登录时, 未开启自动注册且用户是第一次授权登录的临时用户密码, 默认为: "". 注意: 生产环境更换密码 + temporary-user-password: "" + # 用于第三方授权登录时, 未开启自动注册且用户是第一次授权登录的临时用户的默认权限, 多个权限用逗号分开, 默认为: "ROLE_TEMPORARY_USER" + temporary-user-authorities: ROLE_TEMPORARY_USER + # 抑制反射警告, 支持 JDK11, 默认: false , 在确认 WARNING: An illegal reflective access operation has occurred 安全后, 可以打开此设置, 可以抑制反射警告. + suppress-reflect-warning: true + # 第三方服务商: providerId, 支持所有 JustAuth 支持的第三方授权登录, 目前有 32 家第三方授权登录 + github: + # 根据是否有设置 clientId 来动态加载相应 JustAuth 的 AuthXxxRequest + client-id: 4d4ee00e82f669f2ea8d + client-secret: 4050be113a83556b63bd991d606fded437b05235 + scopes: + # - 'repo:status' + # - 'public_repo' + # - 'repo:invite' + # - 'user:follow' + gitee: + client-id: eb5e3298cc10ead57cd40f9f36e7154ab2ea54dcb519684d7e10ca3fec5b1c1a + client-secret: 495b5542dc007e2d46d316c527bd05dac586f2ec31b96c551e164387b5edb1cb + scopes: + - user_info +# # 自定义 OAuth2 Login +# customize: +# client-id: c971cf1634460e18310a5d7cb0f55d7d143a72015b2f29aee6a0e8911efac7eb +# client-secret: 309c9521721e3eb385a99a6bde2755f3107c7e15f3b8e0527c9f3ea4d1ce33bb +# # 自定义第三方授权登录时, 当 Auth2Properties#customize 时有效, 此字段必须以驼峰方式命名. +# # 比如此字段的值为 umsCustomize, 那么 /auth2/authorization/customize 会替换为 /auth2/authorization/umsCustomize +# customize-provider-id: giteeCustomize +# # 自定义第三方授权登录, 当 Auth2Properties#customize 时有效, 设置第三方是否在国外, 默认: false. +# # 如果为 false 时, 设置 {@link HttpConfig} 的超时时间为 ums.oauth.proxy.timeout 的值. +# # 如果为 true 时, 设置 {@link HttpConfig} 的超时时间为 ums.oauth.proxy.foreignTimeout 的值. +# customize-is-foreign: false + # 第三方登录授权登录 url 前缀, 不包含 ServletContextPath,默认为 /auth2/authorization. + auth-login-url-prefix: /api/auth2/authorization + # 第三方登录回调处理 url 前缀 ,也就是 RedirectUrl 的前缀, 不包含 ServletContextPath,默认为 /auth2/login. + redirect-url-prefix: /api/auth2/login + # 第三方登录回调的域名, 例如:http://localhost:9090 默认为 "http://127.0.0.1", + # redirectUrl 直接由 {domain}/{servletContextPath}/{redirectUrlPrefix}/{providerId}(ums.oauth.[qq/gitee/weibo])组成 + domain: http://localhost:48080 + # 第三方授权登录成功后的默认权限, 多个权限用逗号分开, 默认为: "ROLE_USER" + default-authorities: ROLE_USER + # 是否支持内置的第三方登录用户表(user_connection) 和 auth_token 表. 默认: true. + # 注意: 如果为 false, 则必须重新实现 ConnectionService 接口. + enable-user-connection-and-auth-token-table: true + # 是否支持内置的第三方登录 token 表(auth_token). 默认: true. + enable-auth-token-table: true + + + # ================ start: 定时刷新 access token 定时任务相关配置 ================ + + # 是否支持定时刷新 AccessToken 定时任务. 默认: false. + # 支持分布式(分布式 IOC 容器中必须有 RedisConnectionFactory, 也就是说, 是否分布式执行依据 IOC 容器中是否有 RedisConnectionFactory) + enableRefreshTokenJob: false + # A cron-like expression. 0 * 2 * * ? 分别对应: second/minute/hour/day of month/month/day of week, + # 默认为: "0 * 2 * * ?", 凌晨 2 点启动定时任务, 支持分布式(分布式 IOC 容器中必须有 {@link RedisConnectionFactory}, + # 也就是说, 是否分布式执行依据 IOC 容器中是否有 {@link RedisConnectionFactory}) + refresh-token-job-cron: 0 0/5 * * * ? + # 定时刷新 accessToken 任务时, 批处理数据库的记录数. 注意: 分布式应用时, 此配置不同服务器配置必须是一样的. batchCount 大小需要根据实际生产环境进行优化 + batch-count: 1000 + # accessToken 的剩余有效期内进行刷新 accessToken, 默认: 24, 单位: 小时. 注意: 需要根据实际生产环境进行优化 + remaining-expire-in: 24 + + # ================ start: 定时刷新 access token 定时任务相关配置 ================ + + # JustAuth 内部参数设置 + just-auth: + # 忽略校验 state 参数,默认不开启。当 ignoreCheckState 为 true 时, me.zhyd.oauth.request.AuthDefaultRequest.login(AuthCallback) 将不会校验 state 的合法性。 + # 使用场景:当且仅当使用自实现 state 校验逻辑时开启 + # 以下场景使用方案仅作参考: + # 1. 授权、登录为同端,并且全部使用 JustAuth 实现时,该值建议设为 false; + # 2. 授权和登录为不同端实现时,比如前端页面拼装 authorizeUrl,并且前端自行对state进行校验,后端只负责使用code获取用户信息时,该值建议设为 true; + # 如非特殊需要,不建议开启这个配置 + # 该方案主要为了解决以下类似场景的问题:Since: 1.15.6, See Also: https://github.com/justauth/JustAuth/issues/83 + ignoreCheckState: false + # 默认 state 缓存过期时间:3分钟(PT180S) 鉴于授权过程中,根据个人的操作习惯,或者授权平台的不同(google等),每个授权流程的耗时也有差异, + # 不过单个授权流程一般不会太长 本缓存工具默认的过期时间设置为3分钟,即程序默认认为3分钟内的授权有效,超过3分钟则默认失效,失效后删除 + # 注意: 这是为了测试打断点时用的, 生产环境自己设置为合适数组或默认 + timeout: PT1800S + # JustAuth state 缓存类型, 默认 session + cacheType: session + # JustAuth state 缓存 key 前缀 + cacheKeyPrefix: 'JUST_AUTH:' + + # 用于 JustAuth 的代理(HttpClient)设置 + proxy: + # 是否支持代理, 默认为: false. + enable: false + # 针对国外服务可以单独设置代理类型, 默认 Proxy.Type.HTTP, enable = true 时生效. + proxy: HTTP + # 代理 host, enable = true 时生效. + hostname: + # 代理端口, enable = true 时生效. + port: + # 用于国内代理(HttpClient)超时, 默认 PT3S + timeout: PT3S + # 用于国外网站代理(HttpClient)超时, 默认 PT15S + foreign-timeout: PT150S + + + # =============== start: 第三方登录时用的数据库表 user_connection 与 auth_token 添加 redis cache =============== + cache: + # redisCacheManager 设置, 默认实现: 对查询结果 null 值进行缓存, 添加时更新缓存 null 值. + redis: + # 是否开启缓存, 默认 false + open: false + # 是否使用 spring IOC 容器中的 RedisConnectionFactory, 默认: false + # 如果使用 spring IOC 容器中的 RedisConnectionFactory,则要注意 cache.database-index 要与 spring.redis.database 一样。 + use-ioc-redis-connection-factory: true + cache: + # redis cache 存放的 database index, 默认: 0 + database-index: 1 + # 设置缓存管理器管理的缓存的默认过期时间, 默认: 200s + default-expire-time: PT200S + # cache ttl 。使用 0 声明一个永久的缓存。 默认: 180, 单位: 秒
+ # 取缓存时间的 20% 作为动态的随机变量上下浮动, 防止同时缓存失效而缓存击穿 + entry-ttl: PT180S + # Names of the default caches to consider for caching operations defined in the annotated class. + # 此设置不对 user_connection 与 auth_token 使用的缓存名称(UCC/UCHC/UCHACC)产生影响. + cache-names: + - cacheName + # =============== end: 第三方登录时用的数据库表 user_connection 与 auth_token 添加 redis cache =============== + + # =============== start: 线程池配置 =============== + executor: + # 启动第三方授权登录用户的 accessToken 的定时任务时的 Executor 属性, 注意: 需要根据实际生产环境进行优化 + job-task-scheduled-executor: + # 线程池中空闲时保留的线程数, 默认: 0 + core-pool-size: 0 + # keep alive time, 默认: 10 + keep-alive-time: 0 + # keepAliveTime 时间单位, 默认: 毫秒 + time-unit: milliseconds + # 线程池名称, 默认: accessTokenJob + pool-name: accessTokenJob + # 拒绝策略, 默认: ABORT + rejected-execution-handler-policy: abort + # 线程池关闭过程的超时时间, 默认: PT10S + executor-shutdown-timeout: PT10S + # 更新第三方授权登录用户的 accessToken 的执行逻辑, 向本地数据库 auth_token 表获取过期或在一定时间内过期的 token 记录, + # 用 refreshToken 向第三方服务商更新 accessToken 信息的 Executor 属性, + # 注意: 定时刷新 accessToken 的执行逻辑是多线程的, 需要根据实际生产环境进行优化 + refresh-token: + # 程池中空闲时保留的线程数, 默认: 0 + core-pool-size: 0 + # 最大线程数, 默认: 本机核心数 + maximum-pool-size: 8 + # keep alive time, 默认: 5 + keep-alive-time: 5 + # keepAliveTime 时间单位, 默认: 秒 + time-unit: seconds + # blocking queue capacity, 默认: maximumPoolSize * 2 + blocking-queue-capacity: 16 + # 线程池名称, 默认: refreshToken + pool-name: refreshToken + # 拒绝策略, 默认: CALLER_RUNS 注意: 一般情况下不要更改默认设置, 没有实现 RefreshToken 逻辑被拒绝执行后的处理逻辑, 除非自己实现RefreshTokenJob.refreshTokenJob() 对 RefreshToken 逻辑被拒绝执行后的处理逻辑. + rejected-execution-handler-policy: caller_runs + # 线程池关闭过程的超时时间, 默认: 10 秒 + executor-shutdown-timeout: PT10S + # 第三方授权登录时, 异步更新用户的第三方授权用户信息与 token 信息的 Executor 属性, + # 注意: 第三方授权登录时是异步更新第三方用户信息与 token 信息到本地数据库时使用此配置, 需要根据实际生产环境进行优化 + user-connection-update: + # 程池中空闲时保留的线程数, 默认: 5 + core-pool-size: 5 + # 最大线程数, 默认: 本机核心数 + maximum-pool-size: 8 + # keep alive time, 默认: 10 + keep-alive-time: + # keepAliveTime 时间单位, 默认: 秒 + time-unit: seconds + # blocking queue capacity, 默认: maximumPoolSize * 2 + blocking-queue-capacity: 16 + # 线程池名称, 默认: updateConnection + pool-name: updateConnection + # 拒绝策略, 默认: CALLER_RUNS 注意: 一般情况下不要更改默认设置, 除非自己实现Auth2LoginAuthenticationProvider更新逻辑; + # 改成 ABORT 也支持, 默认实现 Auth2LoginAuthenticationProvider 是异步更新被拒绝执行后, 会执行同步更新. + rejected-execution-handler-policy: caller_runs + # 线程池关闭过程的超时时间, 默认: PT10S + executor-shutdown-timeout: PT10S + # =============== end: 线程池配置 =============== + + # =============== start: user_connection repository 配置 =============== + repository: + + # 第三方登录用户数据库表的字段 accessToken 与 refreshToken 加密专用密码 + text-encryptor-password: 7ca5d913a17b4942942d16a974e3fecc + # 第三方登录用户数据库表的字段 accessToken 与 refreshToken 加密专用 salt + text-encryptor-salt: cd538b1b077542aca5f86942b6507fe2 + # 是否在启动时检查并自动创建 userConnectionTableName 与 authTokenTableName, 默认: TRUE + enableStartUpInitializeTable: true + # 其他的有: 数据库表名称, 字段名称, curd sql 语句 等设置, 一般不需要更改, + # 如果要添加字段: 具体查看 RepositoryProperties 与 Auth2JdbcUsersConnectionRepository + # =============== end: user_connection repository 配置 =============== + diff --git a/yudao-admin-ui/src/api/login.js b/yudao-admin-ui/src/api/login.js index cda0d9d23..4ccf1be68 100644 --- a/yudao-admin-ui/src/api/login.js +++ b/yudao-admin-ui/src/api/login.js @@ -38,3 +38,19 @@ export function getCodeImg() { method: 'get' }) } + +// 接入第三方登录 +export function giteeLogin() { + return request({ + url: '/auth2/authorization/gitee', + method: 'get' + }) +} + +export function getToken(path) { + console.log({path}); + return request({ + url: '/auth2/login/gitee' + path, + method: 'get' + }) +} diff --git a/yudao-admin-ui/src/permission.js b/yudao-admin-ui/src/permission.js index dbca87b28..1531b4bbf 100644 --- a/yudao-admin-ui/src/permission.js +++ b/yudao-admin-ui/src/permission.js @@ -7,7 +7,7 @@ import { getToken } from '@/utils/auth' NProgress.configure({ showSpinner: false }) -const whiteList = ['/login', '/auth-redirect', '/bind', '/register'] +const whiteList = ['/login', '/auth-redirect', '/bind', '/register', '/oauthLogin/gitee'] router.beforeEach((to, from, next) => { NProgress.start() diff --git a/yudao-admin-ui/src/router/index.js b/yudao-admin-ui/src/router/index.js index 82a304551..52ddaf86d 100644 --- a/yudao-admin-ui/src/router/index.js +++ b/yudao-admin-ui/src/router/index.js @@ -43,6 +43,11 @@ export const constantRoutes = [ component: (resolve) => require(['@/views/login'], resolve), hidden: true }, + { + path: '/oauthLogin/gitee', + component: (resolve) => require(['@/views/oauthLogin'], resolve), + hidden: true + }, { path: '/404', component: (resolve) => require(['@/views/error/404'], resolve), diff --git a/yudao-admin-ui/src/views/login.vue b/yudao-admin-ui/src/views/login.vue index 40ef6f799..685eed95d 100644 --- a/yudao-admin-ui/src/views/login.vue +++ b/yudao-admin-ui/src/views/login.vue @@ -45,6 +45,11 @@ 登 录 中... + + + + +