first commit

main
魏灿斌 11 months ago
commit 9742357d76

38
.gitignore vendored

@ -0,0 +1,38 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

8
.idea/.gitignore vendored

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ApifoxUploaderProjectSetting">
<option name="apiAccessToken" value="APS-WmPJEk9EldpYTflSKV1yfYY1uOqCHsp7" />
</component>
</project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AgentMigrationStateService">
<option name="migrationStatus" value="COMPLETED" />
</component>
</project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AskMigrationStateService">
<option name="migrationStatus" value="COMPLETED" />
</component>
</project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Ask2AgentMigrationStateService">
<option name="migrationStatus" value="COMPLETED" />
</component>
</project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EditMigrationStateService">
<option name="migrationStatus" value="COMPLETED" />
</component>
</project>

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" native2AsciiForPropertiesFiles="true" defaultCharsetForPropertiesFiles="UTF-8">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/yuxingshi-ssm-common/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/yuxingshi-ssm-common/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/yuxingshi-ssm-common/yuxingshi-ssm-core/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/yuxingshi-ssm-common/yuxingshi-ssm-intercepter/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/yuxingshi-ssm-common/yuxingshi-ssm-intercepter/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/yuxingshi-ssm-common/yuxingshi-ssm-mybatisplus/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/yuxingshi-ssm-common/yuxingshi-ssm-mybatisplus/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/yuxingshi-ssm-common/yuxingshi-ssm-redis/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/yuxingshi-ssm-common/yuxingshi-ssm-redis/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/yuxingshi-ssm-common/yuxingshi-ssm-security/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/yuxingshi-ssm-common/yuxingshi-ssm-security/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/yuxingshi-ssm-server/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/yuxingshi-ssm-server/src/main/resources" charset="UTF-8" />
<file url="PROJECT" charset="UTF-8" />
</component>
</project>

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>yuxingshi</groupId>
<artifactId>yuxingshi-ssm</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>yuxingshi-ssm-server</module>
<module>yuxingshi-ssm-common</module>
</modules>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<!--依赖版本-->
<spring-boot.version>3.3.3</spring-boot.version>
<redisson.version>3.50.0</redisson.version>
<mybatis-plus.version>3.5.7</mybatis-plus.version>
<commons-collections4.version>4.4</commons-collections4.version>
<pagehelper.boot.version>2.0.0</pagehelper.boot.version>
<jwt.version>0.9.1</jwt.version>
<jaxb.version>2.3.0</jaxb.version>
<hutool.version>5.8.22</hutool.version>
<transmittable-thread-local.version>2.14.4</transmittable-thread-local.version>
<idworker-snowflake.version>1.0.0</idworker-snowflake.version>
<!--运行环境-->
<runenv>test</runenv>
<java.opts.default>-Xmx256m</java.opts.default>
</properties>
<dependencyManagement>
<dependencies>
<!-- SpringBoot 依赖配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>${commons-collections4.version}</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
<version>${redisson.version}</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${pagehelper.boot.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jwt.version}</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>${jaxb.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
<version>${transmittable-thread-local.version}</version>
</dependency>
<dependency>
<groupId>com.a3test.component</groupId>
<artifactId>idworker-snowflake</artifactId>
<version>${idworker-snowflake.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>yuxingshi</groupId>
<artifactId>yuxingshi-ssm</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>yuxingshi-ssm-common</artifactId>
<packaging>pom</packaging>
<modules>
<module>yuxingshi-ssm-redis</module>
<module>yuxingshi-ssm-core</module>
<module>yuxingshi-ssm-mybatisplus</module>
<module>yuxingshi-ssm-security</module>
<module>yuxingshi-ssm-intercepter</module>
</modules>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>yuxingshi</groupId>
<artifactId>yuxingshi-ssm-common</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>yuxingshi.ssm.common.core</groupId>
<artifactId>yuxingshi-ssm-core</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-core</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,27 @@
package yuxingshi.ssm.common.core.constants;
/**
* 缓存常量
*/
public class CacheConstants {
/**
* 缓存分割符
*/
public final static String CACHE_SPLIT_COLON = ":";
/**
* 登录用户缓存有效期,默认720(分钟)
*/
public final static long LOGIN_USER_EXPIRATION = 720;
/**
* 缓存刷新时间,默认120(分钟)
*/
public final static long REFRESH_TIME = 120;
/**
* 用户登录凭证有效期延期临界值
*/
public static final long LOGIN_USER_EXP_CRITICAL_TIME = 120L;
}

@ -0,0 +1,23 @@
package yuxingshi.ssm.common.core.constants;
/**
* 通用常量
*/
public class CommonConstants {
/**
* 通用日期格式
*/
public static final String STANDARD_FORMAT = "yyyy-MM-dd HH:mm:ss";
/**
* 默认编码
*/
public final static String UTF8 = "UTF-8";
/**
* 默认分隔符
*/
public final static String DEFAULT_DELIMITER = ", ";
/**
* 空字符串
*/
public final static String EMPTY_STR = "";
}

@ -0,0 +1,180 @@
package yuxingshi.ssm.common.core.constants;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
@Getter
public enum ResultCode {
//---------------------------2xx
/**
* 操作成功
*/
SUCCESS (200000, "操作成功"),
//------------------------4xx
//400
/**
* 无效的参数
*/
INVALID_PARA (400000, "无效的参数"),
/**
* 无效的验证码
*/
INVALID_CODE (400001, "无效的验证码"),
/**
* 错误的验证码
*/
ERROR_CODE (400002, "错误的验证码"),
/**
* 手机号格式错误
*/
ERROR_PHONE_FORMAT (400003, "手机号格式错误"),
/**
* 超过每日发送次数限制
*/
SEND_MSG_OVERLIMIT (400004, "超过每日发送次数限制"),
/**
* 无效的区划
*/
INVALID_REGION (400005, "无效的区划"),
/**
* 参数类型不匹配
*/
PARA_TYPE_MISMATCH (400006, "参数类型不匹配"),
/**
* 账号已停用,登录失败
*/
USER_DISABLE (400007, "账号已停用,登录失败"),
/**
* 请求参数超过最大限制
*/
INVALID_PARA_MAX_SIZE (4000008,"请求参数超过最大限制"),
/**
* 手机号已经被注册
*/
PHONE_ALREADY_REGISTER (4000009,"手机号已经被注册"),
/**
* 用户不存在
*/
USER_NOT_EXIST (4000010,"用户不存在"),
/**
* 解密失败
*/
DECODE_FAIL (4000011,"解密失败"),
/**
* 用户身份不合法
*/
USER_IDENTITY_ILLEGAL (4000012,"用户身份不合法"),
/**
* 用户状态不合法
*/
USER_STATUS_ILLEGAL (4000013,"用户状态不合法"),
/**
* 密码格式不通过
*/
PASSWORD_FORMAT_INVALID (4000015,"密码格式不通过"),
//401
/**
* 令牌不能为空
*/
TOKEN_EMPTY (401000, "令牌不能为空"),
/**
* 令牌已过期或验证不正确!
*/
TOKEN_INVALID (401001, "令牌已过期或验证不正确!"),
/**
* 令牌已过期!
*/
TOKEN_OVERTIME (401002, "令牌已过期!"),
/**
* 登录状态已过期!
*/
LOGIN_STATUS_OVERTIME (401003, "登录状态已过期!"),
/**
* 令牌验证失败!
*/
TOKEN_CHECK_FAILED (401004, "令牌验证失败!"),
// 403
NOT_PERMISSION (403001,"您没有权限!"),
//404
/**
* 服务未找到!
*/
SERVICE_NOT_FOUND (404000, "服务未找到"),
URL_NOT_FOUND (404001, "url未找到"),
//405
/**
* 请求方法不支持!
*/
REQUEST_METNHOD_NOT_SUPPORTED (405000, "请求方法不支持"),
//---------------------5xx
/**
* 服务繁忙请稍后重试!
*/
ERROR (500000, "服务繁忙请稍后重试"),
/**
* 操作失败
*/
FAILED (500001, "操作失败"),
//---------------------枚举占位
/**
* 占位专用
*/
RESERVED (99999999, "占位专用");
/**
* 响应码
*/
private final int code;
/**
* 响应消息
*/
private final String msg;
}

@ -0,0 +1,38 @@
package yuxingshi.ssm.common.core.constants;
/**
* 安全相关的常量类
*/
public class SecurityConstants {
/**
* 用户标识
*/
public static final String USER_KEY = "user_key";
/**
* 用户ID
*/
public static final String USER_ID = "user_id";
/**
* 用户来源
*/
public static final String USER_FROM = "user_from";
/**
* 用户昵称
*/
public static final String USERNAME = "username";
/**
* 用户身份
*/
public static final String USER_IDENTITY = "user_identity";
/**
* 授权信息字段
*/
public static final String AUTHENTICATION = "authorization";
}

@ -0,0 +1,29 @@
package yuxingshi.ssm.common.core.constants;
/**
* 存放token相关的常量
*/
public class TokenConstants {
/**
* 令牌密钥
*/
public static final String SECRET = "jyuxingshiabcdefghijklmnopqrstuvwxyz";
/**
* 令牌前缀
*/
public static final String PREFIX = "Bearer ";
/**
* 缓存的token key
*/
public static final String LOGIN_TOKEN_KEY = "logintoken:";
/**
* 缓存信息分割符号
*/
public static final String LOGIN_CACHE_INGO_SPLIT = "-";
}

@ -0,0 +1,41 @@
package yuxingshi.ssm.common.core.domain.dto;
import lombok.Data;
import java.util.List;
/**
* 响应结果分页报文
*/
@Data
public class BasePageDTO<T> {
/**
* 查询结果总数
*/
Integer totals;
/**
* 总页数
*/
Integer totalPages;
/**
* 数据列表
*/
List<T> list;
/**
* 计算总页数
*
* @param totals 总数量
* @param pageSize 页大小
* @return 页数
*/
public static int calculateTotalPages(long totals, int pageSize) {
if (pageSize <= 0) {
throw new IllegalArgumentException("Page size must be greater than 0.");
}
return (int) Math.ceil((double) totals / pageSize);
}
}

@ -0,0 +1,32 @@
package yuxingshi.ssm.common.core.domain.dto;
import jakarta.validation.constraints.Max;
import lombok.Data;
/**
* 分页查询基类DTO
*/
@Data
public class BasePageReqDTO {
/**
* 分页编码
*/
private Integer pageNo = 1;
/**
* 分页数量
*/
@Max(20)
private Integer pageSize = 10;
/**
* 获取偏移
*
* @return 偏移信息
*/
public Integer getOffset() {
return (pageNo - 1) * pageSize;
}
}

@ -0,0 +1,54 @@
package yuxingshi.ssm.common.core.domain.dto;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
/**
* 登录用户信息
*/
@Getter
@Setter
@ToString
public class LoginUserDTO {
/**
* 用户标识
*/
private String userKey;
/**
* 用户Id
*/
private String userId;
/**
* 用户来源
*/
private String userFrom;
/**
* 用户名
*/
private String userName;
/**
* 用户身份
*/
private Integer userIdentity;
/**
* 登录时间
*/
private Long loginTime;
/**
* 过期时间
*/
private Long expireTime;
}

@ -0,0 +1,141 @@
package yuxingshi.ssm.common.core.domain.vo;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import yuxingshi.ssm.common.core.constants.ResultCode;
/**
* 响应报文封装
*
* @param <T> 响应数据
*/
@Getter
@Setter
@ToString
public class R<T> {
/**
* 响应码
*/
private int code;
/**
* 消息
*/
private String msg;
/**
* 数据
*/
private T data;
/**
* 成功响应
*
* @return 响应报文
* @param <T> 数据类型
*/
public static <T> R<T> ok() {
return restResult(null, ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg());
}
/**
* 成功响应
* @param data 响应数据
* @return 响应报文
* @param <T> 数据类型
*/
public static <T> R<T> ok(T data) {
return restResult(data, ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg());
}
/**
* 成功响应
* @param data 响应数据
* @param msg 响应消息
* @return 响应报文
* @param <T> 数据类型
*/
public static <T> R<T> ok(T data, String msg) {
return restResult(data, ResultCode.SUCCESS.getCode(), msg);
}
/**
* 失败响应
* @return 响应报文
* @param <T> 数据类型
*/
public static <T> R<T> fail() {
return restResult(null, ResultCode.ERROR.getCode(), ResultCode.ERROR.getMsg());
}
/**
* 失败响应
* @param msg 响应消息
* @return 响应报文
* @param <T> 数据类型
*/
public static <T> R<T> fail(String msg) {
return restResult(null, ResultCode.ERROR.getCode(), msg);
}
/**
* 失败响应
* @param code 响应码
* @param msg 响应消息
* @return 响应报文
* @param <T> 数据类型
*/
public static <T> R<T> fail(Integer code,String msg) {
return restResult(null, code, msg);
}
/**
* 失败响应
* @param data 响应数据
* @return 响应报文
* @param <T> 数据类型
*/
public static <T> R<T> fail(T data) {
return restResult(data, ResultCode.ERROR.getCode(), ResultCode.ERROR.getMsg());
}
/**
* 失败响应
* @param data 响应数据
* @param msg 响应消息
* @return 响应报文
* @param <T> 数据类型
*/
public static <T> R<T> fail(T data, String msg) {
return restResult(data, ResultCode.ERROR.getCode(), msg);
}
/**
* 失败响应
* @param code 响应编码
* @param msg 响应消息
* @return 响应报文
* @param <T> 数据类型
*/
public static <T> R<T> fail(int code, String msg) {
return restResult(null, code, msg);
}
/**
* 响应结果
* @param data 响应数据
* @param code 响应编码
* @param msg 响应消息
* @return 响应报文
* @param <T> 数据类型
*/
private static <T> R<T> restResult(T data, int code, String msg) {
R<T> apiResult = new R<>();
apiResult.setCode(code);
apiResult.setData(data);
apiResult.setMsg(msg);
return apiResult;
}
}

@ -0,0 +1,240 @@
package yuxingshi.ssm.common.core.utils;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import yuxingshi.ssm.common.core.constants.CommonConstants;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* JSON工具类
* 提供:
* 1. 对象转JSON
* 2. JSON转对象
*/
@Slf4j
public class JsonUtil {
/**
* 对象转换器
*/
private static ObjectMapper OBJECT_MAPPER;
/**
* init...
* 1. .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
* 在反序列化时,当遇到 JSON 数据中存在 Java 对象对应类中没有定义的属性时,默认情况下
* Jackson 会抛出异常。通过将这个配置项设置为 false,表示允许在反序列化时忽略那些未知的属
* 性,不会因为出现额外的属性而导致反序列化失败,增强了对不同来源 JSON 数据的兼容性。
* 例如: Student:name, 如果传进来的JSON为Student:name,sex,但是sex并不存在,那么设置为false将忽略sex
* <br>
* 2. .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
* 在序列化时,如果Java 对象中包含日期类型默认情况下 Jackson 可能会将日期转换为时间戳来表示。
* 将此配置设置为false,意味着不采用时间戳的方式来表示日期,而是会按照后续配置的其他日期相关格式进行序列化,
* 以便生成更具可读性的日期格式表示在 JSON 数据中。
* <br>
* 3. .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
* 在序列化时,Java对象中没有任何属性值(为空),默认情况下 Jackson 可能会抛出异常。设置
* 此项为 false 后,允许对这样的空对象进行序列化,即便对象没有实质内容也能生成对应的 JSON
* 表示(通常可能是一个空的 JSON 对象 {}),避免了因对象为空导致序列化失败的情况。
* <br>
* 4. .configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false)
* 在反序列化时,如果 JSON 数据中指定的类型信息与期望的 Java 类型层次结构不匹配(例如类型
* 标识错误等情况),默认会抛出异常。将这个配置设为 false,可以放宽这种限制,使得在遇到类
* 型不太准确但仍有可能处理的情况下,尝试继续进行反序列化而不是直接失败,提高对可能存在错
* 误类型标识的 JSON 数据的容错性。
* <br>
* 5. .configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS, false)
* 在序列化时,如果 Java 对象中有以日期类型作为键(比如在 Map 中,键是 Date 类型等情况)的
* 结构,如果设置为true会将日期键转换为时间戳形式。设置为 false 则按照其他日期相关配置来处
* 理,保证日期键也以期望的格式进行序列化,使得整个 JSON 结构中日期相关内容都能保持统一的
* 格式呈现。(默认值为false)
* <br>
* 6. .configure(MapperFeature.USE_ANNOTATIONS, false)
* Jackson 支持通过在 Java 类的属性或方法上添加各种注解来定制序列化和反序列化行为。将此配
* 置设为 false,表示不依赖这些注解来进行相关操作,而是更多地依据全局配置(如上述其他配置
* 项)来控制序列化和反序列化过程,适用于希望统一管理 JSON 处理规则,减少因注解使用不当或
* 过多导致的复杂性的场景
* 7. addModule(new JavaTimeModule())
* 这是序列化LocalDateTIme和LocalDate的必要配置,由Jackson-data-JSR310实现
* <br>
* 8. .defaultDateFormat(new SimpleDateFormat(CommonConstants.STANDARD_FORMAT))
* 所有的日期格式都统一为以下的样式,即yyyy-MM-dd HH:mm:ss
* <br>
* 9. .addModule(new SimpleModule().addSerializer(LocalDateTime.class, new
* LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
* //序列时起作用
* .addDeserializer(LocalDateTime.class, new
* LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd
* HH:mm:ss"))) //反序列时起作用)
* 对于LocalDateTIme和LocalDate时间类型序列列化时转换为json字符串时可以按照指定格式转换,
* 反序列化时可以也可以将指定的时间字符串类型转换为LocalDateTIme和LocalDate。
*/
static {
OBJECT_MAPPER = JsonMapper.builder().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false)
// 不适用默认的dateTime进行序列化,使用JSR310的LocalDateTimeSerializer
.configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS, false)
.configure(MapperFeature.USE_ANNOTATIONS, true)
// 重点,这是序列化LocalDateTIme和LocalDate的必要配置,由Jackson-data-JSR310实现
.addModule(new JavaTimeModule())
.addModule(new SimpleModule()
.addSerializer(LocalDateTime.class,
new LocalDateTimeSerializer(
DateTimeFormatter.ofPattern(CommonConstants.STANDARD_FORMAT)))
.addDeserializer(LocalDateTime.class,
new LocalDateTimeDeserializer(
DateTimeFormatter.ofPattern(CommonConstants.STANDARD_FORMAT))))
// 所有的日期格式都统一为以下的样式,即yyyy-MM-dd HH:mm:ss
.defaultDateFormat(new SimpleDateFormat(CommonConstants.STANDARD_FORMAT))
// 只针对非空的值进行序列化
.serializationInclusion(JsonInclude.Include.NON_NULL)
.build();
}
/**
* 禁用构造
*/
private JsonUtil() {
}
/**
* 对象转Json格式字符串
*
* @param obj 对象
* @return Json格式字符串
* @param <T> 对象类型
*/
public static <T> String obj2String(T obj) {
if (obj == null) {
return null;
}
try {
return obj instanceof String ? (String) obj : OBJECT_MAPPER.writeValueAsString(obj);
} catch (JsonProcessingException e) {
log.warn("Parse Object to String error : {}", e.getMessage());
return null;
}
}
/**
* 对象转Json格式字符串(格式化的Json字符串)
*
* @param obj 对象
* @return 美化的Json格式字符串
* @param <T> 对象类型
*/
public static <T> String obj2StringPretty(T obj) {
if (obj == null) {
return null;
}
try {
return obj instanceof String ? (String) obj
: OBJECT_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
} catch (JsonProcessingException e) {
log.warn("Parse Object to String error : {}", e.getMessage());
return null;
}
}
/**
* 字符串转换为自定义对象
*
* @param str 要转换的字符串
* @param clazz 自定义对象的class对象
* @return 自定义对象
* @param <T> 对象类型
*/
public static <T> T string2Obj(String str, Class<T> clazz) {
if (str == null || str.isEmpty() || clazz == null) {
return null;
}
try {
return clazz.equals(String.class) ? (T) str : OBJECT_MAPPER.readValue(str, clazz);
} catch (Exception e) {
log.warn("Parse String to Object error : {}", e.getMessage());
return null;
}
}
/**
* 字符串转换为自定义对象,支持复杂的泛型嵌套
*
* @param str json字符串
* @param valueTypeRef 对象模板信息
* 使用如 new TypeReference<List<Map<String,TestObj>>>() {}
* @return 对象类对应的对象
* @param <T> 对象类
*/
public static <T> T string2Obj(String str, TypeReference<T> valueTypeRef) {
if (StringUtils.isEmpty(str) || valueTypeRef == null) {
return null;
}
try {
return OBJECT_MAPPER.readValue(str, valueTypeRef);
} catch (Exception e) {
log.warn("Parse String to Object error : {}", e.getMessage());
return null;
}
}
/**
* 字符串转换为自定义字段转为list,支持List嵌套简单对象
*
* @param str json字符串
* @param clazz 对象类
* @return 对象列表
* @param <T> 对象类型
*/
public static <T> List<T> string2List(String str, Class<T> clazz) {
if (str == null || str.isEmpty() || clazz == null) {
return null;
}
JavaType javaType = OBJECT_MAPPER.getTypeFactory().constructParametricType(List.class, clazz);
try {
return OBJECT_MAPPER.readValue(str, javaType);
} catch (IOException e) {
log.warn("Parse String to List error : {}", e.getMessage());
return null;
}
}
/**
* 字符串转换为自定义字段转为map,支持Map嵌套简单对象
*
* @param str str 字符串信息
* @param valueClass valueClass value的类别
* @return map对象
* @param <T> value 的类型
*/
public static <T> Map<String, T> string2Map(String str, Class<T> valueClass) {
if (str == null || str.isEmpty() || valueClass == null) {
return null;
}
JavaType javaType = OBJECT_MAPPER.getTypeFactory().constructMapType(LinkedHashMap.class,
String.class, valueClass);
try {
return OBJECT_MAPPER.readValue(str, javaType);
} catch (JsonProcessingException e) {
log.warn("Parse String to Map error : {}", e.getMessage());
return null;
}
}
}

@ -0,0 +1,157 @@
package yuxingshi.ssm.common.core.utils;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import reactor.core.publisher.Mono;
import yuxingshi.ssm.common.core.constants.CommonConstants;
import yuxingshi.ssm.common.core.domain.vo.R;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
/**
* Servlet工具类
*/
public class ServletUtil {
/**
* 内容编码
*
* @param str 内容
* @return 编码后的内容
*/
public static String urlEncode(String str) {
try {
return URLEncoder.encode(str, CommonConstants.UTF8);
} catch (UnsupportedEncodingException e) {
return StringUtils.EMPTY;
}
}
/**
* 设置webflux模型响应
*
* @param response ServerHttpResponse
* @param code 响应状态码
* @param value 响应内容
* @return 无
*/
public static Mono<Void> webFluxResponseWriter(ServerHttpResponse response, Object value, int code) {
return webFluxResponseWriter(response, HttpStatus.OK, value, code);
}
/**
* 设置webflux模型响应
*
* @param response ServerHttpResponse
* @param status http状态码
* @param code 响应状态码
* @param value 响应内容
* @return 无
*/
public static Mono<Void> webFluxResponseWriter(ServerHttpResponse response, HttpStatus status, Object value, int code) {
//修改了
return webFluxResponseWriter(response, MediaType.APPLICATION_JSON_VALUE, status, value, code);
}
/**
* 设置webflux模型响应
*
* @param response ServerHttpResponse
* @param contentType content-type
* @param status http状态码
* @param code 响应状态码
* @param value 响应内容
* @return 无
*/
public static Mono<Void> webFluxResponseWriter(ServerHttpResponse response, String contentType, HttpStatus status, Object value, int code) {
response.setStatusCode(status);
response.getHeaders().add(HttpHeaders.CONTENT_TYPE, contentType);
R<?> result = R.fail(code, value.toString());
DataBuffer dataBuffer = response.bufferFactory().wrap(JsonUtil.obj2String(result).getBytes());
return response.writeWith(Mono.just(dataBuffer));
}
/**
* 获取request
*
* @return request对象
*/
public static HttpServletRequest getRequest() {
try {
return getRequestAttributes().getRequest();
} catch (Exception e) {
return null;
}
}
/**
* 获取request属性信息
*
* @return request属性
*/
public static ServletRequestAttributes getRequestAttributes() {
try {
RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
return (ServletRequestAttributes) attributes;
} catch (Exception e) {
return null;
}
}
/**
* 请求里面添加Header
* @param mutate 请求
* @param name 键
* @param value 值
*/
public static void addHeader(ServerHttpRequest.Builder mutate, String name, Object value) {
if(value == null) {
return;
}
String valueStr = value.toString();
String valueEncode = urlEncode(valueStr);
mutate.header(name,valueEncode);
}
/**
* 获取请求IP:
* 用户的真实IP不能使用request.getRemoteAddr()
* 这是因为可能会使用一些代理软件,这样ip获取就不准确了
* 此外我们如果使用了多级(LVS/Nginx)反向代理的话,ip需要从X-Forwarded-For中获得第一个非unknown的IP才是用户的有效ip。
* @return
*/
public static String getRequestIp() {
HttpServletRequest request = getRequest();
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
}

@ -0,0 +1,56 @@
package yuxingshi.ssm.common.core.utils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.AntPathMatcher;
import java.util.List;
/**
* 字符串工具类
*/
public class StringUtil extends StringUtils{
/**
* 判断指定字符串是否与指定匹配规则链表中的任意一个匹配规则匹配
*
* @param str 指定字符串
* @param patternList 匹配规则链表
* @return 是否匹配
*/
public static boolean matches(String str, List<String> patternList)
{
if (StringUtils.isEmpty(str) || CollectionUtils.isEmpty(patternList))
{
return false;
}
for (String pattern : patternList)
{
if (isMatch(pattern, str))
{
return true;
}
}
return false;
}
/**
* 判断url是否与规则匹配
*
* 匹配规则:
* 精确匹配
* 匹配规则中包含 ? 表示任意单个字符;
* 匹配规则中包含 * 表示一层路径内的任意字符串,不可跨层级;
* 匹配规则中包含 ** 表示任意层路径的任意字符,可跨层级
*
* @param pattern 匹配规则
* @param url 需要匹配的url
* @return 是否匹配
*/
public static boolean isMatch(String pattern, String url)
{
if (StringUtils.isEmpty(url) || StringUtils.isEmpty(pattern)) {
return false;
}
AntPathMatcher matcher = new AntPathMatcher();
return matcher.match(pattern, url);
}
}

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>yuxingshi</groupId>
<artifactId>yuxingshi-ssm-common</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>yuxingshi.ssm.common.intercepter</groupId>
<artifactId>yuxingshi-ssm-intercepter</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>yuxingshi.ssm.common.core</groupId>
<artifactId>yuxingshi-ssm-core</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>yuxingshi.ssm.common.security</groupId>
<artifactId>yuxingshi-ssm-security</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

@ -0,0 +1,22 @@
package yuxingshi.ssm.common.intercepter.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import yuxingshi.ssm.common.intercepter.filer.AuthInterceptor;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
private AuthInterceptor authInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/**/login/**");
}
}

@ -0,0 +1,37 @@
package yuxingshi.ssm.common.intercepter.filer;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import yuxingshi.ssm.common.security.service.TokenService;
import yuxingshi.ssm.common.security.utils.SecurityUtil;
/**
* 用户身份认证拦截器
*/
@Slf4j
@Component
public class AuthInterceptor implements HandlerInterceptor {
@Autowired
private TokenService tokenService;
@Override
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response,
Object handler) {
return true;
}
@Override
public void afterCompletion(HttpServletRequest request,
HttpServletResponse response,
Object handler,
Exception ex) {
}
}

@ -0,0 +1,2 @@
yuxingshi.ssm.common.intercepter.config.WebConfig
yuxingshi.ssm.common.intercepter.filer.AuthInterceptor

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>yuxingshi</groupId>
<artifactId>yuxingshi-ssm-common</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>yuxingshi.ssm.common.mybatisplus</groupId>
<artifactId>yuxingshi-ssm-mybatisplus</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
</dependency>
<dependency>
<groupId>yuxingshi.ssm.common.core</groupId>
<artifactId>yuxingshi-ssm-core</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.a3test.component</groupId>
<artifactId>idworker-snowflake</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,25 @@
package yuxingshi.ssm.common.mybatisplus.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* MyBatisPlus配置类
*/
@Configuration
public class MyBatisPlusConfig {
/**
* MyBatisPlus拦截器(用于分页)
*/
@Bean
public MybatisPlusInterceptor paginationInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//添加MySQL的分页拦截器
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}

@ -0,0 +1,21 @@
package yuxingshi.ssm.common.mybatisplus.domain;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Getter;
import lombok.Setter;
import java.time.LocalDateTime;
@Getter
@Setter
public class BaseEntity {
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createdTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updatedTime;
}

@ -0,0 +1,25 @@
package yuxingshi.ssm.common.mybatisplus.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler { ;
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject,"createdTime", LocalDateTime.class,LocalDateTime.now());
this.strictInsertFill(metaObject,"updatedTime", LocalDateTime.class,LocalDateTime.now());
}
@Override
public void updateFill(MetaObject metaObject) {
this.strictInsertFill(metaObject,"updatedTime", LocalDateTime.class,LocalDateTime.now());
}
}

@ -0,0 +1,2 @@
yuxingshi.ssm.common.mybatisplus.config.MyBatisPlusConfig
yuxingshi.ssm.common.mybatisplus.handler.MyMetaObjectHandler

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>yuxingshi</groupId>
<artifactId>yuxingshi-ssm-common</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>yuxingshi.ssm.common.redis</groupId>
<artifactId>yuxingshi-ssm-redis</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</dependency>
<!-- redisson -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>yuxingshi.ssm.common.core</groupId>
<artifactId>yuxingshi-ssm-core</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>

@ -0,0 +1,118 @@
package yuxingshi.ssm.common.redis.config;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import yuxingshi.ssm.common.core.constants.CommonConstants;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@Configuration
public class RedisConfig {
private static final Logger log = LoggerFactory.getLogger(RedisConfig.class);
/**
* 配置RedisTemplate并定义序列化规则
*
* @param redisConnectionFactory redis连接工厂(由Spring Boot自动注入)
* @return 自定义序列化规则的Redis操作模板
*
* 关键配置说明:
* 1. setKeySerializer/setHashKeySerializer:
* - 使用StringRedisSerializer序列化String类型的键和Hash的字段名
* - 确保键可读且兼容所有Redis命令
* 2. setValueSerializer:
* - 值使用GenericJackson2JsonRedisSerializer进行JSON序列化
* - 支持复杂对象存储并保留类型信息
* 3. setHashValueSerializer:
* - Hash类型的值同样使用JSON序列化器
* 4. afterPropertiesSet():
* - 初始化模板确保配置生效
*
*
*/
@Bean(name = "customRedisTemplate")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
log.info("Configure Redis serialization");
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
GenericJackson2JsonRedisSerializer jackson2JsonRedisSerializer =
createJacksonSerializer();
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
/**
* 创建自定义Jackson序列化器
*
* @return 配置了安全策略的JSON序列化器
*
* ObjectMapper关键配置详解:
* 1. FAIL_ON_UNKNOWN_PROPERTIES(false):
* - 反序列化时忽略JSON中的未知字段,增强兼容性
* 2. WRITE_DATES_AS_TIMESTAMPS(false):
* - 禁用日期转时间戳,使用格式化字符串输出日期
* 3. FAIL_ON_EMPTY_BEANS(false):
* - 允许序列化空Bean对象而不抛异常
* 4. FAIL_ON_INVALID_SUBTYPE(false):
* - 忽略无效子类型错误,提高容错性
* 5. WRITE_DATE_KEYS_AS_TIMESTAMPS(false):
* - Map中的日期键也使用格式化字符串
* 6. defaultDateFormat():
* - 统一日期格式为"yyyy-MM-dd HH:mm:ss"标准格式
* 7. USE_ANNOTATIONS(false):
* - 禁用Jackson注解处理(根据需求可选)
* 8. JavaTimeModule():
* - 注册Java8时间模块(LocalDateTime等支持)
* 9. serializationInclusion(NON_NULL):
* - 序列化时自动忽略null值字段
*/
public GenericJackson2JsonRedisSerializer createJacksonSerializer() {
// 创建自定义日期格式
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(CommonConstants.STANDARD_FORMAT);
// 创建并配置 JavaTimeModule
JavaTimeModule javaTimeModule = new JavaTimeModule();
javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(formatter));
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(formatter));
ObjectMapper objectMapper =
JsonMapper.builder()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
.configure(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE, false)
.configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS, false)
.defaultDateFormat(new SimpleDateFormat(CommonConstants.STANDARD_FORMAT))
.configure(MapperFeature.USE_ANNOTATIONS, false)
// 注册自定义时间模块
.addModule(javaTimeModule)
.serializationInclusion(JsonInclude.Include.NON_NULL)
.build();
return new GenericJackson2JsonRedisSerializer(objectMapper);
}
}

@ -0,0 +1,2 @@
yuxingshi.ssm.common.redis.config.RedisConfig
yuxingshi.ssm.common.redis.server.RedisService

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>yuxingshi</groupId>
<artifactId>yuxingshi-ssm-common</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>yuxingshi.ssm.common.security</groupId>
<artifactId>yuxingshi-ssm-security</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
</dependency>
<dependency>
<groupId>yuxingshi.ssm.common.core</groupId>
<artifactId>yuxingshi-ssm-core</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>yuxingshi.ssm.common.redis</groupId>
<artifactId>yuxingshi-ssm-redis</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,21 @@
package yuxingshi.ssm.common.security.annotation;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.*;
@Documented
@Constraint(validatedBy = ValueInValidator.class)
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ValueIn {
String message() default "值不在指定范围内";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
// 枚举类
Class<? extends Enum<?>> enumClass();
}

@ -0,0 +1,57 @@
package yuxingshi.ssm.common.security.annotation;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
public class ValueInValidator implements ConstraintValidator<ValueIn, Object> {
private ValueIn constraint;
private Set<Object> validValues = new HashSet<>();
private Class<?> valueType;
private Method getValueMethod;
@Override
public void initialize(ValueIn constraint) {
this.constraint = constraint;
Class<? extends Enum<?>> enumClass = constraint.enumClass();
// 获取枚举值
Enum<?>[] enumConstants = enumClass.getEnumConstants();
if (enumConstants == null || enumConstants.length == 0) {
throw new IllegalArgumentException("枚举类 " + enumClass.getName() + " 不包含任何值");
}
try {
// 强制要求必须存在 getValue() 方法
this.getValueMethod = enumClass.getMethod("getValue");
this.valueType = getValueMethod.getReturnType();
// 收集所有有效的 value 值
for (Enum<?> e : enumConstants) {
Object value = getValueMethod.invoke(e);
validValues.add(value);
}
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException("枚举类 " + enumClass.getName() + " 必须包含 getValue() 方法", e);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException("无法访问枚举的 getValue() 方法", e);
}
}
@Override
public boolean isValid(Object value, ConstraintValidatorContext context) {
if (value == null) {
return true;
}
if(value.getClass() != valueType){
return false;
}
return validValues.contains(value);
}
}

@ -0,0 +1,28 @@
package yuxingshi.ssm.common.security.dto;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
/**
* 存放令牌信息
*/
@Getter
@Setter
@ToString
public class TokenDto {
/**
* 访问的令牌
*/
private String accessToken;
/**
* 令牌的过期时间
*/
private Long expires;
private Integer role;
}

@ -0,0 +1,171 @@
package yuxingshi.ssm.common.security.service;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import yuxingshi.ssm.common.core.constants.CacheConstants;
import yuxingshi.ssm.common.core.constants.SecurityConstants;
import yuxingshi.ssm.common.core.constants.TokenConstants;
import yuxingshi.ssm.common.core.domain.dto.LoginUserDTO;
import yuxingshi.ssm.common.core.utils.ServletUtil;
import yuxingshi.ssm.common.redis.server.RedisService;
import yuxingshi.ssm.common.security.dto.TokenDto;
import yuxingshi.ssm.common.security.utils.JwtUtil;
import yuxingshi.ssm.common.security.utils.SecurityUtil;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
/**
* token服务类
*/
@Component
public class TokenService {
/**
* 登录用户过期时间(s)
*/
private static final Long LOGIN_USER_EXP = CacheConstants.LOGIN_USER_EXPIRATION * 60 * 1000;
@Autowired
private RedisService redisService;
/**
* 创建token
* @param loginUserDto 登录信息
* @return token信息
*/
public TokenDto createToken(LoginUserDTO loginUserDto) {
String userKey = UUID.randomUUID().toString().replaceAll("-", "");
loginUserDto.setUserKey(userKey);
refreshToken(loginUserDto);
Map<String,Object> claimMap = new HashMap<>();
claimMap.put(SecurityConstants.USER_KEY,userKey);
claimMap.put(SecurityConstants.USER_ID,loginUserDto.getUserId());
claimMap.put(SecurityConstants.USER_FROM,loginUserDto.getUserFrom());
claimMap.put(SecurityConstants.USER_IDENTITY,loginUserDto.getUserIdentity());
TokenDto tokenDto = new TokenDto();
tokenDto.setAccessToken(JwtUtil.createToken(claimMap));
tokenDto.setExpires(LOGIN_USER_EXP);
refreshToken(loginUserDto);
return tokenDto;
}
/**
* 根据令牌获取用户信息
* @param token 令牌
* @return 用户信息
*/
public LoginUserDTO getLoginUserDto(String token) {
LoginUserDTO loginUserDto = null;
// 解析令牌
try {
if(StringUtils.isNoneBlank(token)) {
Claims claims = JwtUtil.parseToken(token);
String userKey = JwtUtil.getUserKey(claims);
String userId = JwtUtil.getUserId(claims);
String userFrom = JwtUtil.getUserFrom(claims);
loginUserDto = redisService.getCacheObject(getCacheKey(userKey,userId,userFrom), LoginUserDTO.class);
}
return loginUserDto;
}catch (Exception e) {}
return loginUserDto;
}
/**
* 通过请求信息获取用户信息
* @param request 请求信息
* @return 用户信息
*/
public LoginUserDTO getLoginUserDto(HttpServletRequest request) {
String token = SecurityUtil.getToken(request);
return getLoginUserDto(token);
}
/**
* 获取用户信息
* @return 用户信息
*/
public LoginUserDTO getLoginUserDto() {
return getLoginUserDto(ServletUtil.getRequest());
}
/**
* 删除用户登录状态
*/
public void removeLoginStatus(String token) {
if(StringUtils.isNoneBlank(token)) {
Claims claims = JwtUtil.parseToken(token);
String userKey = JwtUtil.getUserKey(claims);
String userId = JwtUtil.getUserId(claims);
String userFrom = JwtUtil.getUserFrom(claims);
String cacheKey = getCacheKey(userKey,userId,userFrom);
redisService.deleteObject(cacheKey);
}
}
/**
* 允许管理员删除别人的用户登录状态
* @param userId 用户Id
* @param userFrom 用户来源
*/
public void removeLoginStatus(Long userId,String userFrom) {
String split = TokenConstants.LOGIN_CACHE_INGO_SPLIT;
String pattern = TokenConstants.LOGIN_TOKEN_KEY + split + userId + split + userFrom +split + "*";
redisService.scanAndDelete(pattern,100);
}
/**
* 允许管理员设置用户登录状态
* @param loginUserDto 用户信息
*/
public void setLoginUser(LoginUserDTO loginUserDto) {
if(loginUserDto != null && StringUtils.isNoneBlank(loginUserDto.getUserKey())) {
refreshToken(loginUserDto);
}
}
/**
* 延期令牌有效时间 不到120分钟,自动刷新
* @param loginUserDto 用户数据
*/
public void extendToken(LoginUserDTO loginUserDto) {
long expTime = loginUserDto.getExpireTime();
long currentTime = System.currentTimeMillis();
if(currentTime - expTime <= CacheConstants.LOGIN_USER_EXP_CRITICAL_TIME * 60) {
loginUserDto.setLoginTime(currentTime);
loginUserDto.setExpireTime(currentTime + LOGIN_USER_EXP);
refreshToken(loginUserDto);
}
}
/**
* 登录用户缓存
* @param loginUserDto 登录用户信息
*/
private void refreshToken(LoginUserDTO loginUserDto) {
loginUserDto.setLoginTime(System.currentTimeMillis());
loginUserDto.setExpireTime(loginUserDto.getLoginTime() + LOGIN_USER_EXP);
String cacheKey = getCacheKey(loginUserDto.getUserKey(), loginUserDto.getUserId(),loginUserDto.getUserFrom());
redisService.setCacheObject(cacheKey,loginUserDto,LOGIN_USER_EXP, TimeUnit.MILLISECONDS);
}
/**
* 获取缓存键
* @param userKey 用户标识
* @return 缓存键
*/
public String getCacheKey(String userKey,String userId,String userFrom) {
String split = TokenConstants.LOGIN_CACHE_INGO_SPLIT;
return TokenConstants.LOGIN_TOKEN_KEY + ":" + userId + split + userFrom +split+ userKey;
}
}

