Compare commits
2 Commits
Author | SHA1 | Date |
---|---|---|
|
8035c8b56a | |
|
a3b118aef8 |
|
@ -25,39 +25,9 @@ public class Knife4jConfig {
|
|||
return new OpenAPI().info(info).externalDocs(new ExternalDocumentation());
|
||||
}
|
||||
|
||||
// 管理员相关分类接口
|
||||
@Bean
|
||||
public GroupedOpenApi all() {
|
||||
return GroupedOpenApi.builder().group("全部请求接口").pathsToMatch("/api/**").build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GroupedOpenApi i18n() {
|
||||
return GroupedOpenApi.builder().group("多语言").pathsToMatch("/api/i18n/**", "/api/i18nType/**").build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GroupedOpenApi config() {
|
||||
return GroupedOpenApi.builder().group("配置")
|
||||
.pathsToMatch("/api/config/**", "/api/emailTemplate/**", "/api/emailUsers/**",
|
||||
"/api/message/**", "/api/messageReceived/**", "/api/messageType/**",
|
||||
"/api/menuIcon/**", "/api/schedulers/**", "/api/schedulersGroup/**"
|
||||
)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GroupedOpenApi system() {
|
||||
return GroupedOpenApi.builder().group("系统")
|
||||
.pathsToMatch("/api/dept/**", "/api/files/**", "/api/power/**",
|
||||
"/api/rolePower/**", "/api/role/**", "/api/router/**",
|
||||
"/api/routerRole/**", "/api/user/**", "/api/userRole/**"
|
||||
).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public GroupedOpenApi log() {
|
||||
return GroupedOpenApi.builder().group("日志")
|
||||
.pathsToMatch("/api/userLoginLog/**", "/api/quartzExecuteLog/**"
|
||||
).build();
|
||||
public GroupedOpenApi groupedOpenAdminApi() {
|
||||
return GroupedOpenApi.builder().group("默认请求接口").pathsToMatch("/admin/**").build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ public class AuthCustomerException extends RuntimeException {
|
|||
Integer code;
|
||||
|
||||
// 描述信息
|
||||
String message = "服务异常";
|
||||
String message;
|
||||
|
||||
// 返回结果状态
|
||||
ResultCodeEnum resultCodeEnum;
|
||||
|
|
|
@ -6,7 +6,6 @@ import cn.bunny.dao.vo.result.Result;
|
|||
import cn.bunny.dao.vo.result.ResultCodeEnum;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.support.DefaultMessageSourceResolvable;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
@ -37,7 +36,6 @@ public class GlobalExceptionHandler {
|
|||
@ResponseBody
|
||||
public Result<Object> exceptionHandler(RuntimeException exception) {
|
||||
String message = exception.getMessage();
|
||||
message = StringUtils.hasText(message) ? message : "服务器异常";
|
||||
|
||||
// 解析异常
|
||||
String jsonParseError = "JSON parse error (.*)";
|
||||
|
@ -69,7 +67,7 @@ public class GlobalExceptionHandler {
|
|||
|
||||
log.error("GlobalExceptionHandler===>运行时异常信息:{}", message);
|
||||
exception.printStackTrace();
|
||||
return Result.error(null, 500, message);
|
||||
return Result.error(null, 500, "服务器异常");
|
||||
}
|
||||
|
||||
// 捕获系统异常
|
||||
|
|
|
@ -0,0 +1,206 @@
|
|||
package cn.bunny.common.service.utils;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||
import org.apache.http.client.methods.HttpDelete;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.client.methods.HttpPut;
|
||||
import org.apache.http.conn.ClientConnectionManager;
|
||||
import org.apache.http.conn.scheme.Scheme;
|
||||
import org.apache.http.conn.scheme.SchemeRegistry;
|
||||
import org.apache.http.conn.ssl.SSLSocketFactory;
|
||||
import org.apache.http.entity.ByteArrayEntity;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.DefaultHttpClient;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class HttpUtil {
|
||||
public static HttpResponse doGet(String host, String path, String method, Map<String, String> headers, Map<String, String> querys) throws Exception {
|
||||
HttpClient httpClient = wrapClient(host);
|
||||
|
||||
HttpGet request = new HttpGet(buildUrl(host, path, querys));
|
||||
for (Map.Entry<String, String> e : headers.entrySet()) {
|
||||
request.addHeader(e.getKey(), e.getValue());
|
||||
}
|
||||
|
||||
return httpClient.execute(request);
|
||||
}
|
||||
|
||||
public static HttpResponse doPost(String host, String path, String method, Map<String, String> headers, Map<String, String> querys, Map<String, String> bodys) throws Exception {
|
||||
HttpClient httpClient = wrapClient(host);
|
||||
|
||||
HttpPost request = new HttpPost(buildUrl(host, path, querys));
|
||||
for (Map.Entry<String, String> e : headers.entrySet()) {
|
||||
request.addHeader(e.getKey(), e.getValue());
|
||||
}
|
||||
|
||||
if (bodys != null) {
|
||||
List<NameValuePair> nameValuePairList = new ArrayList<NameValuePair>();
|
||||
|
||||
for (String key : bodys.keySet()) {
|
||||
nameValuePairList.add(new BasicNameValuePair(key, bodys.get(key)));
|
||||
}
|
||||
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nameValuePairList, "utf-8");
|
||||
formEntity.setContentType("application/x-www-form-urlencoded; charset=UTF-8");
|
||||
request.setEntity(formEntity);
|
||||
}
|
||||
|
||||
return httpClient.execute(request);
|
||||
}
|
||||
|
||||
|
||||
public static HttpResponse doPost(String host, String path, String method, Map<String, String> headers, Map<String, String> querys, String body) throws Exception {
|
||||
HttpClient httpClient = wrapClient(host);
|
||||
|
||||
HttpPost request = new HttpPost(buildUrl(host, path, querys));
|
||||
for (Map.Entry<String, String> e : headers.entrySet()) {
|
||||
request.addHeader(e.getKey(), e.getValue());
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(body)) {
|
||||
request.setEntity(new StringEntity(body, "utf-8"));
|
||||
}
|
||||
|
||||
return httpClient.execute(request);
|
||||
}
|
||||
|
||||
|
||||
public static HttpResponse doPost(String host, String path, String method, Map<String, String> headers, Map<String, String> querys, byte[] body) throws Exception {
|
||||
HttpClient httpClient = wrapClient(host);
|
||||
|
||||
HttpPost request = new HttpPost(buildUrl(host, path, querys));
|
||||
for (Map.Entry<String, String> e : headers.entrySet()) {
|
||||
request.addHeader(e.getKey(), e.getValue());
|
||||
}
|
||||
|
||||
if (body != null) {
|
||||
request.setEntity(new ByteArrayEntity(body));
|
||||
}
|
||||
|
||||
return httpClient.execute(request);
|
||||
}
|
||||
|
||||
|
||||
public static HttpResponse doPut(String host, String path, String method, Map<String, String> headers, Map<String, String> querys, String body) throws Exception {
|
||||
HttpClient httpClient = wrapClient(host);
|
||||
|
||||
HttpPut request = new HttpPut(buildUrl(host, path, querys));
|
||||
for (Map.Entry<String, String> e : headers.entrySet()) {
|
||||
request.addHeader(e.getKey(), e.getValue());
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(body)) {
|
||||
request.setEntity(new StringEntity(body, "utf-8"));
|
||||
}
|
||||
|
||||
return httpClient.execute(request);
|
||||
}
|
||||
|
||||
|
||||
public static HttpResponse doPut(String host, String path, String method, Map<String, String> headers, Map<String, String> querys, byte[] body) throws Exception {
|
||||
HttpClient httpClient = wrapClient(host);
|
||||
|
||||
HttpPut request = new HttpPut(buildUrl(host, path, querys));
|
||||
for (Map.Entry<String, String> e : headers.entrySet()) {
|
||||
request.addHeader(e.getKey(), e.getValue());
|
||||
}
|
||||
|
||||
if (body != null) {
|
||||
request.setEntity(new ByteArrayEntity(body));
|
||||
}
|
||||
|
||||
return httpClient.execute(request);
|
||||
}
|
||||
|
||||
|
||||
public static HttpResponse doDelete(String host, String path, String method, Map<String, String> headers, Map<String, String> querys) throws Exception {
|
||||
HttpClient httpClient = wrapClient(host);
|
||||
|
||||
HttpDelete request = new HttpDelete(buildUrl(host, path, querys));
|
||||
for (Map.Entry<String, String> e : headers.entrySet()) {
|
||||
request.addHeader(e.getKey(), e.getValue());
|
||||
}
|
||||
|
||||
return httpClient.execute(request);
|
||||
}
|
||||
|
||||
private static String buildUrl(String host, String path, Map<String, String> querys) throws UnsupportedEncodingException {
|
||||
StringBuilder sbUrl = new StringBuilder();
|
||||
sbUrl.append(host);
|
||||
if (!StringUtils.isBlank(path)) {
|
||||
sbUrl.append(path);
|
||||
}
|
||||
if (null != querys) {
|
||||
StringBuilder sbQuery = new StringBuilder();
|
||||
for (Map.Entry<String, String> query : querys.entrySet()) {
|
||||
if (!sbQuery.isEmpty()) {
|
||||
sbQuery.append("&");
|
||||
}
|
||||
if (StringUtils.isBlank(query.getKey()) && !StringUtils.isBlank(query.getValue())) {
|
||||
sbQuery.append(query.getValue());
|
||||
}
|
||||
if (!StringUtils.isBlank(query.getKey())) {
|
||||
sbQuery.append(query.getKey());
|
||||
if (!StringUtils.isBlank(query.getValue())) {
|
||||
sbQuery.append("=");
|
||||
sbQuery.append(URLEncoder.encode(query.getValue(), StandardCharsets.UTF_8));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!sbQuery.isEmpty()) {
|
||||
sbUrl.append("?").append(sbQuery);
|
||||
}
|
||||
}
|
||||
|
||||
return sbUrl.toString();
|
||||
}
|
||||
|
||||
private static HttpClient wrapClient(String host) {
|
||||
HttpClient httpClient = new DefaultHttpClient();
|
||||
if (host.startsWith("https://")) {
|
||||
sslClient(httpClient);
|
||||
}
|
||||
|
||||
return httpClient;
|
||||
}
|
||||
|
||||
private static void sslClient(HttpClient httpClient) {
|
||||
try {
|
||||
SSLContext ctx = SSLContext.getInstance("TLS");
|
||||
X509TrustManager tm = new X509TrustManager() {
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void checkClientTrusted(X509Certificate[] xcs, String str) {
|
||||
}
|
||||
|
||||
public void checkServerTrusted(X509Certificate[] xcs, String str) {
|
||||
}
|
||||
};
|
||||
ctx.init(null, new TrustManager[]{tm}, null);
|
||||
SSLSocketFactory ssf = new SSLSocketFactory(ctx);
|
||||
ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
|
||||
ClientConnectionManager ccm = httpClient.getConnectionManager();
|
||||
SchemeRegistry registry = ccm.getSchemeRegistry();
|
||||
registry.register(new Scheme("https", 443, ssf));
|
||||
} catch (Exception ex) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,13 +11,13 @@ import java.io.IOException;
|
|||
public class ResponseUtil {
|
||||
|
||||
public static void out(HttpServletResponse response, Result<Object> result) {
|
||||
try {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
|
||||
// 注册JavaTimeModule模块
|
||||
mapper.registerModule(new JavaTimeModule());
|
||||
response.setContentType("application/json;charset=UTF-8");
|
||||
response.setStatus(HttpStatus.OK.value());
|
||||
// 注册JavaTimeModule模块
|
||||
mapper.registerModule(new JavaTimeModule());
|
||||
response.setContentType("application/json;charset=UTF-8");
|
||||
response.setStatus(HttpStatus.OK.value());
|
||||
try {
|
||||
mapper.writeValue(response.getWriter(), result);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
|
|
|
@ -13,9 +13,6 @@ import java.util.Objects;
|
|||
import java.util.Properties;
|
||||
|
||||
public class MailSenderUtil {
|
||||
private MailSenderUtil() {
|
||||
// 私有化构造器
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果启用SSL需要配置以下
|
||||
|
@ -26,8 +23,8 @@ public class MailSenderUtil {
|
|||
Properties properties = new Properties();
|
||||
// 开启认证
|
||||
properties.setProperty("mail.smtp.auth", "true");
|
||||
// 是否启用调试---会输出发送邮件调试内容
|
||||
properties.setProperty("mail.debug", "false");
|
||||
// 启用调试
|
||||
properties.setProperty("mail.debug", "true");
|
||||
// 设置链接超时
|
||||
properties.setProperty("mail.smtp.timeout", "200000");
|
||||
// 设置端口
|
||||
|
|
|
@ -23,11 +23,6 @@
|
|||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
<!-- spring-security -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
<!-- mybatis-plus -->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
|
|
|
@ -37,7 +37,7 @@ public class LoginDto {
|
|||
@Schema(name = "type", title = "登录类型")
|
||||
@NotBlank(message = "登录类型不能为空")
|
||||
@NotNull(message = "登录类型能为空")
|
||||
private String type = "default";
|
||||
private String type;
|
||||
|
||||
@Schema(name = "readMeDay", title = "记住我的天数")
|
||||
private Long readMeDay = 1L;
|
||||
|
|
|
@ -6,11 +6,6 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
|||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
|
@ -25,7 +20,7 @@ import java.util.List;
|
|||
@Accessors(chain = true)
|
||||
@TableName("sys_user")
|
||||
@Schema(name = "AdminUser对象", title = "用户信息", description = "用户信息")
|
||||
public class AdminUser extends BaseEntity implements UserDetails {
|
||||
public class AdminUser extends BaseEntity {
|
||||
|
||||
@Schema(name = "username", title = "用户名")
|
||||
private String username;
|
||||
|
@ -60,9 +55,5 @@ public class AdminUser extends BaseEntity implements UserDetails {
|
|||
@Schema(name = "status", title = "状态", description = "1:禁用 0:正常")
|
||||
private Boolean status;
|
||||
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
return List.of();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
package cn.bunny.dao.enums;
|
||||
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum LoginEnums {
|
||||
// 邮箱登录请求
|
||||
EMAIL_STRATEGY("email"),
|
||||
// 默认登录请求
|
||||
default_STRATEGY("default"),
|
||||
// 登良路请求API
|
||||
LOGIN_REQUEST_API("/api/login"),
|
||||
;
|
||||
|
||||
private final String value;
|
||||
|
||||
LoginEnums(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
|
@ -24,7 +24,7 @@ public enum ResultCodeEnum {
|
|||
EMAIL_CODE_NOT_EMPTY(201, "邮箱验证码不能为空"),
|
||||
SEND_EMAIL_CODE_NOT_EMPTY(201, "请先发送邮箱验证码"),
|
||||
EMAIL_CODE_NOT_MATCHING(201, "邮箱验证码不匹配"),
|
||||
LOGIN_ERROR(500, "账号或密码错误"),
|
||||
LOGIN_ERROR(201, "账号或密码错误"),
|
||||
LOGIN_ERROR_USERNAME_PASSWORD_NOT_EMPTY(201, "登录信息不能为空"),
|
||||
GET_BUCKET_EXCEPTION(201, "获取文件信息失败"),
|
||||
SEND_MAIL_CODE_ERROR(201, "邮件发送失败"),
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
name: auth-compose # 定义该配置的名称为 auth-dependence
|
||||
services: # 定义服务列表
|
||||
|
||||
# 安装MySQL
|
||||
mysql: # 定义 MySQL 服务
|
||||
container_name: mysql_master # 容器名称为 mysql_master
|
||||
image: mysql:8.0.33 # 使用 MySQL 8.0.33 版本的镜像
|
||||
ports:
|
||||
- "3306:3306" # 将宿主机的 3306 端口映射到容器的 3306 端口
|
||||
environment:
|
||||
- MYSQL_ROOT_PASSWORD=123456 # 设置 MySQL 的 root 用户密码为 123456
|
||||
- TZ=Asia/Shanghai # 设置时区为亚洲/上海
|
||||
volumes:
|
||||
# - ~/docker/docker_data/mysql/mysql_master/etc/my.cnf:/etc/my.cnf # 如果需要创建配置文件
|
||||
- ~/docker/docker_data/mysql/mysql_master/etc/mysql:/etc/mysql/conf.d # 挂载 MySQL 配置文件目录
|
||||
- ~/docker/docker_data/mysql/mysql_master/data:/var/lib/mysql # 挂载 MySQL 数据目录
|
||||
- ~/docker/docker_data/mysql/mysql_master/backup:/backup # 挂载备份目录
|
||||
command:
|
||||
- "--log-bin=mysql-bin" # 启用二进制日志
|
||||
- "--server-id=1" # 设置服务器 ID 为 1
|
||||
- "--collation-server=utf8mb4_unicode_ci" # 设置默认的排序规则为 utf8mb4_unicode_ci
|
||||
- "--character-set-server=utf8mb4" # 设置默认的字符集为 utf8mb4
|
||||
- "--lower-case-table-names=1" # 设置表名存储为小写
|
||||
restart: always # 设置容器总是自动重启
|
||||
privileged: true # 赋予容器特权模式
|
||||
networks:
|
||||
- auth # 将 MySQL 服务加入到 auth 网络
|
||||
|
||||
# 安装Redis
|
||||
redis: # 定义 Redis 服务
|
||||
container_name: redis_master # 容器名称为 redis_master
|
||||
image: redis:7.0.10 # 使用 Redis 7.0.10 版本的镜像
|
||||
ports:
|
||||
- "6379:6379" # 将宿主机的 6379 端口映射到容器的 6379 端口
|
||||
volumes:
|
||||
# - ~/docker/docker_data/redis_master/redis.conf:/etc/redis/redis.conf # 需要创建配置文件
|
||||
- ~/docker/docker_data/redis_master:/etc/redis # 挂载 Redis 配置文件目录
|
||||
- ~/docker/docker_data/redis_master/data:/data # 挂载 Redis 数据目录
|
||||
command:
|
||||
- "--appendonly yes" # 启用 AOF 持久化
|
||||
- "--daemonize no" # 不以守护进程方式运行
|
||||
- "--requirepass 123456" # 设置 Redis 访问密码为 123456
|
||||
- "--tcp-keepalive 300" # 设置 TCP keepalive 时间为 300 秒
|
||||
restart: always # 设置容器总是自动重启
|
||||
networks:
|
||||
- auth # 将 MySQL 服务加入到 auth 网络
|
||||
|
||||
# 安装 Minio
|
||||
minio: # 定义 Minio 服务
|
||||
image: minio/minio # 使用 Minio 官方镜像
|
||||
container_name: minio_master # 容器名称为 minio_master
|
||||
ports:
|
||||
- "9000:9000" # 将宿主机的 9000 端口映射到容器的 9000 端口
|
||||
- "9090:9090" # 将宿主机的 9090 端口映射到容器的 9090 端口
|
||||
volumes:
|
||||
- ~/docker/docker_data/minio/data:/data # 挂载 Minio 数据目录
|
||||
environment:
|
||||
- MINIO_ROOT_USER=bunny # 设置 Minio 的 root 用户名为 bunny
|
||||
- MINIO_ROOT_PASSWORD=12345678 # 设置 Minio 的 root 用户密码为 123456
|
||||
command: "server /data --console-address :9090" # 启动 Minio 服务并指定控制台地址
|
||||
restart: always # 设置容器总是自动重启
|
||||
networks:
|
||||
- auth # 将 MySQL 服务加入到 auth 网络
|
||||
|
||||
networks: # 定义网络
|
||||
auth: # 定义名为 auth 的网络
|
||||
name: auth # 网络名称为 auth
|
||||
driver: bridge # 使用 bridge 驱动(默认)
|
2
pom.xml
2
pom.xml
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.3.2</version>
|
||||
<version>3.2.3</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>cn.bunny</groupId>
|
||||
|
|
|
@ -14,7 +14,7 @@ WORKDIR /home/server
|
|||
# 复制jar包
|
||||
COPY target/*.jar /home/server/app.jar
|
||||
|
||||
# 程序内部挂在目录,看情况是否需要操作本地docker
|
||||
# 程序内部挂在目录
|
||||
VOLUME /usr/bin/docker
|
||||
VOLUME ["/var/run/docker.sock"]
|
||||
VOLUME /etc/docker/daemon.json
|
||||
|
|
|
@ -25,13 +25,6 @@
|
|||
<artifactId>service-utils</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<!-- devtools -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-devtools</artifactId>
|
||||
<scope>runtime</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<!-- spring-security -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
|
|
@ -1,14 +1,12 @@
|
|||
package cn.bunny.services;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
|
||||
@MapperScan("cn.bunny.services.mapper")
|
||||
|
@ -16,14 +14,10 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
|
|||
@EnableScheduling
|
||||
@EnableCaching
|
||||
@EnableTransactionManagement
|
||||
@Slf4j
|
||||
@SpringBootApplication
|
||||
public class ServiceApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(ServiceApplication.class, args);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public PasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import reactor.core.publisher.Mono;
|
|||
|
||||
@Tag(name = "系统配置", description = "系统配置相关接口")
|
||||
@RestController
|
||||
@RequestMapping("/api/config")
|
||||
@RequestMapping("/admin/config")
|
||||
public class ConfigurationController {
|
||||
|
||||
@Autowired
|
||||
|
|
|
@ -30,7 +30,7 @@ import java.util.List;
|
|||
*/
|
||||
@Tag(name = "系统部门", description = "部门相关接口")
|
||||
@RestController
|
||||
@RequestMapping("/api/dept")
|
||||
@RequestMapping("/admin/dept")
|
||||
public class DeptController {
|
||||
|
||||
@Autowired
|
||||
|
|
|
@ -31,7 +31,7 @@ import java.util.Map;
|
|||
*/
|
||||
@Tag(name = "邮件模板", description = "邮件模板相关接口")
|
||||
@RestController
|
||||
@RequestMapping("api/emailTemplate")
|
||||
@RequestMapping("admin/emailTemplate")
|
||||
public class EmailTemplateController {
|
||||
|
||||
@Autowired
|
||||
|
|
|
@ -32,7 +32,7 @@ import java.util.Map;
|
|||
*/
|
||||
@Tag(name = "邮箱用户发送配置", description = "邮箱用户发送配置相关接口")
|
||||
@RestController
|
||||
@RequestMapping("api/emailUsers")
|
||||
@RequestMapping("admin/emailUsers")
|
||||
public class EmailUsersController {
|
||||
|
||||
@Autowired
|
||||
|
|
|
@ -36,7 +36,7 @@ import java.util.Set;
|
|||
*/
|
||||
@Tag(name = "系统文件表", description = "系统文件相关接口")
|
||||
@RestController
|
||||
@RequestMapping("api/files")
|
||||
@RequestMapping("admin/files")
|
||||
public class FilesController {
|
||||
|
||||
@Autowired
|
||||
|
|
|
@ -31,7 +31,7 @@ import java.util.Map;
|
|||
*/
|
||||
@Tag(name = "多语言", description = "多语言相关接口")
|
||||
@RestController
|
||||
@RequestMapping("api/i18n")
|
||||
@RequestMapping("admin/i18n")
|
||||
public class I18nController {
|
||||
|
||||
@Autowired
|
||||
|
|
|
@ -26,7 +26,7 @@ import java.util.List;
|
|||
*/
|
||||
@Tag(name = "多语言类型", description = "多语言类型相关接口")
|
||||
@RestController
|
||||
@RequestMapping("api/i18nType")
|
||||
@RequestMapping("admin/i18nType")
|
||||
public class I18nTypeController {
|
||||
|
||||
@Autowired
|
||||
|
|
|
@ -30,7 +30,7 @@ import java.util.List;
|
|||
*/
|
||||
@Tag(name = "系统菜单图标", description = "系统菜单图标相关接口")
|
||||
@RestController
|
||||
@RequestMapping("api/menuIcon")
|
||||
@RequestMapping("admin/menuIcon")
|
||||
public class MenuIconController {
|
||||
|
||||
@Autowired
|
||||
|
|
|
@ -32,7 +32,7 @@ import java.util.List;
|
|||
*/
|
||||
@Tag(name = "系统消息", description = "系统消息相关接口")
|
||||
@RestController
|
||||
@RequestMapping("api/message")
|
||||
@RequestMapping("admin/message")
|
||||
public class MessageController {
|
||||
|
||||
@Autowired
|
||||
|
|
|
@ -31,7 +31,7 @@ import java.util.List;
|
|||
*/
|
||||
@Tag(name = "消息接收(用户消息)", description = "消息接收(用户消息)相关接口")
|
||||
@RestController
|
||||
@RequestMapping("/api/messageReceived")
|
||||
@RequestMapping("/admin/messageReceived")
|
||||
public class MessageReceivedController {
|
||||
|
||||
@Autowired
|
||||
|
|
|
@ -30,7 +30,7 @@ import java.util.List;
|
|||
*/
|
||||
@Tag(name = "系统消息类型", description = "系统消息类型相关接口")
|
||||
@RestController
|
||||
@RequestMapping("api/messageType")
|
||||
@RequestMapping("admin/messageType")
|
||||
public class MessageTypeController {
|
||||
|
||||
@Autowired
|
||||
|
|
|
@ -31,7 +31,7 @@ import java.util.List;
|
|||
*/
|
||||
@Tag(name = "权限", description = "权限相关接口")
|
||||
@RestController
|
||||
@RequestMapping("api/power")
|
||||
@RequestMapping("admin/power")
|
||||
public class PowerController {
|
||||
|
||||
@Autowired
|
||||
|
|
|
@ -30,7 +30,7 @@ import java.util.List;
|
|||
*/
|
||||
@Tag(name = "角色", description = "角色相关接口")
|
||||
@RestController
|
||||
@RequestMapping("api/role")
|
||||
@RequestMapping("admin/role")
|
||||
public class RoleController {
|
||||
|
||||
@Autowired
|
||||
|
|
|
@ -22,7 +22,7 @@ import java.util.List;
|
|||
*/
|
||||
@Tag(name = "角色和权限", description = "角色和权限相关接口")
|
||||
@RestController
|
||||
@RequestMapping("api/rolePower")
|
||||
@RequestMapping("admin/rolePower")
|
||||
public class RolePowerController {
|
||||
|
||||
@Autowired
|
||||
|
|
|
@ -32,7 +32,7 @@ import java.util.List;
|
|||
*/
|
||||
@Tag(name = "系统路由", description = "系统路由相关接口")
|
||||
@RestController
|
||||
@RequestMapping("api/router")
|
||||
@RequestMapping("admin/router")
|
||||
public class RouterController {
|
||||
|
||||
@Autowired
|
||||
|
|
|
@ -21,7 +21,7 @@ import java.util.List;
|
|||
*/
|
||||
@Tag(name = "路由和角色", description = "路由和角色相关接口")
|
||||
@RestController
|
||||
@RequestMapping("api/routerRole")
|
||||
@RequestMapping("admin/routerRole")
|
||||
public class RouterRoleController {
|
||||
|
||||
@Autowired
|
||||
|
|
|
@ -27,7 +27,7 @@ import java.util.List;
|
|||
*/
|
||||
@Tag(name = "调度任务执行日志", description = "调度任务执行日志相关接口")
|
||||
@RestController
|
||||
@RequestMapping("api/quartzExecuteLog")
|
||||
@RequestMapping("admin/quartzExecuteLog")
|
||||
public class ScheduleExecuteLogController {
|
||||
|
||||
@Autowired
|
||||
|
|
|
@ -32,7 +32,7 @@ import java.util.Map;
|
|||
*/
|
||||
@Tag(name = "调度任务", description = "调度任务相关接口")
|
||||
@RestController
|
||||
@RequestMapping("api/schedulers")
|
||||
@RequestMapping("admin/schedulers")
|
||||
public class SchedulersController {
|
||||
|
||||
@Autowired
|
||||
|
|
|
@ -30,7 +30,7 @@ import java.util.List;
|
|||
*/
|
||||
@Tag(name = "任务调度分组", description = "任务调度分组相关接口")
|
||||
@RestController
|
||||
@RequestMapping("api/schedulersGroup")
|
||||
@RequestMapping("admin/schedulersGroup")
|
||||
public class SchedulersGroupController {
|
||||
|
||||
@Autowired
|
||||
|
|
|
@ -21,7 +21,7 @@ import java.util.List;
|
|||
|
||||
@Tag(name = "用户信息", description = "用户信息相关接口")
|
||||
@RestController
|
||||
@RequestMapping("/api/user")
|
||||
@RequestMapping("/admin/user")
|
||||
public class UserController {
|
||||
|
||||
@Autowired
|
||||
|
|
|
@ -28,7 +28,7 @@ import java.util.List;
|
|||
*/
|
||||
@Tag(name = "用户登录日志", description = "用户登录日志相关接口")
|
||||
@RestController
|
||||
@RequestMapping("api/userLoginLog")
|
||||
@RequestMapping("admin/userLoginLog")
|
||||
public class UserLoginLogController {
|
||||
|
||||
@Autowired
|
||||
|
|
|
@ -21,7 +21,7 @@ import java.util.List;
|
|||
*/
|
||||
@Tag(name = "用户和角色", description = "用户和角色相关接口")
|
||||
@RestController
|
||||
@RequestMapping("api/userRole")
|
||||
@RequestMapping("admin/userRole")
|
||||
public class UserRoleController {
|
||||
|
||||
@Autowired
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package cn.bunny.services.utils.email;
|
||||
package cn.bunny.services.factory;
|
||||
|
||||
import cn.bunny.common.service.exception.AuthCustomerException;
|
||||
import cn.bunny.common.service.utils.mail.MailSenderUtil;
|
||||
|
@ -7,6 +7,7 @@ import cn.bunny.dao.entity.system.EmailUsers;
|
|||
import cn.bunny.dao.model.email.EmailSend;
|
||||
import cn.bunny.dao.model.email.EmailSendInit;
|
||||
import cn.bunny.dao.vo.result.ResultCodeEnum;
|
||||
import cn.bunny.services.mapper.EmailTemplateMapper;
|
||||
import cn.bunny.services.mapper.EmailUsersMapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import jakarta.mail.MessagingException;
|
||||
|
@ -18,19 +19,19 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public abstract class AbstractSenderEmailTemplate {
|
||||
public class EmailFactory {
|
||||
|
||||
@Autowired
|
||||
private EmailTemplateMapper emailTemplateMapper;
|
||||
|
||||
@Autowired
|
||||
private EmailUsersMapper emailUsersMapper;
|
||||
|
||||
/**
|
||||
* 基本邮件发送模板
|
||||
*
|
||||
* @param email 邮箱
|
||||
* @param emailTemplate 邮箱模板
|
||||
* @param params 传入的参数
|
||||
* * 发送邮件模板
|
||||
* 根据已存在的邮件模板发送邮件
|
||||
*/
|
||||
public void sendEmail(String email, EmailTemplate emailTemplate, HashMap<String, Object> params) {
|
||||
public void sendEmailTemplate(String email, EmailTemplate emailTemplate, HashMap<String, Object> params) {
|
||||
// 判断邮件模板是否为空
|
||||
if (emailTemplate == null) throw new AuthCustomerException(ResultCodeEnum.EMAIL_TEMPLATE_IS_EMPTY);
|
||||
|
||||
|
@ -68,4 +69,27 @@ public abstract class AbstractSenderEmailTemplate {
|
|||
throw new AuthCustomerException(ResultCodeEnum.SEND_MAIL_CODE_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* * 发送邮件模板
|
||||
* 根据邮件模板发送邮件
|
||||
*/
|
||||
public void sendEmailTemplate(String email, Long emailTemplateId, HashMap<String, Object> params) {
|
||||
EmailTemplate emailTemplate = emailTemplateMapper.selectOne(Wrappers.<EmailTemplate>lambdaQuery().eq(EmailTemplate::getId, emailTemplateId));
|
||||
sendEmailTemplate(email, emailTemplate, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断邮箱是否添加
|
||||
*
|
||||
* @param isDefault 邮箱是否为默认
|
||||
*/
|
||||
public void updateEmailUserDefault(Boolean isDefault) {
|
||||
EmailUsers emailUsers = new EmailUsers();
|
||||
// 判断状态,如果是默认将所有的内容都设为false
|
||||
if (isDefault) {
|
||||
emailUsers.setIsDefault(false);
|
||||
emailUsersMapper.update(emailUsers, Wrappers.<EmailUsers>lambdaUpdate().eq(EmailUsers::getIsDefault, true));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package cn.bunny.services.factory;
|
||||
|
||||
import cn.bunny.dao.vo.system.rolePower.PowerVo;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class PowerFactory {
|
||||
|
||||
|
||||
/**
|
||||
* * 构建权限树形结构
|
||||
*
|
||||
* @param id 节点ID
|
||||
* @param powerVoList 节点列表
|
||||
* @return 树形列表
|
||||
*/
|
||||
public List<PowerVo> handlePowerVoChildren(Long id, List<PowerVo> powerVoList) {
|
||||
return powerVoList.stream()
|
||||
.filter(powerVo -> powerVo.getParentId().equals(id))
|
||||
.peek(powerVo -> powerVo.setChildren(handlePowerVoChildren(powerVo.getId(), powerVoList)))
|
||||
.toList();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package cn.bunny.services.factory;
|
||||
|
||||
import cn.bunny.dao.constant.RedisUserConstant;
|
||||
import cn.bunny.dao.entity.system.AdminUser;
|
||||
import cn.bunny.services.mapper.UserMapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class RoleFactory {
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@Autowired
|
||||
private UserMapper userMapper;
|
||||
|
||||
@Autowired
|
||||
private UserFactory userFactory;
|
||||
|
||||
/**
|
||||
* 批量更新Redis中用户信息
|
||||
*
|
||||
* @param userIds 用户Id列表
|
||||
*/
|
||||
public void updateUserRedisInfo(List<Long> userIds) {
|
||||
// 根据Id查找所有用户
|
||||
List<AdminUser> adminUsers = userMapper.selectList(Wrappers.<AdminUser>lambdaQuery().in(AdminUser::getId, userIds));
|
||||
|
||||
// 用户为空时不更新Redis的key
|
||||
if (adminUsers.isEmpty()) return;
|
||||
|
||||
// 更新Redis中用户信息
|
||||
adminUsers.stream().filter(user -> {
|
||||
String adminLoginInfoPrefix = RedisUserConstant.getAdminLoginInfoPrefix(user.getUsername());
|
||||
Object object = redisTemplate.opsForValue().get(adminLoginInfoPrefix);
|
||||
return object != null;
|
||||
}).forEach(user -> userFactory.buildUserVo(user, RedisUserConstant.REDIS_EXPIRATION_TIME));
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package cn.bunny.services.utils;
|
||||
package cn.bunny.services.factory;
|
||||
|
||||
import cn.bunny.dao.vo.system.router.UserRouterVo;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
@ -8,7 +8,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class RouterServiceUtil {
|
||||
public class RouterServiceFactory {
|
||||
|
||||
/**
|
||||
* * 递归调用设置子路由
|
|
@ -1,6 +1,5 @@
|
|||
package cn.bunny.services.utils;
|
||||
package cn.bunny.services.factory;
|
||||
|
||||
import cn.bunny.common.service.exception.AuthCustomerException;
|
||||
import cn.bunny.common.service.utils.JwtHelper;
|
||||
import cn.bunny.common.service.utils.ip.IpUtil;
|
||||
import cn.bunny.common.service.utils.minio.MinioUtil;
|
||||
|
@ -16,6 +15,7 @@ import cn.bunny.services.mapper.PowerMapper;
|
|||
import cn.bunny.services.mapper.RoleMapper;
|
||||
import cn.bunny.services.mapper.UserLoginLogMapper;
|
||||
import cn.bunny.services.mapper.UserMapper;
|
||||
import cn.bunny.services.security.custom.CustomCheckIsAdmin;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -35,7 +35,7 @@ import java.util.regex.Matcher;
|
|||
import java.util.regex.Pattern;
|
||||
|
||||
@Component
|
||||
public class UserUtil {
|
||||
public class UserFactory {
|
||||
@Autowired
|
||||
private PowerMapper powerMapper;
|
||||
|
||||
|
@ -54,14 +54,7 @@ public class UserUtil {
|
|||
@Autowired
|
||||
private MinioUtil minioUtil;
|
||||
|
||||
/**
|
||||
* 构建登录用户返回对象
|
||||
*
|
||||
* @param user 用户
|
||||
* @param readMeDay 保存登录信息时间
|
||||
* @return 登录信息
|
||||
*/
|
||||
@Transactional(rollbackFor = AuthCustomerException.class)
|
||||
@Transactional
|
||||
public LoginVo buildLoginUserVo(AdminUser user, long readMeDay) {
|
||||
Long userId = user.getId();
|
||||
String email = user.getEmail();
|
||||
|
@ -131,7 +124,7 @@ public class UserUtil {
|
|||
List<String> permissions = new ArrayList<>();
|
||||
|
||||
// 判断是否是 admin 如果是admin 赋予所有权限
|
||||
boolean isAdmin = RoleUtil.checkAdmin(roles, permissions, user);
|
||||
boolean isAdmin = CustomCheckIsAdmin.checkAdmin(roles, permissions, user);
|
||||
if (!isAdmin) {
|
||||
permissions = powerMapper.selectListByUserId(userId).stream().map(Power::getPowerCode).toList();
|
||||
}
|
|
@ -1,24 +1,20 @@
|
|||
package cn.bunny.services.security.config;
|
||||
|
||||
import cn.bunny.dao.entity.system.AdminUser;
|
||||
import cn.bunny.dao.vo.result.ResultCodeEnum;
|
||||
import cn.bunny.services.mapper.UserMapper;
|
||||
import cn.bunny.services.security.custom.CustomAuthorizationManagerServiceImpl;
|
||||
import cn.bunny.services.security.custom.CustomPasswordEncoder;
|
||||
import cn.bunny.services.security.filter.TokenLoginFilterService;
|
||||
import cn.bunny.services.security.handelr.SecurityAccessDeniedHandler;
|
||||
import cn.bunny.services.security.handelr.SecurityAuthenticationEntryPoint;
|
||||
import cn.bunny.services.service.UserService;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import cn.bunny.services.security.service.CustomUserDetailsService;
|
||||
import cn.bunny.services.security.service.impl.CustomAuthorizationManagerServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.security.web.util.matcher.RegexRequestMatcher;
|
||||
|
@ -28,7 +24,6 @@ import org.springframework.security.web.util.matcher.RegexRequestMatcher;
|
|||
@EnableMethodSecurity
|
||||
public class WebSecurityConfig {
|
||||
|
||||
// 需要排出的无需验证的请求路径
|
||||
public static String[] annotations = {
|
||||
"/", "/ws/**",
|
||||
"/*/*/noAuth/**", "/*/noAuth/**", "/noAuth/**",
|
||||
|
@ -37,7 +32,13 @@ public class WebSecurityConfig {
|
|||
};
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@Autowired
|
||||
private CustomUserDetailsService customUserDetailsService;
|
||||
|
||||
@Autowired
|
||||
private CustomPasswordEncoder customPasswordEncoder;
|
||||
|
||||
@Autowired
|
||||
private CustomAuthorizationManagerServiceImpl customAuthorizationManagerService;
|
||||
|
@ -72,31 +73,10 @@ public class WebSecurityConfig {
|
|||
exception.accessDeniedHandler(new SecurityAccessDeniedHandler());
|
||||
})
|
||||
// 登录验证过滤器
|
||||
.addFilterBefore(new TokenLoginFilterService(authenticationConfiguration, userService), UsernamePasswordAuthenticationFilter.class);
|
||||
.addFilterBefore(new TokenLoginFilterService(authenticationConfiguration, redisTemplate, customUserDetailsService), UsernamePasswordAuthenticationFilter.class)
|
||||
// 自定义密码加密器和用户登录
|
||||
.passwordManagement(customPasswordEncoder).userDetailsService(customUserDetailsService);
|
||||
|
||||
return httpSecurity.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用数据库方式
|
||||
* 登录方式:邮箱+用户名
|
||||
*
|
||||
* @param userMapper 获取用户数据
|
||||
* @return 数据库的用户
|
||||
*/
|
||||
@Bean
|
||||
public UserDetailsService userDetailsService(UserMapper userMapper) {
|
||||
return username -> {
|
||||
// 查询用户相关内容
|
||||
LambdaQueryWrapper<AdminUser> queryWrapper = new LambdaQueryWrapper<AdminUser>()
|
||||
.eq(AdminUser::getEmail, username)
|
||||
.or()
|
||||
.eq(AdminUser::getUsername, username);
|
||||
|
||||
// 根据邮箱查询用户名
|
||||
AdminUser adminUser = userMapper.selectOne(queryWrapper);
|
||||
if (adminUser == null) throw new UsernameNotFoundException(ResultCodeEnum.USER_IS_EMPTY.getMessage());
|
||||
|
||||
return adminUser;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,11 +13,10 @@ import org.springframework.security.core.AuthenticationException;
|
|||
@ToString
|
||||
@Slf4j
|
||||
public class CustomAuthenticationException extends AuthenticationException {
|
||||
String message;
|
||||
ResultCodeEnum resultCodeEnum;
|
||||
|
||||
public CustomAuthenticationException(String message) {
|
||||
super(message);
|
||||
this.message = message;
|
||||
public CustomAuthenticationException(ResultCodeEnum codeEnum) {
|
||||
super(codeEnum.getMessage());
|
||||
this.resultCodeEnum = codeEnum;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
package cn.bunny.services.security.custom;
|
||||
|
||||
import cn.bunny.common.service.context.BaseContext;
|
||||
import cn.bunny.dao.entity.system.AdminUser;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 检查是否是管理员
|
||||
*/
|
||||
public class CustomCheckIsAdmin {
|
||||
|
||||
/**
|
||||
* 判断是否是管理员
|
||||
*
|
||||
* @param roleList 角色代码列表
|
||||
* @return 是否是管理员
|
||||
*/
|
||||
public static boolean checkAdmin(List<String> roleList) {
|
||||
// 判断是否是超级管理员
|
||||
if (BaseContext.getUserId().equals(1L)) return true;
|
||||
|
||||
// 判断是否是 admin
|
||||
return roleList.stream().anyMatch(role -> role.equals("admin"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否是管理员
|
||||
*
|
||||
* @param roleList 角色代码列表
|
||||
* @param permissions 权限列表
|
||||
* @param adminUser 用户信息
|
||||
* @return 是否是管理员
|
||||
*/
|
||||
public static boolean checkAdmin(List<String> roleList, List<String> permissions, AdminUser adminUser) {
|
||||
// 判断是否是超级管理员
|
||||
boolean isIdAdmin = adminUser.getId().equals(1L);
|
||||
boolean isAdmin = roleList.stream().anyMatch(role -> role.equals("admin"));
|
||||
|
||||
// 判断是否是 admin
|
||||
if (isIdAdmin || isAdmin) {
|
||||
roleList.add("admin");
|
||||
permissions.add("*");
|
||||
permissions.add("*::*");
|
||||
permissions.add("*::*::*");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package cn.bunny.services.security.custom;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.Customizer;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.PasswordManagementConfigurer;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.util.DigestUtils;
|
||||
|
||||
/**
|
||||
* 自定义密码加密比对
|
||||
*/
|
||||
@Configuration
|
||||
public class CustomPasswordEncoder implements PasswordEncoder, Customizer<PasswordManagementConfigurer<HttpSecurity>> {
|
||||
@Override
|
||||
public String encode(CharSequence rawPassword) {
|
||||
return DigestUtils.md5DigestAsHex(rawPassword.toString().getBytes());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean matches(CharSequence rawPassword, String encodedPassword) {
|
||||
return encodedPassword.matches(DigestUtils.md5DigestAsHex(rawPassword.toString().getBytes()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customize(PasswordManagementConfigurer<HttpSecurity> httpSecurityPasswordManagementConfigurer) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package cn.bunny.services.security.custom;
|
||||
|
||||
import cn.bunny.dao.entity.system.AdminUser;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 重写自带的User
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public class CustomUser extends User {
|
||||
private AdminUser user;
|
||||
|
||||
public CustomUser(AdminUser user, Collection<? extends GrantedAuthority> authorities) {
|
||||
super(user.getUsername(), user.getPassword(), authorities);
|
||||
this.user = user;
|
||||
}
|
||||
}
|
|
@ -1,44 +1,52 @@
|
|||
package cn.bunny.services.security.filter;
|
||||
|
||||
|
||||
import cn.bunny.common.service.utils.ResponseUtil;
|
||||
import cn.bunny.dao.constant.RedisUserConstant;
|
||||
import cn.bunny.dao.dto.system.user.LoginDto;
|
||||
import cn.bunny.dao.enums.LoginEnums;
|
||||
import cn.bunny.dao.vo.result.Result;
|
||||
import cn.bunny.dao.vo.result.ResultCodeEnum;
|
||||
import cn.bunny.dao.vo.system.user.LoginVo;
|
||||
import cn.bunny.services.security.handelr.SecurityAuthenticationFailureHandler;
|
||||
import cn.bunny.services.security.handelr.SecurityAuthenticationSuccessHandler;
|
||||
import cn.bunny.services.service.UserService;
|
||||
import cn.bunny.services.security.service.CustomUserDetailsService;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import static cn.bunny.common.service.utils.ResponseUtil.out;
|
||||
|
||||
/**
|
||||
* 自定义登录
|
||||
* 自定义登录路径和自定义登录返回数据
|
||||
* * UsernamePasswordAuthenticationFilter
|
||||
* * 也可以在这里添加验证码、短信等的验证
|
||||
* 由于SpringSecurity的登录只能是表单形式 并且用户名密码需要时username、password,可以通过继承 UsernamePasswordAuthenticationFilter 获取登录请求的参数
|
||||
* 再去设置到 UsernamePasswordAuthenticationToken 中 来改变请求传参方式、参数名等 或者也可以在登录的时候加入其他参数等等
|
||||
*/
|
||||
public class TokenLoginFilterService extends UsernamePasswordAuthenticationFilter {
|
||||
private final UserService userService;
|
||||
LoginDto loginDto;
|
||||
|
||||
public TokenLoginFilterService(AuthenticationConfiguration authenticationConfiguration, UserService customUserDetailsService) throws Exception {
|
||||
private final RedisTemplate<String, Object> redisTemplate;
|
||||
private final CustomUserDetailsService customUserDetailsService;
|
||||
private LoginDto loginDto;
|
||||
|
||||
public TokenLoginFilterService(AuthenticationConfiguration authenticationConfiguration, RedisTemplate<String, Object> redisTemplate, CustomUserDetailsService customUserDetailsService) throws Exception {
|
||||
this.setAuthenticationSuccessHandler(new SecurityAuthenticationSuccessHandler());
|
||||
this.setAuthenticationFailureHandler(new SecurityAuthenticationFailureHandler());
|
||||
this.setPostOnly(false);
|
||||
// 自定义登录路径,自定义登录请求类型
|
||||
this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher(LoginEnums.LOGIN_REQUEST_API.getValue(), HttpMethod.POST.name()));
|
||||
this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/admin/login", HttpMethod.POST.name()));
|
||||
this.setAuthenticationManager(authenticationConfiguration.getAuthenticationManager());
|
||||
this.userService = customUserDetailsService;
|
||||
this.redisTemplate = redisTemplate;
|
||||
this.customUserDetailsService = customUserDetailsService;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -50,22 +58,61 @@ public class TokenLoginFilterService extends UsernamePasswordAuthenticationFilte
|
|||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
try {
|
||||
loginDto = objectMapper.readValue(request.getInputStream(), LoginDto.class);
|
||||
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(loginDto.getUsername(), loginDto.getPassword());
|
||||
return getAuthenticationManager().authenticate(authentication);
|
||||
} catch (Exception exception) {
|
||||
throw new UsernameNotFoundException(exception.getMessage());
|
||||
|
||||
// type不能为空
|
||||
String type = loginDto.getType();
|
||||
if (!StringUtils.hasText(type)) {
|
||||
out(response, Result.error(ResultCodeEnum.REQUEST_IS_EMPTY));
|
||||
return null;
|
||||
}
|
||||
|
||||
String emailCode = loginDto.getEmailCode();
|
||||
String username = loginDto.getUsername();
|
||||
String password = loginDto.getPassword();
|
||||
|
||||
// 如果有邮箱验证码,表示是邮箱登录
|
||||
if (type.equals("email")) {
|
||||
emailCode = emailCode.toLowerCase();
|
||||
Object redisEmailCode = redisTemplate.opsForValue().get(RedisUserConstant.getAdminUserEmailCodePrefix(username));
|
||||
// --------TODO 线上取消注释这个
|
||||
// ----测试
|
||||
// --------线上取消注释这个
|
||||
// if (redisEmailCode == null) {
|
||||
// out(response, Result.error(ResultCodeEnum.EMAIL_CODE_EMPTY));
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// // 判断用户邮箱验证码是否和Redis中发送的验证码
|
||||
// if (!emailCode.equals(redisEmailCode.toString().toLowerCase())) {
|
||||
// out(response, Result.error(ResultCodeEnum.EMAIL_CODE_NOT_MATCHING));
|
||||
// return null;
|
||||
// }
|
||||
}
|
||||
|
||||
Authentication authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
|
||||
return getAuthenticationManager().authenticate(authenticationToken);
|
||||
} catch (IOException e) {
|
||||
out(response, Result.error(ResultCodeEnum.ILLEGAL_DATA_REQUEST));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证成功
|
||||
* 在这里用户的账号和密码是对的
|
||||
* 此时不要再去解析/转换 request.getInputStream() 因为流已经关闭
|
||||
*/
|
||||
@Override
|
||||
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication auth) {
|
||||
LoginVo loginVo = userService.login(loginDto, response);
|
||||
ResponseUtil.out(response, Result.success(loginVo));
|
||||
// 获取登录返回信息
|
||||
LoginVo loginVo = customUserDetailsService.login(loginDto, response);
|
||||
if (loginVo == null) return;
|
||||
|
||||
// 判断用户是否禁用
|
||||
if (loginVo.getStatus()) {
|
||||
out(response, Result.error(ResultCodeEnum.FAIL_NO_ACCESS_DENIED_USER_LOCKED));
|
||||
return;
|
||||
}
|
||||
|
||||
out(response, Result.success(loginVo));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -73,6 +120,12 @@ public class TokenLoginFilterService extends UsernamePasswordAuthenticationFilte
|
|||
*/
|
||||
@Override
|
||||
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) {
|
||||
ResponseUtil.out(response, Result.error(null, failed.getMessage()));
|
||||
String password = loginDto.getPassword();
|
||||
String username = loginDto.getUsername();
|
||||
|
||||
if (!StringUtils.hasText(password) || !StringUtils.hasText(username))
|
||||
out(response, Result.error(ResultCodeEnum.USERNAME_OR_PASSWORD_NOT_EMPTY));
|
||||
else
|
||||
out(response, Result.error(null, ResultCodeEnum.LOGIN_ERROR));
|
||||
}
|
||||
}
|
|
@ -7,12 +7,11 @@ import jakarta.servlet.http.HttpServletRequest;
|
|||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||
|
||||
/**
|
||||
* 没有权限访问
|
||||
*/
|
||||
public class SecurityAccessDeniedHandler implements AccessDeniedHandler {
|
||||
public class SecurityAccessDeniedHandler implements org.springframework.security.web.access.AccessDeniedHandler {
|
||||
@SneakyThrows
|
||||
@Override
|
||||
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) {
|
||||
|
|
|
@ -5,11 +5,10 @@ import com.alibaba.fastjson2.JSON;
|
|||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class SecurityAuthenticationFailureHandler implements AuthenticationFailureHandler {
|
||||
public class SecurityAuthenticationFailureHandler implements org.springframework.security.web.authentication.AuthenticationFailureHandler {
|
||||
@Override
|
||||
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException {
|
||||
// 错误消息
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
package cn.bunny.services.security.service;
|
||||
|
||||
import cn.bunny.dao.dto.system.user.LoginDto;
|
||||
import cn.bunny.dao.vo.system.user.LoginVo;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
|
||||
public interface CustomUserDetailsService extends UserDetailsService {
|
||||
/**
|
||||
* 根据用户名获取用户对象(获取不到直接抛异常)
|
||||
*/
|
||||
@Override
|
||||
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
|
||||
|
||||
/**
|
||||
* 前台用户登录接口
|
||||
*
|
||||
* @param loginDto 登录参数
|
||||
* @return 登录后结果返回
|
||||
*/
|
||||
LoginVo login(LoginDto loginDto, HttpServletResponse response);
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package cn.bunny.services.security.custom;
|
||||
package cn.bunny.services.security.service.impl;
|
||||
|
||||
import cn.bunny.common.service.context.BaseContext;
|
||||
import cn.bunny.common.service.utils.JwtHelper;
|
||||
|
@ -9,7 +9,8 @@ import cn.bunny.dao.vo.result.ResultCodeEnum;
|
|||
import cn.bunny.dao.vo.system.user.LoginVo;
|
||||
import cn.bunny.services.mapper.PowerMapper;
|
||||
import cn.bunny.services.mapper.RoleMapper;
|
||||
import cn.bunny.services.utils.RoleUtil;
|
||||
import cn.bunny.services.security.custom.CustomAuthenticationException;
|
||||
import cn.bunny.services.security.custom.CustomCheckIsAdmin;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
@ -18,7 +19,6 @@ import org.springframework.data.redis.core.RedisTemplate;
|
|||
import org.springframework.security.authorization.AuthorizationDecision;
|
||||
import org.springframework.security.authorization.AuthorizationManager;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.web.access.intercept.RequestAuthorizationContext;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
@ -54,12 +54,12 @@ public class CustomAuthorizationManagerServiceImpl implements AuthorizationManag
|
|||
// 判断是否有 token
|
||||
String token = request.getHeader("token");
|
||||
if (token == null) {
|
||||
throw new UsernameNotFoundException(ResultCodeEnum.LOGIN_AUTH.getMessage());
|
||||
throw new CustomAuthenticationException(ResultCodeEnum.LOGIN_AUTH);
|
||||
}
|
||||
|
||||
// 判断 token 是否过期
|
||||
if (JwtHelper.isExpired(token)) {
|
||||
throw new UsernameNotFoundException(ResultCodeEnum.AUTHENTICATION_EXPIRED.getMessage());
|
||||
throw new CustomAuthenticationException(ResultCodeEnum.AUTHENTICATION_EXPIRED);
|
||||
}
|
||||
|
||||
// 解析JWT中的用户名
|
||||
|
@ -72,12 +72,12 @@ public class CustomAuthorizationManagerServiceImpl implements AuthorizationManag
|
|||
|
||||
// 登录信息为空
|
||||
if (loginVo == null) {
|
||||
throw new UsernameNotFoundException(ResultCodeEnum.LOGIN_AUTH.getMessage());
|
||||
throw new CustomAuthenticationException(ResultCodeEnum.LOGIN_AUTH);
|
||||
}
|
||||
|
||||
// 判断用户是否禁用
|
||||
if (loginVo.getStatus()) {
|
||||
throw new UsernameNotFoundException(ResultCodeEnum.FAIL_NO_ACCESS_DENIED_USER_LOCKED.getMessage());
|
||||
throw new CustomAuthenticationException(ResultCodeEnum.FAIL_NO_ACCESS_DENIED_USER_LOCKED);
|
||||
}
|
||||
|
||||
// 设置用户信息
|
||||
|
@ -103,7 +103,7 @@ public class CustomAuthorizationManagerServiceImpl implements AuthorizationManag
|
|||
List<String> roleCodeList = roleList.stream().map(Role::getRoleCode).toList();
|
||||
|
||||
// 判断是否是管理员用户
|
||||
boolean checkedAdmin = RoleUtil.checkAdmin(roleCodeList);
|
||||
boolean checkedAdmin = CustomCheckIsAdmin.checkAdmin(roleCodeList);
|
||||
if (checkedAdmin) return true;
|
||||
|
||||
// 判断请求地址是否是 noManage 不需要被验证的
|
|
@ -0,0 +1,85 @@
|
|||
package cn.bunny.services.security.service.impl;
|
||||
|
||||
import cn.bunny.common.service.exception.AuthCustomerException;
|
||||
import cn.bunny.dao.dto.system.user.LoginDto;
|
||||
import cn.bunny.dao.entity.system.AdminUser;
|
||||
import cn.bunny.dao.vo.result.Result;
|
||||
import cn.bunny.dao.vo.result.ResultCodeEnum;
|
||||
import cn.bunny.dao.vo.system.user.LoginVo;
|
||||
import cn.bunny.services.factory.UserFactory;
|
||||
import cn.bunny.services.mapper.UserMapper;
|
||||
import cn.bunny.services.security.custom.CustomUser;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.DigestUtils;
|
||||
|
||||
import static cn.bunny.common.service.utils.ResponseUtil.out;
|
||||
|
||||
@Component
|
||||
public class CustomUserDetailsServiceImpl implements cn.bunny.services.security.service.CustomUserDetailsService {
|
||||
|
||||
@Autowired
|
||||
private UserMapper userMapper;
|
||||
|
||||
@Autowired
|
||||
private UserFactory userFactory;
|
||||
|
||||
/**
|
||||
* 根据用户名获取用户对象(获取不到直接抛异常)
|
||||
*
|
||||
* @param username 用户名
|
||||
*/
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
// 查询用户相关内容
|
||||
LambdaQueryWrapper<AdminUser> queryWrapper = new LambdaQueryWrapper<AdminUser>()
|
||||
.eq(AdminUser::getEmail, username)
|
||||
.or()
|
||||
.eq(AdminUser::getUsername, username);
|
||||
|
||||
// 根据邮箱查询用户名
|
||||
AdminUser adminUser = userMapper.selectOne(queryWrapper);
|
||||
if (adminUser == null) throw new UsernameNotFoundException(ResultCodeEnum.USER_IS_EMPTY.getMessage());
|
||||
|
||||
return new CustomUser(adminUser, AuthorityUtils.createAuthorityList());
|
||||
}
|
||||
|
||||
/**
|
||||
* 前台用户登录接口
|
||||
*
|
||||
* @param loginDto 登录参数
|
||||
* @return 登录后结果返回
|
||||
*/
|
||||
@Override
|
||||
public LoginVo login(LoginDto loginDto, HttpServletResponse response) {
|
||||
String username = loginDto.getUsername();
|
||||
String password = loginDto.getPassword();
|
||||
Long readMeDay = loginDto.getReadMeDay();
|
||||
|
||||
// 查询用户相关内容
|
||||
LambdaQueryWrapper<AdminUser> queryWrapper = new LambdaQueryWrapper<>();
|
||||
if (loginDto.getType().equals("email")) {
|
||||
queryWrapper.eq(AdminUser::getEmail, username);
|
||||
} else {
|
||||
queryWrapper.eq(AdminUser::getUsername, username);
|
||||
}
|
||||
AdminUser user = userMapper.selectOne(queryWrapper);
|
||||
|
||||
// 判断用户是否为空
|
||||
if (user == null) {
|
||||
out(response, Result.error(ResultCodeEnum.LOGIN_ERROR));
|
||||
return null;
|
||||
}
|
||||
|
||||
// 对登录密码进行md5加密判断,是否与数据库中一致
|
||||
String md5Password = DigestUtils.md5DigestAsHex(password.getBytes());
|
||||
if (!user.getPassword().equals(md5Password)) throw new AuthCustomerException(ResultCodeEnum.LOGIN_ERROR);
|
||||
|
||||
return userFactory.buildLoginUserVo(user, readMeDay);
|
||||
}
|
||||
}
|
|
@ -6,7 +6,6 @@ import cn.bunny.dao.vo.result.PageResult;
|
|||
import cn.bunny.dao.vo.system.user.*;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.Valid;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
@ -21,14 +20,6 @@ import java.util.List;
|
|||
* @since 2024-09-26
|
||||
*/
|
||||
public interface UserService extends IService<AdminUser> {
|
||||
|
||||
/**
|
||||
* 前台用户登录接口
|
||||
*
|
||||
* @param loginDto 登录参数
|
||||
* @return 登录后结果返回
|
||||
*/
|
||||
LoginVo login(LoginDto loginDto, HttpServletResponse response);
|
||||
|
||||
/**
|
||||
* * 获取用户信息列表
|
||||
|
|
|
@ -9,10 +9,10 @@ import cn.bunny.dao.entity.system.EmailUsers;
|
|||
import cn.bunny.dao.vo.result.PageResult;
|
||||
import cn.bunny.dao.vo.result.ResultCodeEnum;
|
||||
import cn.bunny.dao.vo.system.email.EmailUsersVo;
|
||||
import cn.bunny.services.factory.EmailFactory;
|
||||
import cn.bunny.services.mapper.EmailUsersMapper;
|
||||
import cn.bunny.services.service.EmailUsersService;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import jakarta.validation.Valid;
|
||||
|
@ -38,7 +38,7 @@ import java.util.Map;
|
|||
public class EmailUsersServiceImpl extends ServiceImpl<EmailUsersMapper, EmailUsers> implements EmailUsersService {
|
||||
|
||||
@Autowired
|
||||
private EmailUsersMapper emailUsersMapper;
|
||||
private EmailFactory emailFactory;
|
||||
|
||||
/**
|
||||
* * 邮箱用户发送配置 服务实现类
|
||||
|
@ -67,7 +67,7 @@ public class EmailUsersServiceImpl extends ServiceImpl<EmailUsersMapper, EmailUs
|
|||
@Override
|
||||
public void addEmailUsers(EmailUsersAddDto dto) {
|
||||
// 更新邮箱默认状态
|
||||
updateEmailUserDefault(dto.getIsDefault());
|
||||
emailFactory.updateEmailUserDefault(dto.getIsDefault());
|
||||
|
||||
// 保存数据
|
||||
EmailUsers emailUsers = new EmailUsers();
|
||||
|
@ -84,7 +84,7 @@ public class EmailUsersServiceImpl extends ServiceImpl<EmailUsersMapper, EmailUs
|
|||
@Override
|
||||
public void updateEmailUsers(@Valid EmailUsersUpdateDto dto) {
|
||||
// 更新邮箱默认状态
|
||||
updateEmailUserDefault(dto.getIsDefault());
|
||||
emailFactory.updateEmailUserDefault(dto.getIsDefault());
|
||||
|
||||
// 更新内容
|
||||
EmailUsers emailUsers = new EmailUsers();
|
||||
|
@ -113,7 +113,7 @@ public class EmailUsersServiceImpl extends ServiceImpl<EmailUsersMapper, EmailUs
|
|||
@Override
|
||||
public void updateEmailUserStatus(EmailUserUpdateStatusDto dto) {
|
||||
// 更新邮箱默认状态
|
||||
updateEmailUserDefault(dto.getIsDefault());
|
||||
emailFactory.updateEmailUserDefault(dto.getIsDefault());
|
||||
|
||||
EmailUsers emailUsers = new EmailUsers();
|
||||
BeanUtils.copyProperties(dto, emailUsers);
|
||||
|
@ -134,18 +134,4 @@ public class EmailUsersServiceImpl extends ServiceImpl<EmailUsersMapper, EmailUs
|
|||
return map;
|
||||
}).toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断邮箱是否添加
|
||||
*
|
||||
* @param isDefault 邮箱是否为默认
|
||||
*/
|
||||
public void updateEmailUserDefault(Boolean isDefault) {
|
||||
EmailUsers emailUsers = new EmailUsers();
|
||||
// 判断状态,如果是默认将所有的内容都设为false
|
||||
if (isDefault) {
|
||||
emailUsers.setIsDefault(false);
|
||||
emailUsersMapper.update(emailUsers, Wrappers.<EmailUsers>lambdaUpdate().eq(EmailUsers::getIsDefault, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,9 +11,9 @@ import cn.bunny.dao.vo.result.PageResult;
|
|||
import cn.bunny.dao.vo.result.ResultCodeEnum;
|
||||
import cn.bunny.dao.vo.system.message.MessageReceivedWithMessageVo;
|
||||
import cn.bunny.dao.vo.system.message.MessageUserVo;
|
||||
import cn.bunny.services.factory.UserFactory;
|
||||
import cn.bunny.services.mapper.MessageReceivedMapper;
|
||||
import cn.bunny.services.service.MessageReceivedService;
|
||||
import cn.bunny.services.utils.UserUtil;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
|
@ -39,7 +39,7 @@ import java.util.List;
|
|||
public class MessageReceivedServiceImpl extends ServiceImpl<MessageReceivedMapper, MessageReceived> implements MessageReceivedService {
|
||||
|
||||
@Autowired
|
||||
private UserUtil userUtil;
|
||||
private UserFactory userFactory;
|
||||
|
||||
/**
|
||||
* 管理员管理用户消息接收分页查询
|
||||
|
@ -58,7 +58,7 @@ public class MessageReceivedServiceImpl extends ServiceImpl<MessageReceivedMappe
|
|||
|
||||
// 设置封面返回内容
|
||||
String cover = vo.getCover();
|
||||
cover = userUtil.checkGetUserAvatar(cover);
|
||||
cover = userFactory.checkGetUserAvatar(cover);
|
||||
vo.setCover(cover);
|
||||
return vo;
|
||||
}).toList();
|
||||
|
@ -113,7 +113,7 @@ public class MessageReceivedServiceImpl extends ServiceImpl<MessageReceivedMappe
|
|||
|
||||
// 设置封面返回内容
|
||||
String cover = vo.getCover();
|
||||
cover = userUtil.checkGetUserAvatar(cover);
|
||||
cover = userFactory.checkGetUserAvatar(cover);
|
||||
vo.setCover(cover);
|
||||
return vo;
|
||||
}).toList();
|
||||
|
|
|
@ -14,12 +14,12 @@ import cn.bunny.dao.vo.system.message.MessageDetailVo;
|
|||
import cn.bunny.dao.vo.system.message.MessageReceivedWithMessageVo;
|
||||
import cn.bunny.dao.vo.system.message.MessageReceivedWithUserVo;
|
||||
import cn.bunny.dao.vo.system.message.MessageVo;
|
||||
import cn.bunny.services.factory.UserFactory;
|
||||
import cn.bunny.services.mapper.MessageMapper;
|
||||
import cn.bunny.services.mapper.MessageReceivedMapper;
|
||||
import cn.bunny.services.mapper.UserMapper;
|
||||
import cn.bunny.services.service.MessageReceivedService;
|
||||
import cn.bunny.services.service.MessageService;
|
||||
import cn.bunny.services.utils.UserUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
|
@ -48,7 +48,7 @@ import java.util.stream.Collectors;
|
|||
public class MessageServiceImpl extends ServiceImpl<MessageMapper, Message> implements MessageService {
|
||||
|
||||
@Autowired
|
||||
private UserUtil userUtil;
|
||||
private UserFactory userFactory;
|
||||
|
||||
@Autowired
|
||||
private MessageReceivedMapper messageReceivedMapper;
|
||||
|
@ -152,7 +152,7 @@ public class MessageServiceImpl extends ServiceImpl<MessageMapper, Message> impl
|
|||
|
||||
// 设置封面返回内容
|
||||
String cover = dto.getCover();
|
||||
dto.setCover(userUtil.checkGetUserAvatar(cover));
|
||||
dto.setCover(userFactory.checkGetUserAvatar(cover));
|
||||
|
||||
// 先保存消息数据,之后拿到保存消息的id
|
||||
Message message = new Message();
|
||||
|
@ -198,7 +198,7 @@ public class MessageServiceImpl extends ServiceImpl<MessageMapper, Message> impl
|
|||
|
||||
// 设置封面返回内容
|
||||
String cover = dto.getCover();
|
||||
dto.setCover(userUtil.checkGetUserAvatar(cover));
|
||||
dto.setCover(userFactory.checkGetUserAvatar(cover));
|
||||
|
||||
// 更新内容
|
||||
Message message = new Message();
|
||||
|
|
|
@ -4,11 +4,11 @@ import cn.bunny.dao.dto.system.rolePower.AssignPowersToRoleDto;
|
|||
import cn.bunny.dao.entity.system.AdminUser;
|
||||
import cn.bunny.dao.entity.system.RolePower;
|
||||
import cn.bunny.dao.entity.system.UserRole;
|
||||
import cn.bunny.services.factory.RoleFactory;
|
||||
import cn.bunny.services.mapper.RolePowerMapper;
|
||||
import cn.bunny.services.mapper.UserMapper;
|
||||
import cn.bunny.services.mapper.UserRoleMapper;
|
||||
import cn.bunny.services.service.RolePowerService;
|
||||
import cn.bunny.services.utils.RoleUtil;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -33,7 +33,7 @@ public class RolePowerServiceImpl extends ServiceImpl<RolePowerMapper, RolePower
|
|||
private UserMapper userMapper;
|
||||
|
||||
@Autowired
|
||||
private RoleUtil roleUtil;
|
||||
private RoleFactory roleFactory;
|
||||
|
||||
@Autowired
|
||||
private UserRoleMapper userRoleMapper;
|
||||
|
@ -84,6 +84,6 @@ public class RolePowerServiceImpl extends ServiceImpl<RolePowerMapper, RolePower
|
|||
|
||||
// 更新Redis中用户信息
|
||||
List<Long> userIds = adminUsers.stream().map(AdminUser::getId).toList();
|
||||
roleUtil.updateUserRedisInfo(userIds);
|
||||
roleFactory.updateUserRedisInfo(userIds);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,12 +9,12 @@ import cn.bunny.dao.entity.system.UserRole;
|
|||
import cn.bunny.dao.vo.result.PageResult;
|
||||
import cn.bunny.dao.vo.result.ResultCodeEnum;
|
||||
import cn.bunny.dao.vo.system.rolePower.RoleVo;
|
||||
import cn.bunny.services.factory.RoleFactory;
|
||||
import cn.bunny.services.mapper.RoleMapper;
|
||||
import cn.bunny.services.mapper.RolePowerMapper;
|
||||
import cn.bunny.services.mapper.RouterRoleMapper;
|
||||
import cn.bunny.services.mapper.UserRoleMapper;
|
||||
import cn.bunny.services.service.RoleService;
|
||||
import cn.bunny.services.utils.RoleUtil;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
|
@ -49,7 +49,7 @@ public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements Ro
|
|||
private RouterRoleMapper routerRoleMapper;
|
||||
|
||||
@Autowired
|
||||
private RoleUtil roleUtil;
|
||||
private RoleFactory roleFactory;
|
||||
|
||||
/**
|
||||
* * 角色 服务实现类
|
||||
|
@ -118,7 +118,7 @@ public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements Ro
|
|||
// 找到所有和当前更新角色相同的用户,并更新Redis中用户信息
|
||||
List<Long> userIds = userRoleMapper.selectList(Wrappers.<UserRole>lambdaQuery().eq(UserRole::getRoleId, dto.getId()))
|
||||
.stream().map(UserRole::getUserId).toList();
|
||||
roleUtil.updateUserRedisInfo(userIds);
|
||||
roleFactory.updateUserRedisInfo(userIds);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -15,13 +15,13 @@ import cn.bunny.dao.vo.result.ResultCodeEnum;
|
|||
import cn.bunny.dao.vo.system.router.RouterManageVo;
|
||||
import cn.bunny.dao.vo.system.router.RouterMeta;
|
||||
import cn.bunny.dao.vo.system.router.UserRouterVo;
|
||||
import cn.bunny.services.factory.RouterServiceFactory;
|
||||
import cn.bunny.services.mapper.RoleMapper;
|
||||
import cn.bunny.services.mapper.RolePowerMapper;
|
||||
import cn.bunny.services.mapper.RouterMapper;
|
||||
import cn.bunny.services.mapper.RouterRoleMapper;
|
||||
import cn.bunny.services.security.custom.CustomCheckIsAdmin;
|
||||
import cn.bunny.services.service.RouterService;
|
||||
import cn.bunny.services.utils.RoleUtil;
|
||||
import cn.bunny.services.utils.RouterServiceUtil;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
|
@ -46,7 +46,7 @@ import java.util.stream.Collectors;
|
|||
@Transactional
|
||||
public class RouterServiceImpl extends ServiceImpl<RouterMapper, Router> implements RouterService {
|
||||
@Autowired
|
||||
private RouterServiceUtil routerServiceUtil;
|
||||
private RouterServiceFactory routerServiceFactory;
|
||||
|
||||
@Autowired
|
||||
private RoleMapper roleMapper;
|
||||
|
@ -84,7 +84,7 @@ public class RouterServiceImpl extends ServiceImpl<RouterMapper, Router> impleme
|
|||
List<UserRouterVo> list = new ArrayList<>();
|
||||
|
||||
// 查询用户角色,判断是否是管理员角色
|
||||
boolean isAdmin = RoleUtil.checkAdmin(userRoleCodeList);
|
||||
boolean isAdmin = CustomCheckIsAdmin.checkAdmin(userRoleCodeList);
|
||||
|
||||
// 查询路由和角色对应关系
|
||||
List<ViewRouterRole> routerRoleList = routerRoleMapper.viewRouterRolesWithAll();
|
||||
|
@ -151,7 +151,7 @@ public class RouterServiceImpl extends ServiceImpl<RouterMapper, Router> impleme
|
|||
// 构建树形结构
|
||||
routerVoList.forEach(routerVo -> {
|
||||
if (routerVo.getParentId() == 0) {
|
||||
routerVo.setChildren(routerServiceUtil.handleGetChildrenWIthRouter(routerVo.getId(), routerVoList));
|
||||
routerVo.setChildren(routerServiceFactory.handleGetChildrenWIthRouter(routerVo.getId(), routerVoList));
|
||||
list.add(routerVo);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -8,10 +8,10 @@ import cn.bunny.dao.entity.system.AdminUser;
|
|||
import cn.bunny.dao.entity.system.UserRole;
|
||||
import cn.bunny.dao.vo.result.ResultCodeEnum;
|
||||
import cn.bunny.dao.vo.system.user.LoginVo;
|
||||
import cn.bunny.services.factory.UserFactory;
|
||||
import cn.bunny.services.mapper.UserMapper;
|
||||
import cn.bunny.services.mapper.UserRoleMapper;
|
||||
import cn.bunny.services.service.UserRoleService;
|
||||
import cn.bunny.services.utils.UserUtil;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -38,7 +38,7 @@ public class UserRoleServiceImpl extends ServiceImpl<UserRoleMapper, UserRole> i
|
|||
private UserRoleMapper userRoleMapper;
|
||||
|
||||
@Autowired
|
||||
private UserUtil userUtil;
|
||||
private UserFactory userFactory;
|
||||
|
||||
@Autowired
|
||||
private UserMapper userMapper;
|
||||
|
@ -94,7 +94,7 @@ public class UserRoleServiceImpl extends ServiceImpl<UserRoleMapper, UserRole> i
|
|||
|
||||
// 重新设置Redis中的用户存储信息vo对象
|
||||
String username = adminUser.getUsername();
|
||||
loginVo = userUtil.buildLoginUserVo(adminUser, readMeDay);
|
||||
loginVo = userFactory.buildLoginUserVo(adminUser, readMeDay);
|
||||
redisTemplate.opsForValue().set(RedisUserConstant.getAdminLoginInfoPrefix(username), loginVo, readMeDay, TimeUnit.DAYS);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,24 +10,20 @@ import cn.bunny.dao.dto.system.files.FileUploadDto;
|
|||
import cn.bunny.dao.dto.system.user.*;
|
||||
import cn.bunny.dao.entity.log.UserLoginLog;
|
||||
import cn.bunny.dao.entity.system.AdminUser;
|
||||
import cn.bunny.dao.entity.system.EmailTemplate;
|
||||
import cn.bunny.dao.entity.system.Role;
|
||||
import cn.bunny.dao.entity.system.UserDept;
|
||||
import cn.bunny.dao.enums.EmailTemplateEnums;
|
||||
import cn.bunny.dao.enums.LoginEnums;
|
||||
import cn.bunny.dao.views.ViewUserDept;
|
||||
import cn.bunny.dao.vo.result.PageResult;
|
||||
import cn.bunny.dao.vo.result.ResultCodeEnum;
|
||||
import cn.bunny.dao.vo.system.files.FileInfoVo;
|
||||
import cn.bunny.dao.vo.system.user.*;
|
||||
import cn.bunny.services.factory.EmailFactory;
|
||||
import cn.bunny.services.factory.UserFactory;
|
||||
import cn.bunny.services.mapper.*;
|
||||
import cn.bunny.services.service.FilesService;
|
||||
import cn.bunny.services.service.UserService;
|
||||
import cn.bunny.services.utils.UserUtil;
|
||||
import cn.bunny.services.utils.email.ConcreteSenderEmailTemplate;
|
||||
import cn.bunny.services.utils.login.DefaultLoginStrategy;
|
||||
import cn.bunny.services.utils.login.EmailLoginStrategy;
|
||||
import cn.bunny.services.utils.login.LoginContext;
|
||||
import cn.bunny.services.utils.login.LoginStrategy;
|
||||
import cn.hutool.captcha.CaptchaUtil;
|
||||
import cn.hutool.captcha.CircleCaptcha;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
|
@ -35,17 +31,15 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
|
|||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.SneakyThrows;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.DigestUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
|
@ -65,58 +59,31 @@ import java.util.concurrent.TimeUnit;
|
|||
public class UserServiceImpl extends ServiceImpl<UserMapper, AdminUser> implements UserService {
|
||||
|
||||
@Autowired
|
||||
private UserUtil userUtil;
|
||||
private UserFactory userFactory;
|
||||
|
||||
@Autowired
|
||||
private ConcreteSenderEmailTemplate concreteSenderEmailTemplate;
|
||||
private EmailFactory emailFactory;
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@Autowired
|
||||
private FilesService filesService;
|
||||
|
||||
@Autowired
|
||||
private UserDeptMapper userDeptMapper;
|
||||
|
||||
@Autowired
|
||||
private UserRoleMapper userRoleMapper;
|
||||
|
||||
@Autowired
|
||||
private UserLoginLogMapper userLoginLogMapper;
|
||||
|
||||
@Autowired
|
||||
private EmailTemplateMapper emailTemplateMapper;
|
||||
|
||||
@Autowired
|
||||
private RoleMapper roleMapper;
|
||||
@Autowired
|
||||
private UserMapper userMapper;
|
||||
@Autowired
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
/**
|
||||
* 前台用户登录接口
|
||||
* 这里不用判断用户是否为空,因为在登录时已经校验过了
|
||||
* <p>
|
||||
* 抛出异常使用自带的 UsernameNotFoundException 或者自己封装<br/>
|
||||
* 但是这两个效果传入参数都是一样的,所以全部使用 UsernameNotFoundException
|
||||
* </p>
|
||||
*
|
||||
* @param loginDto 登录参数
|
||||
* @return 登录后结果返回
|
||||
*/
|
||||
@Override
|
||||
public LoginVo login(LoginDto loginDto, HttpServletResponse response) {
|
||||
Long readMeDay = loginDto.getReadMeDay();
|
||||
|
||||
// 初始化登录策略,如果有需要添加策略放在这里
|
||||
HashMap<String, LoginStrategy> loginStrategyHashMap = new HashMap<>();
|
||||
loginStrategyHashMap.put(LoginEnums.EMAIL_STRATEGY.getValue(), new EmailLoginStrategy(redisTemplate, userMapper));
|
||||
loginStrategyHashMap.put(LoginEnums.default_STRATEGY.getValue(), new DefaultLoginStrategy(userMapper));
|
||||
|
||||
// 使用登录上下文调用登录策略
|
||||
LoginContext loginContext = new LoginContext(loginStrategyHashMap);
|
||||
AdminUser user = loginContext.executeStrategy(loginDto);
|
||||
|
||||
// 判断用户是否禁用
|
||||
if (user.getStatus()) {
|
||||
throw new UsernameNotFoundException(ResultCodeEnum.FAIL_NO_ACCESS_DENIED_USER_LOCKED.getMessage());
|
||||
}
|
||||
return userUtil.buildLoginUserVo(user, readMeDay);
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录发送邮件验证码
|
||||
|
@ -126,10 +93,10 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, AdminUser> implemen
|
|||
@Override
|
||||
public void sendLoginEmail(@NotNull String email) {
|
||||
// 查询验证码邮件模板
|
||||
LambdaQueryWrapper<cn.bunny.dao.entity.system.EmailTemplate> lambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
lambdaQueryWrapper.eq(cn.bunny.dao.entity.system.EmailTemplate::getIsDefault, true);
|
||||
lambdaQueryWrapper.eq(cn.bunny.dao.entity.system.EmailTemplate::getType, EmailTemplateEnums.VERIFICATION_CODE.getType());
|
||||
cn.bunny.dao.entity.system.EmailTemplate emailTemplate = emailTemplateMapper.selectOne(lambdaQueryWrapper);
|
||||
LambdaQueryWrapper<EmailTemplate> lambdaQueryWrapper = new LambdaQueryWrapper<>();
|
||||
lambdaQueryWrapper.eq(EmailTemplate::getIsDefault, true);
|
||||
lambdaQueryWrapper.eq(EmailTemplate::getType, EmailTemplateEnums.VERIFICATION_CODE.getType());
|
||||
EmailTemplate emailTemplate = emailTemplateMapper.selectOne(lambdaQueryWrapper);
|
||||
|
||||
// 生成验证码
|
||||
CircleCaptcha captcha = CaptchaUtil.createCircleCaptcha(150, 48, 4, 2);
|
||||
|
@ -144,7 +111,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, AdminUser> implemen
|
|||
hashMap.put("#companyName#", "BunnyAdmin");
|
||||
|
||||
// 发送邮件
|
||||
concreteSenderEmailTemplate.sendEmail(email, emailTemplate, hashMap);
|
||||
emailFactory.sendEmailTemplate(email, emailTemplate, hashMap);
|
||||
|
||||
// 在Redis中存储验证码
|
||||
redisTemplate.opsForValue().set(RedisUserConstant.getAdminUserEmailCodePrefix(email), emailCode, RedisUserConstant.REDIS_EXPIRATION_TIME, TimeUnit.MINUTES);
|
||||
|
@ -165,7 +132,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, AdminUser> implemen
|
|||
if (adminUser == null) throw new AuthCustomerException(ResultCodeEnum.USER_IS_EMPTY);
|
||||
if (adminUser.getStatus()) throw new AuthCustomerException(ResultCodeEnum.FAIL_NO_ACCESS_DENIED_USER_LOCKED);
|
||||
|
||||
LoginVo buildUserVo = userUtil.buildLoginUserVo(adminUser, dto.getReadMeDay());
|
||||
LoginVo buildUserVo = userFactory.buildLoginUserVo(adminUser, dto.getReadMeDay());
|
||||
RefreshTokenVo refreshTokenVo = new RefreshTokenVo();
|
||||
BeanUtils.copyProperties(buildUserVo, refreshTokenVo);
|
||||
|
||||
|
@ -188,7 +155,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, AdminUser> implemen
|
|||
|
||||
// 查询用户信息
|
||||
AdminUser adminUser = getOne(Wrappers.<AdminUser>lambdaQuery().eq(AdminUser::getId, userId));
|
||||
UserLoginLog userLoginLog = userUtil.setUserLoginLog(adminUser, token, ipAddr, ipRegion, "logout");
|
||||
UserLoginLog userLoginLog = userFactory.setUserLoginLog(adminUser, token, ipAddr, ipRegion, "logout");
|
||||
userLoginLogMapper.insert(userLoginLog);
|
||||
|
||||
// 删除Redis中用户信息
|
||||
|
@ -215,7 +182,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, AdminUser> implemen
|
|||
UserVo userVo = new UserVo();
|
||||
BeanUtils.copyProperties(user, userVo);
|
||||
|
||||
userVo.setAvatar(userUtil.checkGetUserAvatar(avatar));
|
||||
userVo.setAvatar(userFactory.checkGetUserAvatar(avatar));
|
||||
return userVo;
|
||||
}
|
||||
|
||||
|
@ -230,19 +197,19 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, AdminUser> implemen
|
|||
String password = dto.getPassword();
|
||||
|
||||
// 对密码加密
|
||||
String encode = passwordEncoder.encode(password);
|
||||
String md5Password = DigestUtils.md5DigestAsHex(password.getBytes());
|
||||
AdminUser adminUser = getOne(Wrappers.<AdminUser>lambdaQuery().eq(AdminUser::getId, userId));
|
||||
|
||||
// 判断是否存在这个用户
|
||||
if (adminUser == null) throw new AuthCustomerException(ResultCodeEnum.USER_IS_EMPTY);
|
||||
|
||||
// 判断新密码是否与旧密码相同
|
||||
if (adminUser.getPassword().equals(encode))
|
||||
if (adminUser.getPassword().equals(md5Password))
|
||||
throw new AuthCustomerException(ResultCodeEnum.UPDATE_NEW_PASSWORD_SAME_AS_OLD_PASSWORD);
|
||||
|
||||
// 更新用户密码
|
||||
adminUser = new AdminUser();
|
||||
adminUser.setPassword(encode);
|
||||
adminUser.setPassword(md5Password);
|
||||
adminUser.setId(userId);
|
||||
updateById(adminUser);
|
||||
|
||||
|
@ -277,7 +244,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, AdminUser> implemen
|
|||
|
||||
// 重新生成用户信息到Redis中
|
||||
user.setAvatar(adminUser.getAvatar());
|
||||
userUtil.buildUserVo(user, RedisUserConstant.REDIS_EXPIRATION_TIME);
|
||||
userFactory.buildUserVo(user, RedisUserConstant.REDIS_EXPIRATION_TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -376,7 +343,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, AdminUser> implemen
|
|||
if (user == null) throw new AuthCustomerException(ResultCodeEnum.USER_IS_EMPTY);
|
||||
|
||||
// 检查用户头像
|
||||
dto.setAvatar(userUtil.checkPostUserAvatar(dto.getAvatar()));
|
||||
dto.setAvatar(userFactory.checkPostUserAvatar(dto.getAvatar()));
|
||||
|
||||
// 更新用户
|
||||
AdminUser adminUser = new AdminUser();
|
||||
|
@ -386,7 +353,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, AdminUser> implemen
|
|||
|
||||
// 重新生成用户信息到Redis中
|
||||
BeanUtils.copyProperties(dto, user);
|
||||
userUtil.buildUserVo(user, RedisUserConstant.REDIS_EXPIRATION_TIME);
|
||||
userFactory.buildUserVo(user, RedisUserConstant.REDIS_EXPIRATION_TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -405,7 +372,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, AdminUser> implemen
|
|||
|
||||
// 数据库中的密码
|
||||
String dbPassword = adminUser.getPassword();
|
||||
password = passwordEncoder.encode(password);
|
||||
password = DigestUtils.md5DigestAsHex(password.getBytes());
|
||||
|
||||
// 判断数据库中密码是否和更新用户密码相同
|
||||
if (dbPassword.equals(password)) throw new AuthCustomerException(ResultCodeEnum.NEW_PASSWORD_SAME_OLD_PASSWORD);
|
||||
|
@ -434,7 +401,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, AdminUser> implemen
|
|||
List<AdminUserVo> voList = page.getRecords().stream()
|
||||
.map(adminUser -> {
|
||||
// 如果存在用户头像,则设置用户头像
|
||||
String avatar = userUtil.checkGetUserAvatar(adminUser.getAvatar());
|
||||
String avatar = userFactory.checkGetUserAvatar(adminUser.getAvatar());
|
||||
|
||||
AdminUserVo adminUserVo = new AdminUserVo();
|
||||
BeanUtils.copyProperties(adminUser, adminUserVo);
|
||||
|
@ -462,12 +429,12 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, AdminUser> implemen
|
|||
@Override
|
||||
public void addAdminUser(@Valid AdminUserAddDto dto) {
|
||||
// 对密码加密
|
||||
String encode = passwordEncoder.encode(dto.getPassword());
|
||||
String md5Password = DigestUtils.md5DigestAsHex(dto.getPassword().getBytes());
|
||||
|
||||
// 保存数据
|
||||
AdminUser adminUser = new AdminUser();
|
||||
BeanUtils.copyProperties(dto, adminUser);
|
||||
adminUser.setPassword(encode);
|
||||
adminUser.setPassword(md5Password);
|
||||
save(adminUser);
|
||||
|
||||
// 插入用户部门关系表
|
||||
|
@ -521,7 +488,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, AdminUser> implemen
|
|||
|
||||
// 重新生成用户信息到Redis中
|
||||
BeanUtils.copyProperties(dto, adminUser);
|
||||
userUtil.buildUserVo(adminUser, RedisUserConstant.REDIS_EXPIRATION_TIME);
|
||||
userFactory.buildUserVo(adminUser, RedisUserConstant.REDIS_EXPIRATION_TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,84 +0,0 @@
|
|||
package cn.bunny.services.utils;
|
||||
|
||||
import cn.bunny.common.service.context.BaseContext;
|
||||
import cn.bunny.dao.constant.RedisUserConstant;
|
||||
import cn.bunny.dao.entity.system.AdminUser;
|
||||
import cn.bunny.services.mapper.UserMapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class RoleUtil {
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
@Autowired
|
||||
private UserMapper userMapper;
|
||||
|
||||
@Autowired
|
||||
private UserUtil userUtil;
|
||||
|
||||
/**
|
||||
* 判断是否是管理员
|
||||
*
|
||||
* @param roleList 角色代码列表
|
||||
* @param permissions 权限列表
|
||||
* @param adminUser 用户信息
|
||||
* @return 是否是管理员
|
||||
*/
|
||||
public static boolean checkAdmin(List<String> roleList, List<String> permissions, AdminUser adminUser) {
|
||||
// 判断是否是超级管理员
|
||||
boolean isIdAdmin = adminUser.getId().equals(1L);
|
||||
boolean isAdmin = roleList.stream().anyMatch(role -> role.equals("admin"));
|
||||
|
||||
// 判断是否是 admin
|
||||
if (isIdAdmin || isAdmin) {
|
||||
roleList.add("admin");
|
||||
permissions.add("*");
|
||||
permissions.add("*::*");
|
||||
permissions.add("*::*::*");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否是管理员
|
||||
*
|
||||
* @param roleList 角色代码列表
|
||||
* @return 是否是管理员
|
||||
*/
|
||||
public static boolean checkAdmin(List<String> roleList) {
|
||||
// 判断是否是超级管理员
|
||||
if (BaseContext.getUserId().equals(1L)) return true;
|
||||
|
||||
// 判断是否是 admin
|
||||
return roleList.stream().anyMatch(role -> role.equals("admin"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量更新Redis中用户信息
|
||||
*
|
||||
* @param userIds 用户Id列表
|
||||
*/
|
||||
public void updateUserRedisInfo(List<Long> userIds) {
|
||||
// 根据Id查找所有用户
|
||||
List<AdminUser> adminUsers = userMapper.selectList(Wrappers.<AdminUser>lambdaQuery().in(AdminUser::getId, userIds));
|
||||
|
||||
// 用户为空时不更新Redis的key
|
||||
if (adminUsers.isEmpty()) return;
|
||||
|
||||
// 更新Redis中用户信息
|
||||
adminUsers.stream().filter(user -> {
|
||||
String adminLoginInfoPrefix = RedisUserConstant.getAdminLoginInfoPrefix(user.getUsername());
|
||||
Object object = redisTemplate.opsForValue().get(adminLoginInfoPrefix);
|
||||
return object != null;
|
||||
}).forEach(user -> userUtil.buildUserVo(user, RedisUserConstant.REDIS_EXPIRATION_TIME));
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
package cn.bunny.services.utils.email;
|
||||
|
||||
import cn.bunny.dao.entity.system.EmailTemplate;
|
||||
import cn.bunny.services.mapper.EmailTemplateMapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
@Component
|
||||
public class ConcreteSenderEmailTemplate extends AbstractSenderEmailTemplate {
|
||||
@Autowired
|
||||
private EmailTemplateMapper emailTemplateMapper;
|
||||
|
||||
/**
|
||||
* 发送邮件模板
|
||||
* 根据邮件模板发送邮件
|
||||
*
|
||||
* @param email 邮件
|
||||
* @param emailTemplateId 模板Id
|
||||
* @param params 替换参数
|
||||
*/
|
||||
public void sendEmailTemplate(String email, Long emailTemplateId, HashMap<String, Object> params) {
|
||||
EmailTemplate emailTemplate = emailTemplateMapper.selectOne(Wrappers.<EmailTemplate>lambdaQuery().eq(EmailTemplate::getId, emailTemplateId));
|
||||
sendEmail(email, emailTemplate, params);
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
package cn.bunny.services.utils.login;
|
||||
|
||||
import cn.bunny.dao.dto.system.user.LoginDto;
|
||||
import cn.bunny.dao.entity.system.AdminUser;
|
||||
import cn.bunny.services.mapper.UserMapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
|
||||
/**
|
||||
* 使用用户名登录
|
||||
*/
|
||||
public class DefaultLoginStrategy implements LoginStrategy {
|
||||
private final UserMapper userMapper;
|
||||
|
||||
public DefaultLoginStrategy(UserMapper userMapper) {
|
||||
this.userMapper = userMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录鉴定方法
|
||||
* 默认登录方式,使用用户名查询用户
|
||||
*
|
||||
* @param loginDto 登录参数
|
||||
* @return 鉴定身份验证
|
||||
*/
|
||||
@Override
|
||||
public AdminUser authenticate(LoginDto loginDto) {
|
||||
String username = loginDto.getUsername();
|
||||
|
||||
// 查询用户相关内容
|
||||
LambdaQueryWrapper<AdminUser> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(AdminUser::getUsername, username);
|
||||
return userMapper.selectOne(queryWrapper);
|
||||
}
|
||||
}
|
|
@ -1,56 +0,0 @@
|
|||
package cn.bunny.services.utils.login;
|
||||
|
||||
import cn.bunny.dao.constant.RedisUserConstant;
|
||||
import cn.bunny.dao.dto.system.user.LoginDto;
|
||||
import cn.bunny.dao.entity.system.AdminUser;
|
||||
import cn.bunny.dao.vo.result.ResultCodeEnum;
|
||||
import cn.bunny.services.mapper.UserMapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
|
||||
/**
|
||||
* 邮箱登录策略
|
||||
*/
|
||||
public class EmailLoginStrategy implements LoginStrategy {
|
||||
private final RedisTemplate<String, Object> redisTemplate;
|
||||
private final UserMapper userMapper;
|
||||
|
||||
public EmailLoginStrategy(RedisTemplate<String, Object> redisTemplate, UserMapper userMapper) {
|
||||
this.redisTemplate = redisTemplate;
|
||||
this.userMapper = userMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录鉴定方法
|
||||
* 只要判断邮箱验证码是否相等,在前面已经验证过用户密码
|
||||
* <p>
|
||||
* 抛出异常类型 UsernameNotFoundException 如果要自定义状态码需要使用 HttpServletResponse
|
||||
* 有封装好的 ResponseUtil.out() 方法
|
||||
* </p>
|
||||
*
|
||||
* @param loginDto 登录参数
|
||||
* @return 鉴定身份验证
|
||||
*/
|
||||
@Override
|
||||
public AdminUser authenticate(LoginDto loginDto) {
|
||||
String username = loginDto.getUsername();
|
||||
String emailCode = loginDto.getEmailCode().toLowerCase();
|
||||
|
||||
// 查找Redis中的验证码
|
||||
Object redisEmailCode = redisTemplate.opsForValue().get(RedisUserConstant.getAdminUserEmailCodePrefix(username));
|
||||
if (redisEmailCode == null) {
|
||||
throw new UsernameNotFoundException(ResultCodeEnum.EMAIL_CODE_EMPTY.getMessage());
|
||||
}
|
||||
|
||||
// 判断用户邮箱验证码是否和Redis中发送的验证码
|
||||
if (!emailCode.equals(redisEmailCode.toString().toLowerCase())) {
|
||||
throw new UsernameNotFoundException(ResultCodeEnum.EMAIL_CODE_NOT_MATCHING.getMessage());
|
||||
}
|
||||
|
||||
// 查询用户相关内容
|
||||
LambdaQueryWrapper<AdminUser> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(AdminUser::getEmail, username);
|
||||
return userMapper.selectOne(queryWrapper);
|
||||
}
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
package cn.bunny.services.utils.login;
|
||||
|
||||
import cn.bunny.dao.dto.system.user.LoginDto;
|
||||
import cn.bunny.dao.entity.system.AdminUser;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 登录策略上下文
|
||||
*/
|
||||
public class LoginContext {
|
||||
private final Map<String, LoginStrategy> strategies;
|
||||
|
||||
public LoginContext(Map<String, LoginStrategy> strategies) {
|
||||
this.strategies = strategies;
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行登录策略
|
||||
* 根据情况判断 type 是否为空
|
||||
*
|
||||
* @param loginDto 登录参数
|
||||
* @return 用户
|
||||
*/
|
||||
public AdminUser executeStrategy(LoginDto loginDto) {
|
||||
String type = loginDto.getType();
|
||||
LoginStrategy strategy = strategies.get(type);
|
||||
if (strategy == null) {
|
||||
throw new UsernameNotFoundException("不支持登录类型: " + type);
|
||||
}
|
||||
return strategy.authenticate(loginDto);
|
||||
}
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
package cn.bunny.services.utils.login;
|
||||
|
||||
import cn.bunny.dao.dto.system.user.LoginDto;
|
||||
import cn.bunny.dao.entity.system.AdminUser;
|
||||
|
||||
/**
|
||||
* 登录策略
|
||||
*/
|
||||
public interface LoginStrategy {
|
||||
|
||||
/**
|
||||
* 登录鉴定方法
|
||||
*
|
||||
* @param loginDto 登录参数
|
||||
* @return 鉴定身份验证
|
||||
*/
|
||||
AdminUser authenticate(LoginDto loginDto);
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
|
||||
_ _
|
||||
| |__ _ _ _ __ _ __ _ _ (_) __ ___ ____ _
|
||||
| '_ \| | | | '_ \| '_ \| | | | | |/ _` \ \ / / _` |
|
||||
| |_) | |_| | | | | | | | |_| | | | (_| |\ V | (_| |
|
||||
|_.__/ \__,_|_| |_|_| |_|\__, | _/ |\__,_| \_/ \__,_|
|
||||
|___/ |__/
|
||||
|
||||
${spring-boot.formatted-version}
|
||||
${application.title}
|
||||
${AnsiColor.BRIGHT_GREEN}
|
||||
SpringBoot Version: ${spring-boot.version}${spring-boot.formatted-version}
|
||||
${AnsiColor.BLACK}
|
|
@ -1,19 +0,0 @@
|
|||
package cn.bunny.services.service.impl;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
|
||||
@SpringBootTest
|
||||
class UserServiceImplTest {
|
||||
|
||||
@Autowired
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
@Test
|
||||
void updateUserPasswordByAdmin() {
|
||||
String encode = passwordEncoder.encode("123456");
|
||||
System.out.println(encode);
|
||||
}
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
package cn.bunny.services.utils.email;
|
||||
|
||||
import cn.bunny.dao.entity.system.EmailTemplate;
|
||||
import cn.bunny.services.mapper.EmailTemplateMapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
@SpringBootTest
|
||||
class ConcreteSenderEmailTemplateTest extends AbstractSenderEmailTemplate {
|
||||
@Autowired
|
||||
private EmailTemplateMapper emailTemplateMapper;
|
||||
|
||||
@Test
|
||||
void sendEmailTemplate() {
|
||||
EmailTemplate emailTemplate = emailTemplateMapper.selectOne(Wrappers.<EmailTemplate>lambdaQuery().eq(EmailTemplate::getId, 1791870020197625858L));
|
||||
sendEmail("1319900154@qq.com", emailTemplate, new HashMap<>());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue