소스 검색

管理员登录

bmmx 1 년 전
커밋
56563d088b
32개의 변경된 파일1669개의 추가작업 그리고 0개의 파일을 삭제
  1. 42 0
      .gitignore
  2. 7 0
      .idea/encodings.xml
  3. 15 0
      .idea/misc.xml
  4. 124 0
      .idea/uiDesigner.xml
  5. 7 0
      .idea/vcs.xml
  6. 175 0
      .idea/workspace.xml
  7. 158 0
      pom.xml
  8. 15 0
      src/main/java/com/om/OperationApplication.java
  9. 53 0
      src/main/java/com/om/config/Knife4jConfig.java
  10. 22 0
      src/main/java/com/om/config/MyBatisPlusConfig.java
  11. 69 0
      src/main/java/com/om/config/RedisConfig.java
  12. 66 0
      src/main/java/com/om/config/WebMvcConfiguration.java
  13. 20 0
      src/main/java/com/om/constant/LoginConstant.java
  14. 9 0
      src/main/java/com/om/constant/RedisConstant.java
  15. 40 0
      src/main/java/com/om/controller/admin/AdminController.java
  16. 75 0
      src/main/java/com/om/entity/po/Admin.java
  17. 49 0
      src/main/java/com/om/entity/vo/AdminLoginVO.java
  18. 19 0
      src/main/java/com/om/exception/BizException.java
  19. 18 0
      src/main/java/com/om/exception/CustomerAuthenticationException.java
  20. 62 0
      src/main/java/com/om/handler/GlobalExceptionHandler.java
  21. 114 0
      src/main/java/com/om/interceptor/JwtTokenAdminInterceptor.java
  22. 111 0
      src/main/java/com/om/interceptor/JwtTokenUserInterceptor.java
  23. 16 0
      src/main/java/com/om/mapper/AdminMapper.java
  24. 18 0
      src/main/java/com/om/service/IAdminService.java
  25. 90 0
      src/main/java/com/om/service/impl/AdminServiceImpl.java
  26. 29 0
      src/main/java/com/om/utils/AdminContext.java
  27. 110 0
      src/main/java/com/om/utils/JwtUtils.java
  28. 70 0
      src/main/java/com/om/utils/Result.java
  29. 21 0
      src/main/java/com/om/utils/ResultCode.java
  30. 34 0
      src/main/resources/application-dev.yml
  31. 6 0
      src/main/resources/application.yml
  32. 5 0
      src/main/resources/mapper/AdminMapper.xml

+ 42 - 0
.gitignore

@@ -0,0 +1,42 @@
+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
+
+
+### 前端 ###
+/yanxin-admin/

+ 7 - 0
.idea/encodings.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Encoding">
+    <file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
+    <file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
+  </component>
+</project>

+ 15 - 0
.idea/misc.xml

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

+ 124 - 0
.idea/uiDesigner.xml

@@ -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>

+ 7 - 0
.idea/vcs.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="$PROJECT_DIR$" vcs="Git" />
+    <mapping directory="$PROJECT_DIR$/yanxin-admin" vcs="Git" />
+  </component>
+</project>

+ 175 - 0
.idea/workspace.xml

@@ -0,0 +1,175 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="AutoImportSettings">
+    <option name="autoReloadType" value="SELECTIVE" />
+  </component>
+  <component name="ChangeListManager">
+    <list default="true" id="46b159bd-08ca-42f0-b80f-41d4944a8a29" name="Changes" comment="">
+      <change afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/.idea/encodings.xml" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/.idea/uiDesigner.xml" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/.idea/vcs.xml" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/pom.xml" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/om/OperationApplication.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/om/config/Knife4jConfig.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/om/config/MyBatisPlusConfig.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/om/config/RedisConfig.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/om/config/WebMvcConfiguration.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/om/constant/LoginConstant.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/om/constant/RedisConstant.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/om/controller/admin/AdminController.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/om/entity/po/Admin.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/om/entity/vo/AdminLoginVO.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/om/exception/BizException.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/om/exception/CustomerAuthenticationException.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/om/handler/GlobalExceptionHandler.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/om/interceptor/JwtTokenAdminInterceptor.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/om/interceptor/JwtTokenUserInterceptor.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/om/mapper/AdminMapper.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/om/service/IAdminService.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/om/service/impl/AdminServiceImpl.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/om/utils/AdminContext.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/om/utils/JwtUtils.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/om/utils/Result.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/java/com/om/utils/ResultCode.java" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/resources/application-dev.yml" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/resources/application.yml" afterDir="false" />
+      <change afterPath="$PROJECT_DIR$/src/main/resources/mapper/AdminMapper.xml" afterDir="false" />
+    </list>
+    <option name="SHOW_DIALOG" value="false" />
+    <option name="HIGHLIGHT_CONFLICTS" value="true" />
+    <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
+    <option name="LAST_RESOLUTION" value="IGNORE" />
+  </component>
+  <component name="FileTemplateManagerImpl">
+    <option name="RECENT_TEMPLATES">
+      <list>
+        <option value="Class" />
+      </list>
+    </option>
+  </component>
+  <component name="Git.Settings">
+    <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
+  </component>
+  <component name="MavenImportPreferences">
+    <option name="generalSettings">
+      <MavenGeneralSettings>
+        <option name="mavenHome" value="B:\apache-maven-3.8.8" />
+        <option name="userSettingsFile" value="B:\apache-maven-3.8.8\conf\settings.xml" />
+      </MavenGeneralSettings>
+    </option>
+  </component>
+  <component name="ProjectColorInfo">{
+  &quot;associatedIndex&quot;: 4
+}</component>
+  <component name="ProjectId" id="2bRXnA0a6xf96LKQuj3K31U3F7Y" />
+  <component name="ProjectLevelVcsManager" settingsEditedManually="true">
+    <ConfirmationsSetting value="2" id="Add" />
+  </component>
+  <component name="ProjectViewState">
+    <option name="hideEmptyMiddlePackages" value="true" />
+    <option name="showLibraryContents" value="true" />
+  </component>
+  <component name="PropertiesComponent">{
+  &quot;keyToString&quot;: {
+    &quot;RequestMappingsPanelOrder0&quot;: &quot;0&quot;,
+    &quot;RequestMappingsPanelOrder1&quot;: &quot;1&quot;,
+    &quot;RequestMappingsPanelWidth0&quot;: &quot;75&quot;,
+    &quot;RequestMappingsPanelWidth1&quot;: &quot;75&quot;,
+    &quot;RunOnceActivity.OpenProjectViewOnStart&quot;: &quot;true&quot;,
+    &quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
+    &quot;SHARE_PROJECT_CONFIGURATION_FILES&quot;: &quot;true&quot;,
+    &quot;Spring Boot.OperationApplication.executor&quot;: &quot;Run&quot;,
+    &quot;git-widget-placeholder&quot;: &quot;master&quot;,
+    &quot;kotlin-language-version-configured&quot;: &quot;true&quot;,
+    &quot;last_opened_file_path&quot;: &quot;B:/WorkSpace/PracticalRojects/OperationSystem/src/main/resources&quot;,
+    &quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,
+    &quot;node.js.detected.package.tslint&quot;: &quot;true&quot;,
+    &quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;,
+    &quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;,
+    &quot;nodejs_package_manager_path&quot;: &quot;npm&quot;,
+    &quot;project.structure.last.edited&quot;: &quot;Project&quot;,
+    &quot;project.structure.proportion&quot;: &quot;0.15&quot;,
+    &quot;project.structure.side.proportion&quot;: &quot;0.2&quot;,
+    &quot;settings.editor.selected.configurable&quot;: &quot;MavenSettings&quot;,
+    &quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
+  }
+}</component>
+  <component name="ReactorSettings">
+    <option name="notificationShown" value="true" />
+  </component>
+  <component name="RecentsManager">
+    <key name="CopyFile.RECENT_KEYS">
+      <recent name="B:\WorkSpace\PracticalRojects\OperationSystem\src\main\resources" />
+      <recent name="B:\WorkSpace\PracticalRojects\OperationSystem\src\main\java\com\om\utils" />
+      <recent name="B:\WorkSpace\PracticalRojects\OperationSystem\src\main\java\com\om" />
+    </key>
+    <key name="CopyClassDialog.RECENTS_KEY">
+      <recent name="com.om.interceptor" />
+      <recent name="com.om.exception" />
+      <recent name="com.om.controller" />
+      <recent name="com.om.config" />
+      <recent name="com.om.mapper" />
+    </key>
+  </component>
+  <component name="RunManager">
+    <configuration name="OperationApplication" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot" temporary="true" nameIsGenerated="true">
+      <module name="OperationSystem" />
+      <option name="SPRING_BOOT_MAIN_CLASS" value="com.om.OperationApplication" />
+      <extension name="coverage">
+        <pattern>
+          <option name="PATTERN" value="com.om.*" />
+          <option name="ENABLED" value="true" />
+        </pattern>
+      </extension>
+      <method v="2">
+        <option name="Make" enabled="true" />
+      </method>
+    </configuration>
+    <recent_temporary>
+      <list>
+        <item itemvalue="Spring Boot.OperationApplication" />
+      </list>
+    </recent_temporary>
+  </component>
+  <component name="SharedIndexes">
+    <attachedChunks>
+      <set>
+        <option value="jdk-1.8.0_392-corretto-1.8.0_392-f644763e9732-f719d367" />
+      </set>
+    </attachedChunks>
+  </component>
+  <component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
+  <component name="TaskManager">
+    <task active="true" id="Default" summary="Default task">
+      <changelist id="46b159bd-08ca-42f0-b80f-41d4944a8a29" name="Changes" comment="" />
+      <created>1706179029455</created>
+      <option name="number" value="Default" />
+      <option name="presentableId" value="Default" />
+      <updated>1706179029455</updated>
+      <workItem from="1706179030846" duration="895000" />
+      <workItem from="1706233987949" duration="10757000" />
+      <workItem from="1706264160330" duration="728000" />
+      <workItem from="1706414608767" duration="680000" />
+      <workItem from="1706415453436" duration="3741000" />
+      <workItem from="1706419384391" duration="5896000" />
+    </task>
+    <servers />
+  </component>
+  <component name="TypeScriptGeneratedFilesManager">
+    <option name="version" value="3" />
+  </component>
+  <component name="XDebuggerManager">
+    <breakpoint-manager>
+      <breakpoints>
+        <line-breakpoint enabled="true" type="java-line">
+          <url>file://$PROJECT_DIR$/src/main/java/com/om/interceptor/JwtTokenAdminInterceptor.java</url>
+          <line>74</line>
+          <option name="timeStamp" value="10" />
+        </line-breakpoint>
+      </breakpoints>
+    </breakpoint-manager>
+  </component>
+</project>

+ 158 - 0
pom.xml

@@ -0,0 +1,158 @@
+<?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>com.om</groupId>
+    <artifactId>OperationSystem</artifactId>
+    <version>1.0-SNAPSHOT</version>
+
+    <parent>
+        <groupId>org.springframework.boot</groupId>
+        <artifactId>spring-boot-starter-parent</artifactId>
+        <version>2.4.10</version>
+    </parent>
+
+    <properties>
+        <maven.compiler.source>8</maven.compiler.source>
+        <maven.compiler.target>8</maven.compiler.target>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <mybatis-plus.version>3.4.1</mybatis-plus.version>
+        <mysql.version>8.0.33</mysql.version>
+        <knife4j.version>3.0.3</knife4j.version>
+        <jwt.version>0.9.1</jwt.version>
+        <fastjson.version>2.0.21</fastjson.version>
+    </properties>
+
+
+
+    <dependencies>
+        <!--springboot中web启动器-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.springframework.boot</groupId>
+                    <artifactId>spring-boot-starter-tomcat</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-undertow</artifactId>
+            <exclusions>
+                <!-- 排除 undertow-websockets-jsr 依赖 -->
+                <exclusion>
+                    <groupId>io.undertow</groupId>
+                    <artifactId>undertow-websockets-jsr</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+
+        <!--springboot中test启动-->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <!--mybatis-plus 持久层-->
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <version>${mybatis-plus.version}</version>
+        </dependency>
+
+        <!--mysql-->
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <version>${mysql.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+      <!--  <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-security</artifactId>
+        </dependency>-->
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-data-redis</artifactId>
+        </dependency>
+
+
+        <!--http客户端依赖-->
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>4.5.10</version>
+        </dependency>
+        <dependency>
+            <groupId>org.json</groupId>
+            <artifactId>json</artifactId>
+            <version>20230618</version>
+        </dependency>
+
+        <!--common-lang工具包-->
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-lang3</artifactId>
+            <version>3.4</version>
+        </dependency>
+
+        <!--springboot整合knife4j依赖-->
+        <dependency>
+            <groupId>com.github.xiaoymin</groupId>
+            <artifactId>knife4j-spring-boot-starter</artifactId>
+            <version>3.0.3</version>
+        </dependency>
+        <!--hutool工具包-->
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>5.8.21</version>
+        </dependency>
+
+        <!--jjwt-->
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt</artifactId>
+            <version>${jwt.version}</version>
+        </dependency>
+        <!--fastjson-->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>fastjson</artifactId>
+            <version>${fastjson.version}</version>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <!--项目名称-->
+        <finalName>${project.artifactId}</finalName>
+        <plugins>
+            <!-- 设置maven生命周期-->
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <!--test失败后忽略-->
+                    <skipTests>true</skipTests>
+                </configuration>
+            </plugin>
+            <!--项目打包时,把需要的各种依赖包都打到jar包中,jar包可以独立运行,使用“java -jar”可以直接运-->
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+
+</project>

+ 15 - 0
src/main/java/com/om/OperationApplication.java

@@ -0,0 +1,15 @@
+package com.om;
+
+import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+@EnableKnife4j
+@MapperScan("com.om.mapper")
+public class OperationApplication {
+    public static void main(String[] args) {
+        SpringApplication.run(OperationApplication.class,args);
+    }
+}

+ 53 - 0
src/main/java/com/om/config/Knife4jConfig.java

@@ -0,0 +1,53 @@
+package com.om.config;
+
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.Contact;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
+
+import java.util.Collections;
+
+@Configuration
+@EnableSwagger2WebMvc
+public class Knife4jConfig {
+
+    @Bean
+    public Docket createRestApi1() {
+        return new Docket(DocumentationType.SWAGGER_2)
+                .groupName("管理员接口")
+                .protocols(Collections.singleton("https"))
+                .apiInfo(apiInfo())
+                .select()
+                .apis(RequestHandlerSelectors.basePackage("com.om.controller.admin"))
+                .paths(PathSelectors.any())
+                .build();
+    }
+
+    @Bean
+    public Docket createRestApi2() {
+        return new Docket(DocumentationType.SWAGGER_2)
+                .groupName("客户端接口")
+                .protocols(Collections.singleton("https"))
+                .apiInfo(apiInfo())
+                .select()
+                .apis(RequestHandlerSelectors.basePackage("com.om.controller.user"))
+                .paths(PathSelectors.any())
+                .build();
+    }
+
+    private ApiInfo apiInfo() {
+        return new ApiInfoBuilder()
+                .title("运维系统项目接口文档")
+                .description("运维系统项目接口文档")
+                .version("1.0")
+                .build();
+    }
+
+}

+ 22 - 0
src/main/java/com/om/config/MyBatisPlusConfig.java

@@ -0,0 +1,22 @@
+package com.om.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;
+
+
+@Configuration
+public class MyBatisPlusConfig {
+    @Bean
+    public MybatisPlusInterceptor mybatisPlusInterceptor() {
+        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
+        PaginationInnerInterceptor paginationInnerInterceptor =
+                new PaginationInnerInterceptor(DbType.MYSQL);
+        paginationInnerInterceptor.setOverflow(true);//溢出后从第1页开始
+        //指定数据库类型
+        interceptor.addInnerInterceptor(paginationInnerInterceptor);
+        return interceptor;
+    }
+}

+ 69 - 0
src/main/java/com/om/config/RedisConfig.java

@@ -0,0 +1,69 @@
+package com.om.config;
+
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.cache.RedisCacheConfiguration;
+import org.springframework.data.redis.cache.RedisCacheManager;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.RedisSerializationContext;
+import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+import java.time.Duration;
+
+/**
+ * redis配置类
+ */
+@Configuration
+public class RedisConfig {
+
+
+    @Bean
+    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
+        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
+        // 配置连接工厂
+        template.setConnectionFactory(factory);
+        //使用Jackson2JsonRedisSerialize 替换默认序列化(默认采用的是JDK序列化)
+        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
+        //解决查询缓存转换异常的问题
+        ObjectMapper om = new ObjectMapper();
+        //设置在生成 json 串时,对象中的成员的可见性
+        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+        //存储到redis的json将是有类型的数据
+        //指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
+        om.activateDefaultTyping(om.getPolymorphicTypeValidator(), ObjectMapper.DefaultTyping.NON_FINAL);
+        jackson2JsonRedisSerializer.setObjectMapper(om);
+        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
+        // key采用String的序列化方式
+        template.setKeySerializer(stringRedisSerializer);
+        // hash的key也采用String的序列化方式
+        template.setHashKeySerializer(stringRedisSerializer);
+        // value序列化方式采用jackson
+        template.setValueSerializer(jackson2JsonRedisSerializer);
+        // hash的value序列化方式采用jackson
+        template.setHashValueSerializer(jackson2JsonRedisSerializer);
+        template.afterPropertiesSet();
+        return template;
+    }
+
+    //@Cacheable注解字符集编码配置
+    @Bean
+    public RedisCacheManager cacheManager(RedisConnectionFactory factory) {
+        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
+        config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.string()))
+                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(RedisSerializer.json()));
+
+        return RedisCacheManager
+                .builder(factory)
+                .cacheDefaults(config)
+                .build();
+    }
+}
+

+ 66 - 0
src/main/java/com/om/config/WebMvcConfiguration.java

@@ -0,0 +1,66 @@
+package com.om.config;
+
+import com.om.constant.LoginConstant;
+import com.om.interceptor.JwtTokenAdminInterceptor;
+import com.om.interceptor.JwtTokenUserInterceptor;
+import lombok.extern.slf4j.Slf4j;
+
+import org.springframework.context.annotation.Configuration;
+
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
+
+import javax.annotation.Resource;
+
+/**
+ * 配置类,注册web层相关组件
+ */
+@Configuration
+@Slf4j
+public class WebMvcConfiguration extends WebMvcConfigurationSupport {
+
+    @Resource
+    private JwtTokenAdminInterceptor jwtTokenAdminInterceptor;
+
+    @Resource
+    private JwtTokenUserInterceptor jwtTokenUserInterceptor;
+    /**
+     * 注册自定义拦截器
+     *
+     * @param registry
+     */
+    protected void addInterceptors(InterceptorRegistry registry) {
+        log.info("开始注册自定义拦截器...");
+        //管理员拦截器
+        registry.addInterceptor(jwtTokenAdminInterceptor)
+                .addPathPatterns("/web/**")
+                .excludePathPatterns(LoginConstant.ADMIN_ALLOWED_PATHS)
+                .excludePathPatterns(LoginConstant.KNIFE4J_PATHS);
+
+        //用户拦截器 todo
+        registry.addInterceptor(jwtTokenUserInterceptor)
+                .addPathPatterns("/manager/**")
+                .excludePathPatterns(LoginConstant.ADMIN_ALLOWED_PATHS)
+                .excludePathPatterns(LoginConstant.KNIFE4J_PATHS);
+
+    }
+
+
+
+
+    /**
+     * 设置静态资源映射
+     * @param registry
+     */
+    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
+        registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
+        registry.addResourceHandler("/favicon.ico").addResourceLocations("classpath:/META-INF/resources/");
+        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
+    }
+
+   
+
+    }
+
+

+ 20 - 0
src/main/java/com/om/constant/LoginConstant.java

@@ -0,0 +1,20 @@
+package com.om.constant;
+
+public class LoginConstant {
+
+    public static final String[] KNIFE4J_PATHS = {
+            "/v2/**",
+            "/swagger-resources/**",
+            "/webjars/**",
+            "/doc.html",
+            "/public/**",
+            "/static/**",
+            "/resources/**",
+            "/favicon.ico"//上面都是Knife4j的静态资源路径
+    };
+
+    public static final String[]  ADMIN_ALLOWED_PATHS = {
+            "/manager/login"
+    };
+
+}

+ 9 - 0
src/main/java/com/om/constant/RedisConstant.java

@@ -0,0 +1,9 @@
+package com.om.constant;
+
+public class RedisConstant {
+    /**
+    * 格式:token:admin:管理员id
+     * */
+    public static final String ADMIN_TOKEN_PREFIX = "token:admin:";
+    public static final Long ADMIN_TOKEN_TTL = 7200000L;
+}

+ 40 - 0
src/main/java/com/om/controller/admin/AdminController.java

@@ -0,0 +1,40 @@
+package com.om.controller.admin;
+
+
+import com.om.exception.BizException;
+import com.om.service.IAdminService;
+import com.om.utils.AdminContext;
+import com.om.utils.Result;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author bmmx
+ * @since 2024-01-26
+ */
+@RestController
+@Api(tags = "后台管理系统用户模块接口")
+@RequestMapping("/manager")
+public class AdminController {
+
+    @Resource
+    private IAdminService adminService;
+
+
+    @GetMapping("/login")
+    @ApiOperation("管理员登录")
+    public Result login(@RequestParam String username, @RequestParam String password){
+        return adminService.login(username,password);
+    }
+
+}

+ 75 - 0
src/main/java/com/om/entity/po/Admin.java

@@ -0,0 +1,75 @@
+package com.om.entity.po;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author bmmx
+ * @since 2024-01-26
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@TableName("admin")
+@ApiModel(value="Admin对象", description="")
+public class Admin implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "管理员ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @ApiModelProperty(value = "管理员用户名")
+    private String username;
+
+    @ApiModelProperty(value = "管理员密码")
+    private String password;
+
+    @ApiModelProperty(value = "管理员真实姓名")
+    private String realName;
+
+    @ApiModelProperty(value = "管理员电子邮件")
+    private String email;
+
+    @ApiModelProperty(value = "管理员电话号码")
+    private String tel;
+
+    @ApiModelProperty(value = "是否启用管理员账户")
+    private Boolean enabled;
+
+    @ApiModelProperty(value = "管理员账户创建时间")
+    private LocalDateTime createTime;
+
+    @ApiModelProperty(value = "管理员账户更新时间")
+    private LocalDateTime updateTime;
+
+    @ApiModelProperty(value = "管理员权限")
+    private String authority;
+
+    @ApiModelProperty(value = "管理员认证信息")
+    private String auths;
+
+    @ApiModelProperty(value = "操作人ID")
+    private Integer operatorId;
+
+
+
+
+}

+ 49 - 0
src/main/java/com/om/entity/vo/AdminLoginVO.java

@@ -0,0 +1,49 @@
+package com.om.entity.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.time.LocalDateTime;
+
+@Data
+@NoArgsConstructor
+public class AdminLoginVO {
+
+    @ApiModelProperty(value = "管理员ID")
+    private Integer id;
+
+    @ApiModelProperty(value = "管理员用户名")
+    private String username;
+
+    @ApiModelProperty(value = "管理员密码")
+    private String password;
+
+    @ApiModelProperty(value = "管理员真实姓名")
+    private String realName;
+
+    @ApiModelProperty(value = "管理员电子邮件")
+    private String email;
+
+    @ApiModelProperty(value = "管理员电话号码")
+    private String tel;
+
+    @ApiModelProperty(value = "是否启用管理员账户")
+    private Boolean enabled;
+
+    @ApiModelProperty(value = "管理员账户创建时间")
+    private LocalDateTime createTime;
+
+    @ApiModelProperty(value = "管理员账户更新时间")
+    private LocalDateTime updateTime;
+
+    @ApiModelProperty(value = "管理员权限")
+    private String authority;
+
+    @ApiModelProperty(value = "管理员认证信息")
+    private String auths;
+
+    @ApiModelProperty(value = "token")
+    private String loginToken;
+
+}

+ 19 - 0
src/main/java/com/om/exception/BizException.java

@@ -0,0 +1,19 @@
+package com.om.exception;
+
+import lombok.Data;
+
+/**
+ * 业务异常类
+ *需要继承运行时异常RuntimeException
+ */
+@Data
+public class BizException extends RuntimeException {
+    private final Integer code = 500;
+    private String message;
+
+    public BizException(String message) {
+        this.message = message;
+    }
+
+
+}

+ 18 - 0
src/main/java/com/om/exception/CustomerAuthenticationException.java

@@ -0,0 +1,18 @@
+package com.om.exception;
+
+
+import lombok.Data;
+
+/**
+ * 自定义验证异常类
+ */
+@Data
+public class CustomerAuthenticationException extends RuntimeException{
+
+    private String message;
+
+    public CustomerAuthenticationException(String message){
+        super(message);
+        this.message = message;
+    }
+}

+ 62 - 0
src/main/java/com/om/handler/GlobalExceptionHandler.java

@@ -0,0 +1,62 @@
+package com.om.handler;
+
+
+import com.om.exception.BizException;
+import com.om.exception.CustomerAuthenticationException;
+import com.om.utils.Result;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.core.Ordered;
+import org.springframework.core.annotation.Order;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+/**
+ * 统一异常处理
+ *
+ * ControllerAdvice注解的含义是当异常抛到controller层时会拦截下来
+ */
+@ControllerAdvice
+@Slf4j
+public class GlobalExceptionHandler {
+
+    /**
+     * 使用ExceptionHandler注解声明处理Exception异常
+     *
+     * @param e e
+     *
+     */
+    @ResponseBody
+    @ExceptionHandler(Exception.class)
+    public Result exception(Exception e) {
+        // 记录异常信息到日志
+        log.error("Exception caught: ", e);
+        // 返回错误格式信息
+        return Result.error();
+    }
+
+
+    @ResponseBody
+    @Order(Ordered.HIGHEST_PRECEDENCE)
+    @ExceptionHandler(BizException.class)
+    public Result BizException(BizException e) {
+        // 记录异常信息到日志
+        log.error("Exception caught: ", e);
+        // 返回错误格式信息
+        return Result.error().message(e.getMessage());
+    }
+
+    @ResponseBody
+    @Order(Ordered.HIGHEST_PRECEDENCE)
+    @ExceptionHandler(CustomerAuthenticationException.class)
+    public Result CustomerAuthenticationException(CustomerAuthenticationException e) {
+        // 记录异常信息到日志
+        log.error("Exception caught: ", e);
+        // 返回错误格式信息
+        return Result.error().message(e.getMessage());
+    }
+
+
+
+
+}

+ 114 - 0
src/main/java/com/om/interceptor/JwtTokenAdminInterceptor.java

@@ -0,0 +1,114 @@
+package com.om.interceptor;
+
+
+import com.alibaba.fastjson.JSON;
+import com.om.constant.RedisConstant;
+import com.om.exception.CustomerAuthenticationException;
+import com.om.utils.AdminContext;
+import com.om.utils.JwtUtils;
+import com.om.utils.Result;
+
+import lombok.extern.slf4j.Slf4j;
+
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * jwt令牌校验的拦截器
+ */
+@Component
+@Slf4j
+public class JwtTokenAdminInterceptor implements HandlerInterceptor {
+
+    @Resource
+    private JwtUtils jwtUtils;
+
+    @Resource
+    private RedisTemplate redisTemplate;
+
+    /**
+     * 校验jwt
+     *
+     * @param request
+     * @param response
+     * @param handler
+     * @return
+     * @throws Exception
+     */
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        //判断当前拦截到的是Controller的方法还是其他资源
+        if (!(handler instanceof HandlerMethod)) {
+            //当前拦截到的不是动态方法,直接放行
+            return true;
+        }
+
+        //2、校验令牌
+        try {
+             this.validateToken(request);
+        } catch (CustomerAuthenticationException ex) {
+
+            response.setContentType("application/json;charset=UTF-8");  // 设置字符集为 UTF-8
+            String message = ex.getMessage();
+            response.setStatus(401);
+            response.getWriter().write(JSON.toJSONString(Result.error().message(message).result(401)));
+            return false;
+        }
+
+        return true;
+    }
+
+
+    /**
+     * 验证token信息
+     */
+    private void validateToken(HttpServletRequest request) {
+
+        //从headers头部获取token信息
+        String token = request.getHeader("token");
+
+        //如果请求头部中没有携带token  则从请求的参数中中获取token
+        if (StringUtils.isEmpty(token)) {
+            token = request.getParameter("token");        //从参数中获取
+
+        }
+
+        //如果请求参数中也没有携带token信息  则抛出异常
+        if (StringUtils.isEmpty(token)) {
+            throw new CustomerAuthenticationException("token不存在");
+        }
+
+        //从token中获取管理员id
+        Integer aId = jwtUtils.getIdFromToken(token);
+        //判断 管理员id 是否为空
+        if (StringUtils.isEmpty(aId)) {
+            throw new CustomerAuthenticationException("token解析失败");
+        }
+
+        //判断redis中是否存在token信息
+
+        String tokenKey = RedisConstant.ADMIN_TOKEN_PREFIX +aId;
+        String redisToken = (String) redisTemplate.opsForValue().get(tokenKey);
+
+        //判断redis中是否存在token信息  如果为空 则表示token已经失效、
+        if (StringUtils.isEmpty(redisToken)) {
+            throw new CustomerAuthenticationException("token已过期");
+
+        }
+
+        //如果token和redis中的token不一致 则验证失败
+        if (!token.equals(redisToken)) {
+            throw new CustomerAuthenticationException("token验证失败");
+        }
+        //获取管理员id
+        AdminContext.setAdminId(aId);
+    }
+}
+

+ 111 - 0
src/main/java/com/om/interceptor/JwtTokenUserInterceptor.java

@@ -0,0 +1,111 @@
+package com.om.interceptor;
+
+
+import com.alibaba.fastjson.JSON;
+import com.om.constant.RedisConstant;
+import com.om.exception.CustomerAuthenticationException;
+import com.om.utils.AdminContext;
+import com.om.utils.JwtUtils;
+import com.om.utils.Result;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * jwt令牌校验的拦截器
+ */
+@Component
+@Slf4j
+public class JwtTokenUserInterceptor implements HandlerInterceptor {
+
+    @Resource
+    private JwtUtils jwtUtils;
+
+    @Resource
+    private RedisTemplate redisTemplate;
+
+    /**
+     * 校验jwt
+     *
+     * @param request
+     * @param response
+     * @param handler
+     * @return
+     * @throws Exception
+     */
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        //判断当前拦截到的是Controller的方法还是其他资源
+        if (!(handler instanceof HandlerMethod)) {
+            //当前拦截到的不是动态方法,直接放行
+            return true;
+        }
+
+        //2、校验令牌
+        try {
+             this.validateToken(request);
+        } catch (CustomerAuthenticationException ex) {
+
+            response.setContentType("application/json;charset=UTF-8");  // 设置字符集为 UTF-8
+            String message = ex.getMessage();
+            response.setStatus(401);
+            response.getWriter().write(JSON.toJSONString(Result.error().message(message).result(401)));
+            return false;
+        }
+
+        return true;
+    }
+
+
+    /**
+     * 验证token信息
+     */
+    private void validateToken(HttpServletRequest request) {
+
+        //从headers头部获取token信息
+        String token = request.getHeader("token");
+
+        //如果请求头部中没有携带token  则从请求的参数中中获取token
+        if (StringUtils.isEmpty(token)) {
+            token = request.getParameter("token");        //从参数中获取
+
+        }
+
+        //如果请求参数中也没有携带token信息  则抛出异常
+        if (StringUtils.isEmpty(token)) {
+            throw new CustomerAuthenticationException("token不存在");
+        }
+
+        //从token中获取管理员id
+        Integer aId = jwtUtils.getIdFromToken(token);
+        //判断 管理员id 是否为空
+        if (StringUtils.isEmpty(aId)) {
+            throw new CustomerAuthenticationException("token解析失败");
+        }
+
+        //判断redis中是否存在token信息
+
+        String tokenKey = RedisConstant.ADMIN_TOKEN_PREFIX +aId;
+        String redisToken = (String) redisTemplate.opsForValue().get(tokenKey);
+
+        //判断redis中是否存在token信息  如果为空 则表示token已经失效、
+        if (StringUtils.isEmpty(redisToken)) {
+            throw new CustomerAuthenticationException("token已过期");
+
+        }
+
+        //如果token和redis中的token不一致 则验证失败
+        if (!token.equals(redisToken)) {
+            throw new CustomerAuthenticationException("token验证失败");
+        }
+        //获取管理员id
+        AdminContext.setAdminId(aId);
+    }
+}
+

+ 16 - 0
src/main/java/com/om/mapper/AdminMapper.java

@@ -0,0 +1,16 @@
+package com.om.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.om.entity.po.Admin;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author bmmx
+ * @since 2024-01-26
+ */
+public interface AdminMapper extends BaseMapper<Admin> {
+
+}

+ 18 - 0
src/main/java/com/om/service/IAdminService.java

@@ -0,0 +1,18 @@
+package com.om.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.om.entity.po.Admin;
+import com.om.utils.Result;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author bmmx
+ * @since 2024-01-26
+ */
+public interface IAdminService extends IService<Admin> {
+
+    Result login(String username, String password);
+}

+ 90 - 0
src/main/java/com/om/service/impl/AdminServiceImpl.java

@@ -0,0 +1,90 @@
+package com.om.service.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.om.constant.RedisConstant;
+import com.om.entity.po.Admin;
+import com.om.entity.vo.AdminLoginVO;
+import com.om.mapper.AdminMapper;
+import com.om.service.IAdminService;
+import com.om.utils.JwtUtils;
+import com.om.utils.Result;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.data.redis.core.RedisTemplate;
+
+import org.springframework.stereotype.Service;
+import org.springframework.util.DigestUtils;
+
+import javax.annotation.Resource;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author bmmx
+ * @since 2024-01-26
+ */
+@Service
+public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements IAdminService {
+
+    @Resource
+    private JwtUtils jwtUtils;
+
+    @Resource
+    private RedisTemplate redisTemplate;
+
+
+    @Override
+    public Result login(String username, String password) {
+        if (StringUtils.isBlank(username)){
+            return Result.error().message("用户名为空");
+        }
+        if (StringUtils.isBlank(password)){
+           return Result.error().message("密码为空");
+        }
+
+        //根据username 查询数据库
+        Admin admin = this.lambdaQuery()
+                .eq(Admin::getUsername, username)
+                .one();
+        //判断是否存在
+        if (BeanUtil.isEmpty(admin)){
+            return Result.error().message("该用户不存在");
+        }
+        //密码加密
+         password = DigestUtils.md5DigestAsHex(password.getBytes());
+        //判断密码是否正确
+        if (!StringUtils.equals(password,admin.getPassword())){
+            return Result.error().message("密码错误");
+        }
+
+        //判断管理员状态
+        if (!admin.getEnabled()){
+            return Result.error().message("该管理员已被禁用");
+        }
+        //封装vo返回
+        AdminLoginVO adminLoginVO = BeanUtil.copyProperties(admin, AdminLoginVO.class);
+        //生成token
+        Map<String, Object> claims = new HashMap<>();
+        claims.put("a_id",admin.getId());
+        String token = jwtUtils.generateToken(claims);
+        //把token存入到redis中
+        String key = RedisConstant.ADMIN_TOKEN_PREFIX + admin.getId();
+        redisTemplate.opsForValue().set(key,token,RedisConstant.ADMIN_TOKEN_TTL, TimeUnit.SECONDS);
+        adminLoginVO.setLoginToken(token);
+
+        return Result.ok(adminLoginVO);
+    }
+
+
+
+}

+ 29 - 0
src/main/java/com/om/utils/AdminContext.java

@@ -0,0 +1,29 @@
+package com.om.utils;
+
+public class AdminContext {
+    private static final ThreadLocal<Integer> TL = new ThreadLocal<>();
+
+    /**
+     * 保存管理员信息
+     * @param adminId 用户id
+     */
+    public static void setAdminId(Integer adminId){
+        TL.set(adminId);
+    }
+
+    /**
+     * 获取管理员
+     * @return 用户id
+     */
+    public static Integer getAdminId(){
+        return TL.get();
+    }
+
+    /**
+     * 移除管理员信息
+     */
+    public static void removeAdmin(){
+        TL.remove();
+    }
+}
+

+ 110 - 0
src/main/java/com/om/utils/JwtUtils.java