@ -0,0 +1,156 @@
package yuxingshi.ssm.common.security.utils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import yuxingshi.ssm.common.core.constants.SecurityConstants;
import yuxingshi.ssm.common.core.constants.TokenConstants;
import java.util.Map;
/**
* 令牌工具类
*/
public class JwtUtil {
private static final Logger log = LoggerFactory.getLogger(JwtUtil.class);
public static String secret = TokenConstants.SECRET;
/**
* 根据原始的数据生成令牌
* @param claims 原始数据
* @return 令牌
*/
public static String createToken(Map<String,Object> claims) {
return Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS512, secret).compact();
}
/**
* 根据令牌获取原始数据
* @param token 令牌
* @return 原始数据
*/
public static Claims parseToken(String token) {
try {
return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
}catch (Exception e) {
log.warn("[JwtUtil.parseToken]");
return null;
}
}
/**
* 从令牌中获取用户标识
* @param token 令牌
* @return 用户标识
*/
public static String getUserKey(String token) {
Claims claims = parseToken(token);
return getValue(claims, SecurityConstants.USER_KEY);
}
/**
* 根据数据声明获取用户Id
* @param claims 数据声明
* @return 用户id
*/
public static String getUserId(Claims claims) {
return getValue(claims, SecurityConstants.USER_ID);
}
/**
* 从令牌中获取用户id
* @param token 令牌
* @return 用户id
*/
public static String getUserId(String token) {
Claims claims = parseToken(token);
return getValue(claims, SecurityConstants.USER_ID);
}
/**
* 根据数据声明获取用户名称
* @param claims 数据声明
* @return 用户名称
*/
public static String getUserName(Claims claims) {
return getValue(claims, SecurityConstants.USERNAME);
}
/**
* 从令牌中获取用户身份
* @param token 令牌
* @return 用户身份
*/
public static String getUserIdentity(String token) {
Claims claims = parseToken(token);
return getValue(claims, SecurityConstants.USER_IDENTITY);
}
/**
* 根据数据声明获取用户身份
* @param claims 数据声明
* @return 用户身份
*/
public static String getUserIdentity(Claims claims) {
return getValue(claims, SecurityConstants.USER_IDENTITY);
}
/**
* 从令牌中获取用户标识
* @param token 令牌
* @return 用户标识
*/
public static String getUserFrom(String token) {
Claims claims = parseToken(token);
return getValue(claims, SecurityConstants.USER_FROM);
}
/**
* 根据数据声明获取用户来源
* @param claims 数据声明
* @return 用户来源
*/
public static String getUserFrom(Claims claims) {
return getValue(claims, SecurityConstants.USER_FROM);
}
/**
* 从令牌中获取用户来源
* @param token 令牌
* @return 用户来源
*/
public static String getUserName(String token) {
Claims claims = parseToken(token);
return getValue(claims, SecurityConstants.USERNAME);
}
/**
* 根据数据声明获取用户标识
* @param claims 数据声明
* @return 用户标识
*/
public static String getUserKey(Claims claims) {
return getValue(claims, SecurityConstants.USER_KEY);
}
/**
* 获取数据声明来获取数据
* @param claims 数据声明
* @param key 键
* @return 数据
*/
public static String getValue(Claims claims,String key) {
Object value = claims.get(key);
if(value == null) {
return "";
}
return value.toString();
}
}

