提交 e8fd70c2 编写于 作者: jiachengren's avatar jiachengren

add jwt

上级 cdfab1ab
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="4baf6bea-a7f6-4038-bf36-4d5fae1b64e6" name="Default Changelist" comment="" />
<list default="true" id="4baf6bea-a7f6-4038-bf36-4d5fae1b64e6" name="Default Changelist" comment="">
<change afterPath="$PROJECT_DIR$/.idea/vcs.xml" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/com/jmu/shiro_demo/config/IntercepetorConfig.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/com/jmu/shiro_demo/intercepetor/JWTIntercepetor.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/java/com/jmu/shiro_demo/utils/JWTutil.java" afterDir="false" />
<change afterPath="$PROJECT_DIR$/src/main/resources/static/js/jquery-3.6.0.slim.min.js" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/pom.xml" beforeDir="false" afterPath="$PROJECT_DIR$/pom.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/shiro_demo.iml" beforeDir="false" afterPath="$PROJECT_DIR$/shiro_demo.iml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/jmu/shiro_demo/controller/RouteController.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/jmu/shiro_demo/controller/RouteController.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/jmu/shiro_demo/controller/UserController.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/jmu/shiro_demo/controller/UserController.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/jmu/shiro_demo/entity/RolePermission.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/jmu/shiro_demo/entity/RolePermission.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/jmu/shiro_demo/service/UserService.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/jmu/shiro_demo/service/UserService.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/jmu/shiro_demo/service/impl/UserServiceImpl.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/jmu/shiro_demo/service/impl/UserServiceImpl.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/java/com/jmu/shiro_demo/shiro/ShiroConfig.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/java/com/jmu/shiro_demo/shiro/ShiroConfig.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/resources/application.properties" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/resources/application.properties" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/resources/templates/index.html" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/resources/templates/index.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/main/resources/templates/login.html" beforeDir="false" afterPath="$PROJECT_DIR$/src/main/resources/templates/login.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/test/java/com/jmu/shiro_demo/ShiroDemoApplicationTests.java" beforeDir="false" afterPath="$PROJECT_DIR$/src/test/java/com/jmu/shiro_demo/ShiroDemoApplicationTests.java" afterDir="false" />
<change beforePath="$PROJECT_DIR$/target/classes/application.properties" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/application.properties" afterDir="false" />
<change beforePath="$PROJECT_DIR$/target/classes/com/jmu/shiro_demo/controller/RouteController.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/jmu/shiro_demo/controller/RouteController.class" afterDir="false" />
<change beforePath="$PROJECT_DIR$/target/classes/com/jmu/shiro_demo/controller/UserController.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/jmu/shiro_demo/controller/UserController.class" afterDir="false" />
<change beforePath="$PROJECT_DIR$/target/classes/com/jmu/shiro_demo/entity/RolePermission.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/jmu/shiro_demo/entity/RolePermission.class" afterDir="false" />
<change beforePath="$PROJECT_DIR$/target/classes/com/jmu/shiro_demo/service/UserService.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/jmu/shiro_demo/service/UserService.class" afterDir="false" />
<change beforePath="$PROJECT_DIR$/target/classes/com/jmu/shiro_demo/service/impl/UserServiceImpl.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/jmu/shiro_demo/service/impl/UserServiceImpl.class" afterDir="false" />
<change beforePath="$PROJECT_DIR$/target/classes/com/jmu/shiro_demo/shiro/RedisCache.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/jmu/shiro_demo/shiro/RedisCache.class" afterDir="false" />
<change beforePath="$PROJECT_DIR$/target/classes/com/jmu/shiro_demo/shiro/ShiroConfig.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/jmu/shiro_demo/shiro/ShiroConfig.class" afterDir="false" />
<change beforePath="$PROJECT_DIR$/target/classes/com/jmu/shiro_demo/test/Test.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/com/jmu/shiro_demo/test/Test.class" afterDir="false" />
<change beforePath="$PROJECT_DIR$/target/classes/mapper/RoleMapper.xml" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/mapper/RoleMapper.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/target/classes/mapper/UserMapper.xml" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/mapper/UserMapper.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/target/classes/templates/index.html" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/templates/index.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/target/classes/templates/login.html" beforeDir="false" afterPath="$PROJECT_DIR$/target/classes/templates/login.html" afterDir="false" />
<change beforePath="$PROJECT_DIR$/target/test-classes/com/jmu/shiro_demo/ShiroDemoApplicationTests.class" beforeDir="false" afterPath="$PROJECT_DIR$/target/test-classes/com/jmu/shiro_demo/ShiroDemoApplicationTests.class" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
......@@ -15,6 +48,9 @@
</list>
</option>
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="MavenImportPreferences">
<option name="generalSettings">
<MavenGeneralSettings>
......@@ -29,17 +65,22 @@
</option>
</component>
<component name="ProjectId" id="1rQj5KzVv0eN78gXgiRBc0mj1JB" />
<component name="ProjectLevelVcsManager" settingsEditedManually="true">
<ConfirmationsSetting value="2" id="Add" />
</component>
<component name="ProjectViewState">
<option name="showExcludedFiles" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">
<property name="ASKED_ADD_EXTERNAL_FILES" value="true" />
<property name="DefaultHtmlFileTemplate" value="HTML File" />
<property name="RequestMappingsPanelOrder0" value="0" />
<property name="RequestMappingsPanelOrder1" value="1" />
<property name="RequestMappingsPanelWidth0" value="75" />
<property name="RequestMappingsPanelWidth1" value="75" />
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
<property name="SHARE_PROJECT_CONFIGURATION_FILES" value="true" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="aspect.path.notification.shown" value="true" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/src/main/java/com/jmu/shiro_demo" />
......@@ -49,12 +90,13 @@
<property name="settings.editor.selected.configurable" value="preferences.pluginManager" />
</component>
<component name="RecentsManager">
<key name="MoveFile.RECENT_KEYS">
<recent name="F:\shiro_demo\src\main\resources\mapper" />
</key>
<key name="CopyFile.RECENT_KEYS">
<recent name="F:\shiro_demo\src\main\java\com\jmu\shiro_demo" />
</key>
<key name="MoveFile.RECENT_KEYS">
<recent name="F:\shiro_demo\src\main\resources\static\js" />
<recent name="F:\shiro_demo\src\main\resources\mapper" />
</key>
</component>
<component name="RunManager" selected="Spring Boot.ShiroDemoApplication">
<configuration name="MpGenerator" type="Application" factoryName="Application" temporary="true" nameIsGenerated="true">
......@@ -83,6 +125,38 @@
<option name="Make" enabled="true" />
</method>
</configuration>
<configuration name="ShiroDemoApplicationTests.contextLoads" type="JUnit" factoryName="JUnit" temporary="true" nameIsGenerated="true">
<module name="shiro_demo" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="com.jmu.shiro_demo.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<option name="PACKAGE_NAME" value="com.jmu.shiro_demo" />
<option name="MAIN_CLASS_NAME" value="com.jmu.shiro_demo.ShiroDemoApplicationTests" />
<option name="METHOD_NAME" value="contextLoads" />
<option name="TEST_OBJECT" value="method" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
<configuration name="ShiroDemoApplicationTests.test" type="JUnit" factoryName="JUnit" temporary="true" nameIsGenerated="true">
<module name="shiro_demo" />
<extension name="coverage">
<pattern>
<option name="PATTERN" value="com.jmu.shiro_demo.*" />
<option name="ENABLED" value="true" />
</pattern>
</extension>
<option name="PACKAGE_NAME" value="com.jmu.shiro_demo" />
<option name="MAIN_CLASS_NAME" value="com.jmu.shiro_demo.ShiroDemoApplicationTests" />
<option name="METHOD_NAME" value="test" />
<option name="TEST_OBJECT" value="method" />
<method v="2">
<option name="Make" enabled="true" />
</method>
</configuration>
<configuration name="ShiroDemoApplication" type="SpringBootApplicationConfigurationType" factoryName="Spring Boot">
<module name="shiro_demo" />
<option name="SPRING_BOOT_MAIN_CLASS" value="com.jmu.shiro_demo.ShiroDemoApplication" />
......@@ -92,6 +166,8 @@
</configuration>
<recent_temporary>
<list>
<item itemvalue="JUnit.ShiroDemoApplicationTests.contextLoads" />
<item itemvalue="JUnit.ShiroDemoApplicationTests.test" />
<item itemvalue="Application.Test" />
<item itemvalue="Application.MpGenerator" />
</list>
......@@ -128,58 +204,64 @@
<workItem from="1619070187162" duration="2670000" />
<workItem from="1619085271614" duration="1714000" />
<workItem from="1619154044773" duration="7558000" />
<workItem from="1619172156911" duration="1887000" />
<workItem from="1619172156911" duration="3161000" />
<workItem from="1619192742568" duration="398000" />
<workItem from="1619241892155" duration="4466000" />
<workItem from="1619263177714" duration="9312000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="1" />
</component>
<component name="VcsManagerConfiguration">
<option name="ADD_EXTERNAL_FILES_SILENTLY" value="true" />
</component>
<component name="WindowStateProjectService">
<state x="515" y="215" key="#com.intellij.fileTypes.FileTypeChooser" timestamp="1618915195121">
<screen x="0" y="0" width="1536" height="824" />
</state>
<state x="515" y="215" key="#com.intellij.fileTypes.FileTypeChooser/0.0.1536.824@0.0.1536.824" timestamp="1618915195121" />
<state x="211" y="146" width="495" height="579" key="#com.intellij.ide.util.MemberChooser" timestamp="1619155701161">
<state x="211" y="146" width="495" height="579" key="#com.intellij.ide.util.MemberChooser" timestamp="1619246681798">
<screen x="0" y="0" width="1536" height="824" />
</state>
<state x="211" y="146" width="495" height="579" key="#com.intellij.ide.util.MemberChooser/0.0.1536.824@0.0.1536.824" timestamp="1619155701161" />
<state x="211" y="146" width="495" height="579" key="#com.intellij.ide.util.MemberChooser/0.0.1536.824@0.0.1536.824" timestamp="1619246681798" />
<state x="499" y="159" key="#com.intellij.refactoring.safeDelete.UnsafeUsagesDialog" timestamp="1619069602052">
<screen x="0" y="0" width="1536" height="824" />
</state>
<state x="499" y="159" key="#com.intellij.refactoring.safeDelete.UnsafeUsagesDialog/0.0.1536.824@0.0.1536.824" timestamp="1619069602052" />
<state width="1493" height="207" key="GridCell.Tab.0.bottom" timestamp="1619171854703">
<state width="1493" height="246" key="GridCell.Tab.0.bottom" timestamp="1619271094318">
<screen x="0" y="0" width="1536" height="824" />
</state>
<state width="1493" height="207" key="GridCell.Tab.0.bottom/0.0.1536.824@0.0.1536.824" timestamp="1619171854703" />
<state width="1493" height="207" key="GridCell.Tab.0.center" timestamp="1619171854703">
<state width="1493" height="246" key="GridCell.Tab.0.bottom/0.0.1536.824@0.0.1536.824" timestamp="1619271094318" />
<state width="1493" height="246" key="GridCell.Tab.0.center" timestamp="1619271094318">
<screen x="0" y="0" width="1536" height="824" />
</state>
<state width="1493" height="207" key="GridCell.Tab.0.center/0.0.1536.824@0.0.1536.824" timestamp="1619171854703" />
<state width="1493" height="207" key="GridCell.Tab.0.left" timestamp="1619171854703">
<state width="1493" height="246" key="GridCell.Tab.0.center/0.0.1536.824@0.0.1536.824" timestamp="1619271094318" />
<state width="1493" height="246" key="GridCell.Tab.0.left" timestamp="1619271094318">
<screen x="0" y="0" width="1536" height="824" />
</state>
<state width="1493" height="207" key="GridCell.Tab.0.left/0.0.1536.824@0.0.1536.824" timestamp="1619171854703" />
<state width="1493" height="207" key="GridCell.Tab.0.right" timestamp="1619171854703">
<state width="1493" height="246" key="GridCell.Tab.0.left/0.0.1536.824@0.0.1536.824" timestamp="1619271094318" />
<state width="1493" height="246" key="GridCell.Tab.0.right" timestamp="1619271094318">
<screen x="0" y="0" width="1536" height="824" />
</state>
<state width="1493" height="207" key="GridCell.Tab.0.right/0.0.1536.824@0.0.1536.824" timestamp="1619171854703" />
<state width="1493" height="207" key="GridCell.Tab.1.bottom" timestamp="1619171854703">
<state width="1493" height="246" key="GridCell.Tab.0.right/0.0.1536.824@0.0.1536.824" timestamp="1619271094318" />
<state width="1493" height="246" key="GridCell.Tab.1.bottom" timestamp="1619271094319">
<screen x="0" y="0" width="1536" height="824" />
</state>
<state width="1493" height="207" key="GridCell.Tab.1.bottom/0.0.1536.824@0.0.1536.824" timestamp="1619171854703" />
<state width="1493" height="207" key="GridCell.Tab.1.center" timestamp="1619171854703">
<state width="1493" height="246" key="GridCell.Tab.1.bottom/0.0.1536.824@0.0.1536.824" timestamp="1619271094319" />
<state width="1493" height="246" key="GridCell.Tab.1.center" timestamp="1619271094318">
<screen x="0" y="0" width="1536" height="824" />
</state>
<state width="1493" height="207" key="GridCell.Tab.1.center/0.0.1536.824@0.0.1536.824" timestamp="1619171854703" />
<state width="1493" height="207" key="GridCell.Tab.1.left" timestamp="1619171854703">
<state width="1493" height="246" key="GridCell.Tab.1.center/0.0.1536.824@0.0.1536.824" timestamp="1619271094318" />
<state width="1493" height="246" key="GridCell.Tab.1.left" timestamp="1619271094318">
<screen x="0" y="0" width="1536" height="824" />
</state>
<state width="1493" height="207" key="GridCell.Tab.1.left/0.0.1536.824@0.0.1536.824" timestamp="1619171854703" />
<state width="1493" height="207" key="GridCell.Tab.1.right" timestamp="1619171854703">
<state width="1493" height="246" key="GridCell.Tab.1.left/0.0.1536.824@0.0.1536.824" timestamp="1619271094318" />
<state width="1493" height="246" key="GridCell.Tab.1.right" timestamp="1619271094319">
<screen x="0" y="0" width="1536" height="824" />
</state>
<state width="1493" height="207" key="GridCell.Tab.1.right/0.0.1536.824@0.0.1536.824" timestamp="1619171854703" />
<state width="1493" height="246" key="GridCell.Tab.1.right/0.0.1536.824@0.0.1536.824" timestamp="1619271094319" />
<state x="299" y="68" key="Maven.ArtifactSearchDialog" timestamp="1618916736347">
<screen x="0" y="0" width="1536" height="824" />
</state>
......@@ -188,17 +270,17 @@
<screen x="0" y="0" width="1536" height="824" />
</state>
<state x="270" y="55" key="SettingsEditor/0.0.1536.824@0.0.1536.824" timestamp="1619060693037" />
<state x="449" y="237" key="com.intellij.ide.util.TipDialog" timestamp="1619172176387">
<state x="449" y="237" key="com.intellij.ide.util.TipDialog" timestamp="1619263177788">
<screen x="0" y="0" width="1536" height="824" />
</state>
<state x="449" y="237" key="com.intellij.ide.util.TipDialog/0.0.1536.824@0.0.1536.824" timestamp="1619172176387" />
<state x="449" y="237" key="com.intellij.ide.util.TipDialog/0.0.1536.824@0.0.1536.824" timestamp="1619263177788" />
<state x="511" y="30" key="refactoring.ChangeSignatureDialog" timestamp="1619069021267">
<screen x="0" y="0" width="1536" height="824" />
</state>
<state x="511" y="30" key="refactoring.ChangeSignatureDialog/0.0.1536.824@0.0.1536.824" timestamp="1619069021267" />
<state x="431" y="145" width="672" height="678" key="search.everywhere.popup" timestamp="1619160982166">
<state x="431" y="145" width="672" height="678" key="search.everywhere.popup" timestamp="1619273348221">
<screen x="0" y="0" width="1536" height="824" />
</state>
<state x="431" y="145" width="672" height="678" key="search.everywhere.popup/0.0.1536.824@0.0.1536.824" timestamp="1619160982166" />
<state x="431" y="145" width="672" height="678" key="search.everywhere.popup/0.0.1536.824@0.0.1536.824" timestamp="1619273348221" />
</component>
</project>
\ No newline at end of file
......@@ -16,6 +16,13 @@
</properties>
<dependencies>
<!--jwt-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.15.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
......
......@@ -25,6 +25,10 @@
</content>
<orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Maven: com.auth0:java-jwt:3.15.0" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.11.3" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.11.3" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.11.3" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-data-redis:2.3.7.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter:2.3.7.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-logging:2.3.7.RELEASE" level="project" />
......@@ -82,9 +86,6 @@
<orderEntry type="library" name="Maven: org.thymeleaf.extras:thymeleaf-extras-java8time:3.0.4.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-web:2.3.7.RELEASE" level="project" />
<orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-json:2.3.7.RELEASE" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.11.3" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.11.3" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.11.3" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.11.3" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.11.3" level="project" />
<orderEntry type="library" name="Maven: com.fasterxml.jackson.module:jackson-module-parameter-names:2.11.3" level="project" />
......
package com.jmu.shiro_demo.config;
import com.jmu.shiro_demo.intercepetor.JWTIntercepetor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class IntercepetorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new JWTIntercepetor())
.addPathPatterns("/**") //拦截所有请求
.excludePathPatterns("/logout","/js/**","/index","/getAuthCode","/login","/toLogin","/user/**"); // 放行 登陆请求 下面的所有请求
}
}
......@@ -8,6 +8,7 @@ import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
......@@ -33,18 +34,21 @@ public class RouteController {
}
@GetMapping("/toUserAdd")
@ResponseBody
@RequiresPermissions("user:add")
public String toUserAdd() {
return "user/add";
}
@GetMapping("/toUserUpdate")
@ResponseBody
@RequiresPermissions("user:update")
public String toUserUpdate() {
return "user/update";
}
@GetMapping("/toUserDelete")
@ResponseBody
@RequiresPermissions("user:delete")
public String toUserDelete() {
return "user/delete";
......@@ -73,8 +77,6 @@ public class RouteController {
} catch (IOException e) {
e.printStackTrace();
}
}
}
......@@ -9,12 +9,12 @@ import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;
/**
* <p>
......@@ -31,10 +31,29 @@ public class UserController {
@Autowired
private UserService userService;
@GetMapping("/add")
public String toUserAdd(){
return "user/add";
}
@GetMapping("/update")
public String toUserUpdate(){
return "user/update";
}
@GetMapping("/delete")
public String toUserDelete(){
return "user/delete";
}
@PostMapping("/login")
public String login(String username, String password, String code,
HttpSession session,Model model) {
return userService.login(username,password,code,session,model);
@ResponseBody
public Map<String,String> login(String username, String password, String code,
HttpSession session, HttpServletResponse response, Model model) {
Map<String,String> map = new HashMap<String, String>();
map.put("url",userService.login(username,password,code,session,response,model));
map.put("token",response.getHeader("token"));
return map;
}
}
package com.jmu.shiro_demo.entity;
import java.io.Serializable;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* <p>
*
*
* </p>
*
* @author ${author}
......
package com.jmu.shiro_demo.intercepetor;
import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jmu.shiro_demo.utils.JWTutil;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
public class JWTIntercepetor implements HandlerInterceptor {
private final String TOKEN_NAME = "token";
//JWT拦截器,所有请求都被这个拦截器拦截,校验header中的token,token校验通过再放行
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//1.token一般存放在 header 中,所以从 request.getHeader()中获取 token
String token = request.getHeader(TOKEN_NAME);
Map<String,Object> map = new HashMap<String, Object>();
try {
JWTutil.verify(token);
map.put("state",true);
return true;
} catch (AlgorithmMismatchException e) {
map.put("msg","JWT算法不匹配!");
} catch (SignatureVerificationException e) {
map.put("msg","JWT签名不匹配!");
} catch (TokenExpiredException e) {
map.put("msg","token(用户信息)已经过期,请重新登录!");
} catch (Exception e) {
map.put("msg","token无效!");
}
map.put("state",false);
response.setContentType("application/json");
String msg = new ObjectMapper().writeValueAsString(map);
response.getWriter().println(msg);
return false;
}
}
......@@ -6,6 +6,8 @@ import com.jmu.shiro_demo.entity.User;
import com.baomidou.mybatisplus.extension.service.IService;
import org.springframework.ui.Model;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.List;
......@@ -19,7 +21,7 @@ import java.util.List;
*/
public interface UserService extends IService<User> {
String login(String username, String password, String code, HttpSession session, Model model);
String login(String username, String password, String code, HttpSession session, HttpServletResponse response, Model model);
User getUserByUserName(String username);
......
......@@ -8,6 +8,7 @@ import com.jmu.shiro_demo.mapper.UserMapper;
import com.jmu.shiro_demo.service.RoleService;
import com.jmu.shiro_demo.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jmu.shiro_demo.utils.JWTutil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
......@@ -16,9 +17,14 @@ import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* <p>
......@@ -35,7 +41,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
private RoleService roleService;
@Override
public String login(String username, String password, String code, HttpSession session,Model model) {
public String login(String username, String password, String code, HttpSession session, HttpServletResponse response, Model model) {
//在校验登陆之前先检验验证码的正确性
String realAuthCode = (String) session.getAttribute("code");
if(!realAuthCode.equalsIgnoreCase(code)) {
......@@ -45,19 +51,25 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
//1.获取 Subject
Subject subject = SecurityUtils.getSubject();
//2.封装 token
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
UsernamePasswordToken shiroToken = new UsernamePasswordToken(username, password);
//3.调用 subject.login(token) 方法
try {
subject.login(token);
subject.login(shiroToken);
//登录成功之后返回 token 给客户端
Map<String,String> map = new HashMap<String, String>();
map.put("username",username);
String token = JWTutil.getToken(map); //登陆成功,生成JWT token
response.setHeader("token",token); // 将 token 设置在 header 里面
model.addAttribute("token",token);
}catch (UnknownAccountException e1) {
//用户名不存在
model.addAttribute("msg","用户名不存在!");
return "login";
return "/login";
}catch (IncorrectCredentialsException e2) {
model.addAttribute("msg","密码错误!");
return "login";
return "/login";
}
return "redirect:/index";
return "/index";
}
@Override
......
......@@ -40,6 +40,7 @@ public class ShiroConfig {
filterMap.put("/index","anon");
filterMap.put("/login","anon");
filterMap.put("/getAuthCode","anon");
filterMap.put("/js","anon");
//配置动态授权
List<Permission> perms = permissionService.list();
for (Permission permission : perms) {
......
package com.jmu.shiro_demo.utils;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.security.Signature;
import java.util.Calendar;
import java.util.Map;
public class JWTutil {
private static final String SIGN = "jiachengren"; //JWT 签名
private static final int DEFAULT_JWT_EXPIRE_DAYS = 7; //默认JWT过期天数
public static String getToken(Map<String,String> map) {
JWTCreator.Builder builder = JWT.create();
Calendar instance = Calendar.getInstance();
instance.add(Calendar.DATE,DEFAULT_JWT_EXPIRE_DAYS);
//1.header 默认
//2.payload 遍历 map
map.forEach((k,v) -> {
builder.withClaim(k,v);
});
//3.设置过期时间和签名后生成 token
String token = builder
.withExpiresAt(instance.getTime())
.sign(Algorithm.HMAC256(SIGN));
return token;
}
public static DecodedJWT verify(String token){
return JWT.require(Algorithm.HMAC256(SIGN)).build().verify(token);
}
}
......@@ -27,7 +27,7 @@ spring.thymeleaf.encoding=UTF-8
# 要被排除在解析之外的视图名称列表,⽤逗号分隔
spring.thymeleaf.excluded-view-names=
# 要运⽤于模板之上的模板模式。另⻅ StandardTemplate-ModeHandlers( 默认值: HTML5)
spring.thymeleaf.mode=HTML5
spring.thymeleaf.mode=HTML
# 在构建 URL 时添加到视图名称前的前缀(默认值: classpath:/templates/ )
spring.thymeleaf.prefix=classpath:/templates/
# 在构建 URL 时添加到视图名称后的后缀(默认值: .html )
......
此差异已折叠。
<!DOCTYPE html>
<html lang="en" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<html lang="en" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro" xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>index</title>
<script th:src="@{/js/jquery-3.6.0.slim.min.js}"></script>
</head>
<body>
<a shiro:guest href="/toLogin">去登陆</a><br/>
<a shiro:hasPermission="user:add" href="/toUserAdd">去添加</a><br/>
<a shiro:hasPermission="user:update" href="/toUserUpdate">去更新</a><br/>
<a shiro:hasPermission="user:delete" href="/toUserDelete">去删除</a><br/>
<button id="addBtn" shiro:hasPermission="user:add">去添加</button><br/>
<button id="updateBtn" shiro:hasPermission="user:update">去更新</button><br/>
<button id="deleteBtn" shiro:hasPermission="user:delete">去删除</button><br/>
<a shiro:user href="/logout">退出当前用户</a>
</body>
<script>
$(function () {
let token = localStorage.getItem("token")
function myAjax(url){
$.ajax({
url: url,
headers: {
"token": token
},
success: function (data) {
console.log(data)
window.location = data
},
error: function (data) {
alert("error!")
}
})
}
$('#addBtn').click(function () {
myAjax("/toUserAdd")
})
$('#updateBtn').click(function () {
myAjax("/toUserUpdate")
})
$('#deleteBtn').click(function () {
myAjax("/toUserDelete")
})
})
</script>
</html>
......@@ -3,21 +3,42 @@
<head>
<meta charset="UTF-8">
<title>Login</title>
<script th:src="@{/js/jquery-3.6.0.slim.min.js}"></script>
</head>
<body>
<h3 style="color: red" th:text="${msg}"/>
<form action="/user/login" method="post">
账号: <input type="text" name="username"> <br/>
密码: <input type="password" name="password"> <br/>
验证码: <input type="text" name="code"><img id="changeImg" src="/getAuthCode" alt=""><br/>
<button>登陆</button>
</form>
<script src="https://code.jquery.com/jquery-3.6.0.slim.min.js" integrity="sha256-u7e5khyithlIdTpu22PHhENmPcRdFiHRjhAuHcs05RI=" crossorigin="anonymous"></script>
<div>
账号: <input type="text" name="username" id="username"> <br/>
密码: <input type="password" name="password" id="password"> <br/>
验证码: <input type="text" name="code" id="code"><img id="changeImg" src="/getAuthCode" alt=""><br/>
<button id="loginBtn">登陆</button>
</div>
<script>
//点击更换验证码 拼接随机数
$("#changeImg").click(function(){
$("#changeImg").attr('src',"/getAuthCode?d="+Math.random());
});
$(function () {
//点击更换验证码 拼接随机数
$("#changeImg").click(function(){
$("#changeImg").attr('src',"/getAuthCode?d="+Math.random());
});
$('#loginBtn').click(function () {
let username = $('#username').val()
let password = $('#password').val()
let code = $('#code').val()
$.ajax({
url:"/user/login",
data:{"username":username,"password":password,"code":code},
method:"POST",
success: function (data) {
window.localStorage.setItem("token",data.token)
window.location = data.url
console.log(data)
},
error: function () {
alert("error!")
}
})
})
})
</script>
</body>
</html>
package com.jmu.shiro_demo;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
class ShiroDemoApplicationTests {
private final String SIGN = "jiachengren";
@Test
void contextLoads() {
Map<String,Object> map = new HashMap<String, Object>();
Calendar instance = Calendar.getInstance();
instance.add(Calendar.SECOND,0);
String token = JWT.create()
.withHeader(map)
.withClaim("userId", 12)
.withClaim("username", "1")
.withExpiresAt(instance.getTime())
.sign(Algorithm.HMAC256(SIGN));
System.out.println(token);
test(token);
}
@Test
void test(String token) {
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SIGN)).build();
DecodedJWT decodedJWT = jwtVerifier.verify(token);
System.out.println(decodedJWT.getClaim("userId").asInt());
System.out.println(decodedJWT.getClaim("username").asString());
}
}
......@@ -27,7 +27,7 @@ spring.thymeleaf.encoding=UTF-8
# 要被排除在解析之外的视图名称列表,⽤逗号分隔
spring.thymeleaf.excluded-view-names=
# 要运⽤于模板之上的模板模式。另⻅ StandardTemplate-ModeHandlers( 默认值: HTML5)
spring.thymeleaf.mode=HTML5
spring.thymeleaf.mode=HTML
# 在构建 URL 时添加到视图名称前的前缀(默认值: classpath:/templates/ )
spring.thymeleaf.prefix=classpath:/templates/
# 在构建 URL 时添加到视图名称后的后缀(默认值: .html )
......
......@@ -2,6 +2,7 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jmu.shiro_demo.mapper.RoleMapper">
<!--查出一个角色所拥有的全部权限-->
<select id="getRolePermissionsByRoleId" parameterType="int" resultType="permission">
select url,perm
from role,role_permission,permission
......
......@@ -2,6 +2,7 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.jmu.shiro_demo.mapper.UserMapper">
<!--这是 连接 5 张表的sql语句,根据用户ID获取到该用户所拥有的权限,在这里写出来,但是不使用,因为效率不高-->
<select id="getUserPermissionsByUserId" parameterType="int" resultType="permission">
select url,perm
from user,user_role,role,role_permission,permission
......@@ -12,6 +13,7 @@
and user.userid=#{userid};
</select>
<!--查出一个用户所拥有的全部角色-->
<select id="getUserRoleByUserId" parameterType="int" resultType="role">
select role.roleid,role
from user,user_role,role
......
<!DOCTYPE html>
<html lang="en" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<html lang="en" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro" xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>index</title>
<script th:src="@{/js/jquery-3.6.0.slim.min.js}"></script>
</head>
<body>
<a shiro:guest href="/toLogin">去登陆</a><br/>
<a shiro:hasPermission="user:add" href="/toUserAdd">去添加</a><br/>
<a shiro:hasPermission="user:update" href="/toUserUpdate">去更新</a><br/>
<a shiro:hasPermission="user:delete" href="/toUserDelete">去删除</a><br/>
<button id="addBtn" shiro:hasPermission="user:add">去添加</button><br/>
<button id="updateBtn" shiro:hasPermission="user:update">去更新</button><br/>
<button id="deleteBtn" shiro:hasPermission="user:delete">去删除</button><br/>
<a shiro:user href="/logout">退出当前用户</a>
</body>
<script>
$(function () {
let token = localStorage.getItem("token")
function myAjax(url){
$.ajax({
url: url,
headers: {
"token": token
},
success: function (data) {
console.log(data)
window.location = data
},
error: function (data) {
alert("error!")
}
})
}
$('#addBtn').click(function () {
myAjax("/toUserAdd")
})
$('#updateBtn').click(function () {
myAjax("/toUserUpdate")
})
$('#deleteBtn').click(function () {
myAjax("/toUserDelete")
})
})
</script>
</html>
......@@ -3,21 +3,42 @@
<head>
<meta charset="UTF-8">
<title>Login</title>
<script th:src="@{/js/jquery-3.6.0.slim.min.js}"></script>
</head>
<body>
<h3 style="color: red" th:text="${msg}"/>
<form action="/user/login" method="post">
账号: <input type="text" name="username"> <br/>
密码: <input type="password" name="password"> <br/>
验证码: <input type="text" name="code"><img id="changeImg" src="/getAuthCode" alt=""><br/>
<button>登陆</button>
</form>
<script src="https://code.jquery.com/jquery-3.6.0.slim.min.js" integrity="sha256-u7e5khyithlIdTpu22PHhENmPcRdFiHRjhAuHcs05RI=" crossorigin="anonymous"></script>
<div>
账号: <input type="text" name="username" id="username"> <br/>
密码: <input type="password" name="password" id="password"> <br/>
验证码: <input type="text" name="code" id="code"><img id="changeImg" src="/getAuthCode" alt=""><br/>
<button id="loginBtn">登陆</button>
</div>
<script>
//点击更换验证码 拼接随机数
$("#changeImg").click(function(){
$("#changeImg").attr('src',"/getAuthCode?d="+Math.random());
});
$(function () {
//点击更换验证码 拼接随机数
$("#changeImg").click(function(){
$("#changeImg").attr('src',"/getAuthCode?d="+Math.random());
});
$('#loginBtn').click(function () {
let username = $('#username').val()
let password = $('#password').val()
let code = $('#code').val()
$.ajax({
url:"/user/login",
data:{"username":username,"password":password,"code":code},
method:"POST",
success: function (data) {
window.localStorage.setItem("token",data.token)
window.location = data.url
console.log(data)
},
error: function () {
alert("error!")
}
})
})
})
</script>
</body>
</html>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册