@@ -0,0 +1,110 @@
+package com.om.utils;
+
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+import org.springframework.stereotype.Component;
+import java.util.Date;
+import java.util.Map;
+
+@Data
+@ConfigurationProperties(prefix = "jwt")
+@Component
+public class JwtUtils {
+    //密钥
+    private String secret;
+
+    // 过期时间 毫秒
+    private Long expiration;
+
+
+    /**
+     * 从数据声明生成令牌
+     *
+     * @param claims 数据声明
+     * @return 令牌
+     */
+    public String generateToken(Map<String, Object> claims) {
+        Date expirationDate = new Date(System.currentTimeMillis() + expiration);
+        return Jwts.builder().setClaims(claims).setExpiration(expirationDate).signWith(SignatureAlgorithm.HS512, secret).compact();
+    }
+
+    /**
+     * 从令牌中获取数据声明
+     *
+     * @param token 令牌
+     * @return 数据声明
+     */
+    public Claims getClaimsFromToken(String token) {
+        Claims claims;
+        try {
+            claims = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
+        } catch (Exception e) {
+            claims = null;
+        }
+        return claims;
+    }
+
+    /**
+     * 从令牌中获取id
+     *
+     * @param token 令牌
+     * @return id
+     */
+    public Integer getIdFromToken(String token) {
+        Integer uId;
+        try {
+            Claims claims = getClaimsFromToken(token);
+            uId =  claims.get("a_id", Integer.class);
+        } catch (Exception e) {
+            uId = null;
+        }
+        return uId;
+    }
+
+    /**
+     * 判断令牌是否过期
+     *
+     * @param token 令牌
+     * @return 是否过期
+     */
+    public Boolean isTokenExpired(String token) {
+        Claims claims = getClaimsFromToken(token);
+        Date expiration = claims.getExpiration();
+        return expiration.before(new Date());
+    }
+
+    /**
+     * 刷新令牌
+     *
+     * @param token 原令牌
+     * @return 新令牌
+     */
+    public String refreshToken(String token) {
+        String refreshedToken;
+        try {
+            Claims claims = getClaimsFromToken(token);
+            claims.put(Claims.ISSUED_AT, new Date());
+            refreshedToken = generateToken(claims);
+        } catch (Exception e) {
+            refreshedToken = null;
+        }
+        return refreshedToken;
+    }
+
+    /**
+     * 验证令牌
+     *
+     * @param token       令牌
+     * @param id id
+     * @return 是否有效
+     */
+    public Boolean validateToken(String token, Integer id) {
+        Integer uId = getIdFromToken(token);
+        return (uId.equals(id) && !isTokenExpired(token));
+    }
+}
+

+ 70 - 0
src/main/java/com/om/utils/Result.java

@@ -0,0 +1,70 @@
+package com.om.utils;
+
+import lombok.Data;
+
+/**
+ * 全局统一返回结果类
+ */
+@Data
+public class Result<T> {
+    private Integer result;//状态码
+    private String message;//返回消息
+    private T data;//返回数据
+    /**
+     * 私有化构造方法,禁止在其它类创建对象
+     */
+    private Result(){}
+    /**
+     * 成功执行,不返回数据
+     * @return
+     */
+    public static<T> Result<T> ok(){
+        Result<T> result = new Result<T>();
+        result.setResult(ResultCode.SUCCESS);
+        result.setMessage("执行成功");
+        return result;
+    }
+    /**
+     * 成功执行,并返回数据
+     * @param data
+     * @param <T>
+     * @return
+     */
+    public static<T> Result<T> ok(T data){
+        Result<T> result = new Result<T>();
+        result.setResult(ResultCode.SUCCESS);
+        result.setMessage("执行成功");
+        result.setData(data);
+        return result;
+    }
+    /**
+     * 失败
+     * @return
+     */
+    public static<T> Result<T> error(){
+        Result<T> result = new Result<T>();
+        result.setResult(ResultCode.ERROR);
+        result.setMessage("执行失败");
+        return result;
+    }
+
+    /**
+     * 设置状态码
+     * @param code
+     * @return
+     */
+    public Result<T> result(Integer code){
+        this.setResult(code);
+        return this;
+    }
+    /**
+     * 设置返回消息
+     * @param message
+     * @return
+     */
+    public Result<T> message(String message){
+        this.setMessage(message);
+        return this;
+    }
+
+}

+ 21 - 0
src/main/java/com/om/utils/ResultCode.java

@@ -0,0 +1,21 @@
+package com.om.utils;
+
+public class ResultCode {
+    /**
+     * 成功状态码
+     */
+    public static final Integer SUCCESS = 200;
+    /**
+     * 失败状态码
+     */
+    public static final Integer ERROR = 400;
+
+    /**
+     * 未授权状态码
+     */
+    public static final int NO_AUTH = 401;
+    /**
+     * 访问受限,授权过期状态码
+     */
+    public static final int AUTH_EX = 403;
+}

+ 34 - 0
src/main/resources/application-dev.yml

@@ -0,0 +1,34 @@
+server:
+  port: 8888
+
+mybatis-plus:
+  configuration:
+    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 查看日志
+  mapper-locations: classpath:mapper/*.xml		#mapper的位置
+spring:
+  datasource:
+    driver-class-name: com.mysql.cj.jdbc.Driver
+    url: jdbc:mysql://47.113.197.148:33306/test?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true
+    username: root
+    password: om1020
+  redis:
+    host: 47.113.197.148
+    password: om1020
+    port: 6379
+    database: 1
+
+  jackson:
+    date-format: yyyy-MM-dd HH:mm:ss
+    time-zone: GMT+8
+  mvc:
+    pathmatch:
+      matching-strategy: ant_path_matcher
+
+#jwt配置
+#密钥
+jwt:
+  secret: opera
+  expiration: 7200000  #过期时间2小时
+
+
+

+ 6 - 0
src/main/resources/application.yml

@@ -0,0 +1,6 @@
+spring:
+  application:
+    name: OperationSystem
+  profiles:
+    active: dev
+

+ 5 - 0
src/main/resources/mapper/AdminMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.om.mapper.AdminMapper">
+
+</mapper>