@ -0,0 +1,53 @@
package yuxingshi.ssm.common.security.utils;
import jakarta.servlet.http.HttpServletRequest;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.server.reactive.ServerHttpRequest;
import yuxingshi.ssm.common.core.constants.SecurityConstants;
import yuxingshi.ssm.common.core.constants.TokenConstants;
import yuxingshi.ssm.common.core.utils.ServletUtil;
/**
* 安全工具类
*/
public class SecurityUtil {
/**
* 获取请求token
* @return token信息
*/
public static String getToken() {
return getToken(ServletUtil.getRequest());
}
/**
* 从请求头中获取token
* @param request 请求信息
* @return token
*/
public static String getToken(HttpServletRequest request) {
return replaceTokenPrefix(request.getHeader(SecurityConstants.AUTHENTICATION));
}
/**
* 从请求头中获取token
* @param request 请求信息
* @return token
*/
public static String getToken(ServerHttpRequest request) {
return replaceTokenPrefix(request.getHeaders().getFirst(SecurityConstants.AUTHENTICATION));
}
/**
* 裁剪token前缀
* @param token 令牌
* @return 裁剪后的token
*/
public static String replaceTokenPrefix(String token) {
if(StringUtils.isNoneBlank(token) && token.startsWith(TokenConstants.PREFIX)){
token.replaceFirst(TokenConstants.PREFIX,"");
}
return token;
}
}

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>yuxingshi</groupId>
<artifactId>yuxingshi-ssm</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<groupId>yuxingshi.ssm.server</groupId>
<artifactId>yuxingshi-ssm-server</artifactId>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,7 @@
package yuxingshi.ssm.server;
public class Main {
public static void main(String[] args) {
System.out.println("Hello world!");
}
}
Loading…
Cancel
Save