Browse Source

add springboot shiro demo

ityouknow 7 years ago
parent
commit
70d1585320
25 changed files with 1116 additions and 1 deletions
  1. 3 1
      README.md
  2. 1 0
      README_EN.md
  3. 225 0
      spring-boot-shiro/mvnw
  4. 143 0
      spring-boot-shiro/mvnw.cmd
  5. 79 0
      spring-boot-shiro/pom.xml
  6. 12 0
      spring-boot-shiro/src/main/java/com/neo/SpringBootShiroApplication.java
  7. 60 0
      spring-boot-shiro/src/main/java/com/neo/config/MyShiroRealm.java
  8. 98 0
      spring-boot-shiro/src/main/java/com/neo/config/ShiroConfig.java
  9. 9 0
      spring-boot-shiro/src/main/java/com/neo/dao/UserInfoDao.java
  10. 94 0
      spring-boot-shiro/src/main/java/com/neo/entity/SysPermission.java
  11. 71 0
      spring-boot-shiro/src/main/java/com/neo/entity/SysRole.java
  12. 86 0
      spring-boot-shiro/src/main/java/com/neo/entity/UserInfo.java
  13. 8 0
      spring-boot-shiro/src/main/java/com/neo/sevice/UserInfoService.java
  14. 19 0
      spring-boot-shiro/src/main/java/com/neo/sevice/impl/UserInfoServiceImpl.java
  15. 52 0
      spring-boot-shiro/src/main/java/com/neo/web/HomeController.java
  16. 40 0
      spring-boot-shiro/src/main/java/com/neo/web/UserInfoController.java
  17. 23 0
      spring-boot-shiro/src/main/resources/application.yml
  18. 12 0
      spring-boot-shiro/src/main/resources/database/import.sql
  19. 10 0
      spring-boot-shiro/src/main/resources/templates/403.html
  20. 10 0
      spring-boot-shiro/src/main/resources/templates/index.html
  21. 15 0
      spring-boot-shiro/src/main/resources/templates/login.html
  22. 10 0
      spring-boot-shiro/src/main/resources/templates/userInfo.html
  23. 10 0
      spring-boot-shiro/src/main/resources/templates/userInfoAdd.html
  24. 10 0
      spring-boot-shiro/src/main/resources/templates/userInfoDel.html
  25. 16 0
      spring-boot-shiro/src/test/java/com/neo/SpringBootShiroApplicationTests.java

+ 3 - 1
README.md

@@ -20,6 +20,7 @@ Spring boot使用的各种示例,以最简单、最实用为标准
 - [spring-boot-mongodb](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-mongodb):spring boot和mongodb的使用
 - [spring-boot-mongodb](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-mongodb):spring boot和mongodb的使用
 - [spring-boot-multi-mongodb](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-multi-mongodb):spring boot和mongodb多数据源的使用
 - [spring-boot-multi-mongodb](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-multi-mongodb):spring boot和mongodb多数据源的使用
 - [spring-boot-package-war](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-package-war):spring-boot打包成war包示例
 - [spring-boot-package-war](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-package-war):spring-boot打包成war包示例
+- [spring-boot-shiro](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-shiro):springboot 整合shiro rbac示例
 - [Favorites-web](https://github.com/cloudfavorites/favorites-web):云收藏(springboot实战开源软件)
 - [Favorites-web](https://github.com/cloudfavorites/favorites-web):云收藏(springboot实战开源软件)
 
 
 
 
@@ -39,7 +40,8 @@ Spring boot使用的各种示例,以最简单、最实用为标准
 - [springboot(十一):Spring boot中mongodb的使用](http://www.ityouknow.com/springboot/2017/05/08/springboot-mongodb.html)
 - [springboot(十一):Spring boot中mongodb的使用](http://www.ityouknow.com/springboot/2017/05/08/springboot-mongodb.html)
 - [springboot(十二):springboot如何测试打包部署](http://www.ityouknow.com/springboot/2017/05/09/springboot-deploy.html)
 - [springboot(十二):springboot如何测试打包部署](http://www.ityouknow.com/springboot/2017/05/09/springboot-deploy.html)
 - [springboot实战:我们的第一款开源软件](http://www.ityouknow.com/springboot/2016/09/26/springboot%E5%AE%9E%E6%88%98-%E6%88%91%E4%BB%AC%E7%9A%84%E7%AC%AC%E4%B8%80%E6%AC%BE%E5%BC%80%E6%BA%90%E8%BD%AF%E4%BB%B6.html)
 - [springboot实战:我们的第一款开源软件](http://www.ityouknow.com/springboot/2016/09/26/springboot%E5%AE%9E%E6%88%98-%E6%88%91%E4%BB%AC%E7%9A%84%E7%AC%AC%E4%B8%80%E6%AC%BE%E5%BC%80%E6%BA%90%E8%BD%AF%E4%BB%B6.html)
-
+- [springboot(十三):springboot小技巧](http://www.ityouknow.com/springboot/2017/06/22/springboot-tips.html)
+- [springboot(十四):springboot整合shiro-登录认证和权限管理](http://www.ityouknow.com/springboot/2017/06/26/springboot-shiro.html)
 
 
 > 如果大家想了解关于springboot的其它方面应用,也可以以[issues](https://github.com/ityouknow/spring-boot-examples/issues)的形式反馈给我,我后续来完善。
 > 如果大家想了解关于springboot的其它方面应用,也可以以[issues](https://github.com/ityouknow/spring-boot-examples/issues)的形式反馈给我,我后续来完善。
 
 

+ 1 - 0
README_EN.md

@@ -21,4 +21,5 @@ Spring Boot Examples, Use the simplest and most useful scene demo.
 - [spring-boot-mongodb](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-mongodb):Spring Boot + Mongodb
 - [spring-boot-mongodb](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-mongodb):Spring Boot + Mongodb
 - [spring-boot-multi-mongodb](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-multi-mongodb):Spring Boot + multiMongodb
 - [spring-boot-multi-mongodb](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-multi-mongodb):Spring Boot + multiMongodb
 - [spring-boot-package-war](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-package-war):Spring Boot package war
 - [spring-boot-package-war](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-package-war):Spring Boot package war
+- [spring-boot-shiro](https://github.com/ityouknow/spring-boot-examples/tree/master/spring-boot-shiro):spring boot shiro rbac demo 
 - [Favorites-web](https://github.com/cloudfavorites/favorites-web):Open source projects developed using Spring Boot
 - [Favorites-web](https://github.com/cloudfavorites/favorites-web):Open source projects developed using Spring Boot

+ 225 - 0
spring-boot-shiro/mvnw

@@ -0,0 +1,225 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Maven2 Start Up Batch script
+#
+# Required ENV vars:
+# ------------------
+#   JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+#   M2_HOME - location of maven2's installed home dir
+#   MAVEN_OPTS - parameters passed to the Java VM when running Maven
+#     e.g. to debug Maven itself, use
+#       set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+#   MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+  if [ -f /etc/mavenrc ] ; then
+    . /etc/mavenrc
+  fi
+
+  if [ -f "$HOME/.mavenrc" ] ; then
+    . "$HOME/.mavenrc"
+  fi
+
+fi
+
+# OS specific support.  $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "`uname`" in
+  CYGWIN*) cygwin=true ;;
+  MINGW*) mingw=true;;
+  Darwin*) darwin=true
+    # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+    # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+    if [ -z "$JAVA_HOME" ]; then
+      if [ -x "/usr/libexec/java_home" ]; then
+        export JAVA_HOME="`/usr/libexec/java_home`"
+      else
+        export JAVA_HOME="/Library/Java/Home"
+      fi
+    fi
+    ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+  if [ -r /etc/gentoo-release ] ; then
+    JAVA_HOME=`java-config --jre-home`
+  fi
+fi
+
+if [ -z "$M2_HOME" ] ; then
+  ## resolve links - $0 may be a link to maven's home
+  PRG="$0"
+
+  # need this for relative symlinks
+  while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+      PRG="$link"
+    else
+      PRG="`dirname "$PRG"`/$link"
+    fi
+  done
+
+  saveddir=`pwd`
+
+  M2_HOME=`dirname "$PRG"`/..
+
+  # make it fully qualified
+  M2_HOME=`cd "$M2_HOME" && pwd`
+
+  cd "$saveddir"
+  # echo Using m2 at $M2_HOME
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+  [ -n "$M2_HOME" ] &&
+    M2_HOME=`cygpath --unix "$M2_HOME"`
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
+fi
+
+# For Migwn, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+  [ -n "$M2_HOME" ] &&
+    M2_HOME="`(cd "$M2_HOME"; pwd)`"
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
+  # TODO classpath?
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+  javaExecutable="`which javac`"
+  if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
+    # readlink(1) is not available as standard on Solaris 10.
+    readLink=`which readlink`
+    if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
+      if $darwin ; then
+        javaHome="`dirname \"$javaExecutable\"`"
+        javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
+      else
+        javaExecutable="`readlink -f \"$javaExecutable\"`"
+      fi
+      javaHome="`dirname \"$javaExecutable\"`"
+      javaHome=`expr "$javaHome" : '\(.*\)/bin'`
+      JAVA_HOME="$javaHome"
+      export JAVA_HOME
+    fi
+  fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+  if [ -n "$JAVA_HOME"  ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+      # IBM's JDK on AIX uses strange locations for the executables
+      JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+      JAVACMD="$JAVA_HOME/bin/java"
+    fi
+  else
+    JAVACMD="`which java`"
+  fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+  echo "Error: JAVA_HOME is not defined correctly." >&2
+  echo "  We cannot execute $JAVACMD" >&2
+  exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+  echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+
+  if [ -z "$1" ]
+  then
+    echo "Path not specified to find_maven_basedir"
+    return 1
+  fi
+
+  basedir="$1"
+  wdir="$1"
+  while [ "$wdir" != '/' ] ; do
+    if [ -d "$wdir"/.mvn ] ; then
+      basedir=$wdir
+      break
+    fi
+    # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+    if [ -d "${wdir}" ]; then
+      wdir=`cd "$wdir/.."; pwd`
+    fi
+    # end of workaround
+  done
+  echo "${basedir}"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+  if [ -f "$1" ]; then
+    echo "$(tr -s '\n' ' ' < "$1")"
+  fi
+}
+
+BASE_DIR=`find_maven_basedir "$(pwd)"`
+if [ -z "$BASE_DIR" ]; then
+  exit 1;
+fi
+
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
+echo $MAVEN_PROJECTBASEDIR
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+  [ -n "$M2_HOME" ] &&
+    M2_HOME=`cygpath --path --windows "$M2_HOME"`
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
+  [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+    MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
+fi
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+exec "$JAVACMD" \
+  $MAVEN_OPTS \
+  -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+  "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+  ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

+ 143 - 0
spring-boot-shiro/mvnw.cmd

@@ -0,0 +1,143 @@
+@REM ----------------------------------------------------------------------------
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements.  See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership.  The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License.  You may obtain a copy of the License at
+@REM
+@REM    http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied.  See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM ----------------------------------------------------------------------------
+
+@REM ----------------------------------------------------------------------------
+@REM Maven2 Start Up Batch script
+@REM
+@REM Required ENV vars:
+@REM JAVA_HOME - location of a JDK home dir
+@REM
+@REM Optional ENV vars
+@REM M2_HOME - location of maven2's installed home dir
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
+@REM     e.g. to debug Maven itself, use
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+@REM ----------------------------------------------------------------------------
+
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
+@echo off
+@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
+@if "%MAVEN_BATCH_ECHO%" == "on"  echo %MAVEN_BATCH_ECHO%
+
+@REM set %HOME% to equivalent of $HOME
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
+
+@REM Execute a user defined script before this one
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
+:skipRcPre
+
+@setlocal
+
+set ERROR_CODE=0
+
+@REM To isolate internal variables from possible post scripts, we use another setlocal
+@setlocal
+
+@REM ==== START VALIDATION ====
+if not "%JAVA_HOME%" == "" goto OkJHome
+
+echo.
+echo Error: JAVA_HOME not found in your environment. >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+:OkJHome
+if exist "%JAVA_HOME%\bin\java.exe" goto init
+
+echo.
+echo Error: JAVA_HOME is set to an invalid directory. >&2
+echo JAVA_HOME = "%JAVA_HOME%" >&2
+echo Please set the JAVA_HOME variable in your environment to match the >&2
+echo location of your Java installation. >&2
+echo.
+goto error
+
+@REM ==== END VALIDATION ====
+
+:init
+
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
+@REM Fallback to current working directory if not found.
+
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
+
+set EXEC_DIR=%CD%
+set WDIR=%EXEC_DIR%
+:findBaseDir
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
+cd ..
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
+set WDIR=%CD%
+goto findBaseDir
+
+:baseDirFound
+set MAVEN_PROJECTBASEDIR=%WDIR%
+cd "%EXEC_DIR%"
+goto endDetectBaseDir
+
+:baseDirNotFound
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
+cd "%EXEC_DIR%"
+
+:endDetectBaseDir
+
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
+
+@setlocal EnableExtensions EnableDelayedExpansion
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
+
+:endReadAdditionalConfig
+
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
+
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
+if ERRORLEVEL 1 goto error
+goto end
+
+:error
+set ERROR_CODE=1
+
+:end
+@endlocal & set ERROR_CODE=%ERROR_CODE%
+
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
+:skipRcPost
+
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
+
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
+
+exit /B %ERROR_CODE%

+ 79 - 0
spring-boot-shiro/pom.xml

@@ -0,0 +1,79 @@
+<?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.neo</groupId>
+	<artifactId>spring-boot-shiro</artifactId>
+	<version>0.0.1-SNAPSHOT</version>
+	<packaging>jar</packaging>
+
+	<name>spring-boot-shiro</name>
+	<description>Demo project for Spring Boot</description>
+
+	<parent>
+		<groupId>org.springframework.boot</groupId>
+		<artifactId>spring-boot-starter-parent</artifactId>
+		<version>1.5.4.RELEASE</version>
+		<relativePath/> <!-- lookup parent from repository -->
+	</parent>
+
+	<properties>
+		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+		<java.version>1.8</java.version>
+	</properties>
+
+	<dependencies>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-data-jpa</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-thymeleaf</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>net.sourceforge.nekohtml</groupId>
+			<artifactId>nekohtml</artifactId>
+			<version>1.9.22</version>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-web</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>org.apache.shiro</groupId>
+			<artifactId>shiro-spring</artifactId>
+			<version>1.4.0</version>
+		</dependency>
+		<dependency>
+			<groupId>mysql</groupId>
+			<artifactId>mysql-connector-java</artifactId>
+			<scope>runtime</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-test</artifactId>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-devtools</artifactId>
+			<optional>true</optional>
+		</dependency>
+	</dependencies>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.springframework.boot</groupId>
+				<artifactId>spring-boot-maven-plugin</artifactId>
+				<configuration>
+					<fork>true</fork>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+</project>

+ 12 - 0
spring-boot-shiro/src/main/java/com/neo/SpringBootShiroApplication.java

@@ -0,0 +1,12 @@
+package com.neo;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class SpringBootShiroApplication {
+
+	public static void main(String[] args) {
+		SpringApplication.run(SpringBootShiroApplication.class, args);
+	}
+}

+ 60 - 0
spring-boot-shiro/src/main/java/com/neo/config/MyShiroRealm.java

@@ -0,0 +1,60 @@
+package com.neo.config;
+
+import com.neo.entity.SysPermission;
+import com.neo.entity.SysRole;
+import com.neo.entity.UserInfo;
+import com.neo.sevice.UserInfoService;
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.AuthenticationInfo;
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.authc.SimpleAuthenticationInfo;
+import org.apache.shiro.authz.AuthorizationInfo;
+import org.apache.shiro.authz.SimpleAuthorizationInfo;
+import org.apache.shiro.realm.AuthorizingRealm;
+import org.apache.shiro.subject.PrincipalCollection;
+import org.apache.shiro.util.ByteSource;
+
+import javax.annotation.Resource;
+
+public class MyShiroRealm extends AuthorizingRealm {
+    @Resource
+    private UserInfoService userInfoService;
+    @Override
+    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
+        System.out.println("权限配置-->MyShiroRealm.doGetAuthorizationInfo()");
+        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
+        UserInfo userInfo  = (UserInfo)principals.getPrimaryPrincipal();
+        for(SysRole role:userInfo.getRoleList()){
+            authorizationInfo.addRole(role.getRole());
+            for(SysPermission p:role.getPermissions()){
+                authorizationInfo.addStringPermission(p.getPermission());
+            }
+        }
+        return authorizationInfo;
+    }
+
+    /*主要是用来进行身份认证的,也就是说验证用户输入的账号和密码是否正确。*/
+    @Override
+    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
+            throws AuthenticationException {
+        System.out.println("MyShiroRealm.doGetAuthenticationInfo()");
+        //获取用户的输入的账号.
+        String username = (String)token.getPrincipal();
+        System.out.println(token.getCredentials());
+        //通过username从数据库中查找 User对象,如果找到,没找到.
+        //实际项目中,这里可以根据实际情况做缓存,如果不做,Shiro自己也是有时间间隔机制,2分钟内不会重复执行该方法
+        UserInfo userInfo = userInfoService.findByUsername(username);
+        System.out.println("----->>userInfo="+userInfo);
+        if(userInfo == null){
+            return null;
+        }
+        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
+                userInfo, //用户名
+                userInfo.getPassword(), //密码
+                ByteSource.Util.bytes(userInfo.getCredentialsSalt()),//salt=username+salt
+                getName()  //realm name
+        );
+        return authenticationInfo;
+    }
+
+}

+ 98 - 0
spring-boot-shiro/src/main/java/com/neo/config/ShiroConfig.java

@@ -0,0 +1,98 @@
+package com.neo.config;
+
+import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
+import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
+import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Properties;
+
+@Configuration
+public class ShiroConfig {
+	@Bean
+	public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
+		System.out.println("ShiroConfiguration.shirFilter()");
+		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
+		shiroFilterFactoryBean.setSecurityManager(securityManager);
+		//拦截器.
+		Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
+		// 配置不会被拦截的链接 顺序判断
+		filterChainDefinitionMap.put("/static/**", "anon");
+		//配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
+		filterChainDefinitionMap.put("/logout", "logout");
+		//<!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
+		//<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
+		filterChainDefinitionMap.put("/**", "authc");
+		// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
+		shiroFilterFactoryBean.setLoginUrl("/login");
+		// 登录成功后要跳转的链接
+		shiroFilterFactoryBean.setSuccessUrl("/index");
+
+		//未授权界面;
+		shiroFilterFactoryBean.setUnauthorizedUrl("/403");
+		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
+		return shiroFilterFactoryBean;
+	}
+
+	/**
+	 * 凭证匹配器
+	 * (由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了
+	 * )
+	 * @return
+	 */
+	@Bean
+	public HashedCredentialsMatcher hashedCredentialsMatcher(){
+		HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
+		hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:这里使用MD5算法;
+		hashedCredentialsMatcher.setHashIterations(2);//散列的次数,比如散列两次,相当于 md5(md5(""));
+		return hashedCredentialsMatcher;
+	}
+
+	@Bean
+	public MyShiroRealm myShiroRealm(){
+		MyShiroRealm myShiroRealm = new MyShiroRealm();
+		myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
+		return myShiroRealm;
+	}
+
+
+	@Bean
+	public SecurityManager securityManager(){
+		DefaultWebSecurityManager securityManager =  new DefaultWebSecurityManager();
+		securityManager.setRealm(myShiroRealm());
+		return securityManager;
+	}
+
+	/**
+	 *  开启shiro aop注解支持.
+	 *  使用代理方式;所以需要开启代码支持;
+	 * @param securityManager
+	 * @return
+	 */
+	@Bean
+	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
+		AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
+		authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
+		return authorizationAttributeSourceAdvisor;
+	}
+
+	@Bean(name="simpleMappingExceptionResolver")
+	public SimpleMappingExceptionResolver
+	createSimpleMappingExceptionResolver() {
+		SimpleMappingExceptionResolver r = new SimpleMappingExceptionResolver();
+		Properties mappings = new Properties();
+		mappings.setProperty("DatabaseException", "databaseError");//数据库异常处理
+		mappings.setProperty("UnauthorizedException","403");
+		r.setExceptionMappings(mappings);  // None by default
+		r.setDefaultErrorView("error");    // No default
+		r.setExceptionAttribute("ex");     // Default is "exception"
+		//r.setWarnLogCategory("example.MvcLogger");     // No default
+		return r;
+	}
+}

+ 9 - 0
spring-boot-shiro/src/main/java/com/neo/dao/UserInfoDao.java

@@ -0,0 +1,9 @@
+package com.neo.dao;
+
+import com.neo.entity.UserInfo;
+import org.springframework.data.repository.CrudRepository;
+
+public interface UserInfoDao extends CrudRepository<UserInfo,Long> {
+    /**通过username查找用户信息;*/
+    public UserInfo findByUsername(String username);
+}

+ 94 - 0
spring-boot-shiro/src/main/java/com/neo/entity/SysPermission.java

@@ -0,0 +1,94 @@
+package com.neo.entity;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.List;
+
+@Entity
+public class SysPermission implements Serializable {
+    @Id@GeneratedValue
+    private Integer id;//主键.
+    private String name;//名称.
+    @Column(columnDefinition="enum('menu','button')")
+    private String resourceType;//资源类型,[menu|button]
+    private String url;//资源路径.
+    private String permission; //权限字符串,menu例子:role:*,button例子:role:create,role:update,role:delete,role:view
+    private Long parentId; //父编号
+    private String parentIds; //父编号列表
+    private Boolean available = Boolean.FALSE;
+    @ManyToMany
+    @JoinTable(name="SysRolePermission",joinColumns={@JoinColumn(name="permissionId")},inverseJoinColumns={@JoinColumn(name="roleId")})
+    private List<SysRole> roles;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getResourceType() {
+        return resourceType;
+    }
+
+    public void setResourceType(String resourceType) {
+        this.resourceType = resourceType;
+    }
+
+    public String getUrl() {
+        return url;
+    }
+
+    public void setUrl(String url) {
+        this.url = url;
+    }
+
+    public String getPermission() {
+        return permission;
+    }
+
+    public void setPermission(String permission) {
+        this.permission = permission;
+    }
+
+    public Long getParentId() {
+        return parentId;
+    }
+
+    public void setParentId(Long parentId) {
+        this.parentId = parentId;
+    }
+
+    public String getParentIds() {
+        return parentIds;
+    }
+
+    public void setParentIds(String parentIds) {
+        this.parentIds = parentIds;
+    }
+
+    public Boolean getAvailable() {
+        return available;
+    }
+
+    public void setAvailable(Boolean available) {
+        this.available = available;
+    }
+
+    public List<SysRole> getRoles() {
+        return roles;
+    }
+
+    public void setRoles(List<SysRole> roles) {
+        this.roles = roles;
+    }
+}

+ 71 - 0
spring-boot-shiro/src/main/java/com/neo/entity/SysRole.java

@@ -0,0 +1,71 @@
+package com.neo.entity;
+
+import javax.persistence.*;
+import java.util.List;
+
+@Entity
+public class SysRole {
+    @Id@GeneratedValue
+    private Integer id; // 编号
+    private String role; // 角色标识程序中判断使用,如"admin",这个是唯一的:
+    private String description; // 角色描述,UI界面显示使用
+    private Boolean available = Boolean.FALSE; // 是否可用,如果不可用将不会添加给用户
+
+    //角色 -- 权限关系:多对多关系;
+    @ManyToMany(fetch= FetchType.EAGER)
+    @JoinTable(name="SysRolePermission",joinColumns={@JoinColumn(name="roleId")},inverseJoinColumns={@JoinColumn(name="permissionId")})
+    private List<SysPermission> permissions;
+
+    // 用户 - 角色关系定义;
+    @ManyToMany
+    @JoinTable(name="SysUserRole",joinColumns={@JoinColumn(name="roleId")},inverseJoinColumns={@JoinColumn(name="uid")})
+    private List<UserInfo> userInfos;// 一个角色对应多个用户
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public String getRole() {
+        return role;
+    }
+
+    public void setRole(String role) {
+        this.role = role;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public Boolean getAvailable() {
+        return available;
+    }
+
+    public void setAvailable(Boolean available) {
+        this.available = available;
+    }
+
+    public List<SysPermission> getPermissions() {
+        return permissions;
+    }
+
+    public void setPermissions(List<SysPermission> permissions) {
+        this.permissions = permissions;
+    }
+
+    public List<UserInfo> getUserInfos() {
+        return userInfos;
+    }
+
+    public void setUserInfos(List<UserInfo> userInfos) {
+        this.userInfos = userInfos;
+    }
+}

+ 86 - 0
spring-boot-shiro/src/main/java/com/neo/entity/UserInfo.java

@@ -0,0 +1,86 @@
+package com.neo.entity;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.List;
+
+@Entity
+public class UserInfo implements Serializable {
+    @Id
+    @GeneratedValue
+    private Integer uid;
+    @Column(unique =true)
+    private String username;//帐号
+    private String name;//名称(昵称或者真实姓名,不同系统不同定义)
+    private String password; //密码;
+    private String salt;//加密密码的盐
+    private byte state;//用户状态,0:创建未认证(比如没有激活,没有输入验证码等等)--等待验证的用户 , 1:正常状态,2:用户被锁定.
+    @ManyToMany(fetch= FetchType.EAGER)//立即从数据库中进行加载数据;
+    @JoinTable(name = "SysUserRole", joinColumns = { @JoinColumn(name = "uid") }, inverseJoinColumns ={@JoinColumn(name = "roleId") })
+    private List<SysRole> roleList;// 一个用户具有多个角色
+
+    public Integer getUid() {
+        return uid;
+    }
+
+    public void setUid(Integer uid) {
+        this.uid = uid;
+    }
+
+    public String getUsername() {
+        return username;
+    }
+
+    public void setUsername(String username) {
+        this.username = username;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public String getSalt() {
+        return salt;
+    }
+
+    public void setSalt(String salt) {
+        this.salt = salt;
+    }
+
+    public byte getState() {
+        return state;
+    }
+
+    public void setState(byte state) {
+        this.state = state;
+    }
+
+    public List<SysRole> getRoleList() {
+        return roleList;
+    }
+
+    public void setRoleList(List<SysRole> roleList) {
+        this.roleList = roleList;
+    }
+
+    /**
+     * 密码盐.
+     * @return
+     */
+    public String getCredentialsSalt(){
+        return this.username+this.salt;
+    }
+    //重新对盐重新进行了定义,用户名+salt,这样就更加不容易被破解
+}

+ 8 - 0
spring-boot-shiro/src/main/java/com/neo/sevice/UserInfoService.java

@@ -0,0 +1,8 @@
+package com.neo.sevice;
+
+import com.neo.entity.UserInfo;
+
+public interface UserInfoService {
+    /**通过username查找用户信息;*/
+    public UserInfo findByUsername(String username);
+}

+ 19 - 0
spring-boot-shiro/src/main/java/com/neo/sevice/impl/UserInfoServiceImpl.java

@@ -0,0 +1,19 @@
+package com.neo.sevice.impl;
+
+import com.neo.dao.UserInfoDao;
+import com.neo.entity.UserInfo;
+import com.neo.sevice.UserInfoService;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+
+@Service
+public class UserInfoServiceImpl implements UserInfoService {
+    @Resource
+    private UserInfoDao userInfoDao;
+    @Override
+    public UserInfo findByUsername(String username) {
+        System.out.println("UserInfoServiceImpl.findByUsername()");
+        return userInfoDao.findByUsername(username);
+    }
+}

+ 52 - 0
spring-boot-shiro/src/main/java/com/neo/web/HomeController.java

@@ -0,0 +1,52 @@
+package com.neo.web;
+
+import org.apache.shiro.authc.IncorrectCredentialsException;
+import org.apache.shiro.authc.UnknownAccountException;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.Map;
+
+@Controller
+public class HomeController {
+    @RequestMapping({"/","/index"})
+    public String index(){
+        return"/index";
+    }
+
+    @RequestMapping("/login")
+    public String login(HttpServletRequest request, Map<String, Object> map) throws Exception{
+        System.out.println("HomeController.login()");
+        // 登录失败从request中获取shiro处理的异常信息。
+        // shiroLoginFailure:就是shiro异常类的全类名.
+        String exception = (String) request.getAttribute("shiroLoginFailure");
+        System.out.println("exception=" + exception);
+        String msg = "";
+        if (exception != null) {
+            if (UnknownAccountException.class.getName().equals(exception)) {
+                System.out.println("UnknownAccountException -- > 账号不存在:");
+                msg = "UnknownAccountException -- > 账号不存在:";
+            } else if (IncorrectCredentialsException.class.getName().equals(exception)) {
+                System.out.println("IncorrectCredentialsException -- > 密码不正确:");
+                msg = "IncorrectCredentialsException -- > 密码不正确:";
+            } else if ("kaptchaValidateFailed".equals(exception)) {
+                System.out.println("kaptchaValidateFailed -- > 验证码错误");
+                msg = "kaptchaValidateFailed -- > 验证码错误";
+            } else {
+                msg = "else >> "+exception;
+                System.out.println("else -- >" + exception);
+            }
+        }
+        map.put("msg", msg);
+        // 此方法不处理登录成功,由shiro进行处理
+        return "/login";
+    }
+
+    @RequestMapping("/403")
+    public String unauthorizedRole(){
+        System.out.println("------没有权限-------");
+        return "403";
+    }
+
+}

+ 40 - 0
spring-boot-shiro/src/main/java/com/neo/web/UserInfoController.java

@@ -0,0 +1,40 @@
+package com.neo.web;
+
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@Controller
+@RequestMapping("/userInfo")
+public class UserInfoController {
+
+    /**
+     * 用户查询.
+     * @return
+     */
+    @RequestMapping("/userList")
+    @RequiresPermissions("userInfo:view")//权限管理;
+    public String userInfo(){
+        return "userInfo";
+    }
+
+    /**
+     * 用户添加;
+     * @return
+     */
+    @RequestMapping("/userAdd")
+    @RequiresPermissions("userInfo:add")//权限管理;
+    public String userInfoAdd(){
+        return "userInfoAdd";
+    }
+
+    /**
+     * 用户删除;
+     * @return
+     */
+    @RequestMapping("/userDel")
+    @RequiresPermissions("userInfo:del")//权限管理;
+    public String userDel(){
+        return "userInfoDel";
+    }
+}

+ 23 - 0
spring-boot-shiro/src/main/resources/application.yml

@@ -0,0 +1,23 @@
+spring:
+    datasource:
+      url: jdbc:mysql://localhost:3306/test
+      username: root
+      password: root
+      #schema: database/import.sql
+      #sql-script-encoding: utf-8
+      driver-class-name: com.mysql.jdbc.Driver
+
+    jpa:
+      database: mysql
+      show-sql: true
+      hibernate:
+        ddl-auto: update
+        naming:
+          strategy: org.hibernate.cfg.DefaultComponentSafeNamingStrategy
+      properties:
+         hibernate:
+            dialect: org.hibernate.dialect.MySQL5Dialect
+
+    thymeleaf:
+       cache: false
+       mode: LEGACYHTML5

+ 12 - 0
spring-boot-shiro/src/main/resources/database/import.sql

@@ -0,0 +1,12 @@
+INSERT INTO `sys_permission` (`id`,`available`,`name`,`parent_id`,`parent_ids`,`permission`,`resource_type`,`url`) VALUES (1,0,'用户管理',0,'0/','userInfo:view','menu','userInfo/userList');
+INSERT INTO `sys_permission` (`id`,`available`,`name`,`parent_id`,`parent_ids`,`permission`,`resource_type`,`url`) VALUES (2,0,'用户添加',1,'0/1','userInfo:add','button','userInfo/userAdd');
+INSERT INTO `sys_permission` (`id`,`available`,`name`,`parent_id`,`parent_ids`,`permission`,`resource_type`,`url`) VALUES (3,0,'用户删除',1,'0/1','userInfo:del','button','userInfo/userDel');
+INSERT INTO `sys_role` (`id`,`available`,`description`,`role`) VALUES (1,'0','管理员','admin');
+INSERT INTO `sys_role` (`id`,`available`,`description`,`role`) VALUES (2,'0','VIP会员','vip');INSERT INTO `sys_role_permission` VALUES ('1', '1');
+INSERT INTO `sys_role_permission` (`permission_id`,`role_id`) VALUES (1,1);
+INSERT INTO `sys_role_permission` (`permission_id`,`role_id`) VALUES (1,2);
+INSERT INTO `sys_role_permission` (`permission_id`,`role_id`) VALUES (1,3);
+INSERT INTO `sys_user_role` (`role_id`,`uid`) VALUES (1,1);
+INSERT INTO `user_info` (`uid`,`username`,`name`,`password`,`salt`,`state`) VALUES ('1', 'admin', '管理员', 'd3c59d25033dbf980d29554025c23a75', '8d78869f470951332959580424d4bf4f', 0);
+
+

+ 10 - 0
spring-boot-shiro/src/main/resources/templates/403.html

@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Title</title>
+</head>
+<body>
+<h3>403没有权限</h3>
+</body>
+</html>

+ 10 - 0
spring-boot-shiro/src/main/resources/templates/index.html

@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Title</title>
+</head>
+<body>
+<h1>index</h1>
+</body>
+</html>

+ 15 - 0
spring-boot-shiro/src/main/resources/templates/login.html

@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Title</title>
+</head>
+<body>
+错误信息:<h4 th:text="${msg}"></h4>
+<form action="" method="post">
+    <p>账号:<input type="text" name="username" value="admin"/></p>
+    <p>密码:<input type="text" name="password" value="123456"/></p>
+    <p><input type="submit" value="登录"/></p>
+</form>
+</body>
+</html>

+ 10 - 0
spring-boot-shiro/src/main/resources/templates/userInfo.html

@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Title</title>
+</head>
+<body>
+<h3>用户查询界面</h3>
+</body>
+</html>

+ 10 - 0
spring-boot-shiro/src/main/resources/templates/userInfoAdd.html

@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Title</title>
+</head>
+<body>
+<h3>用户添加界面</h3>
+</body>
+</html>

+ 10 - 0
spring-boot-shiro/src/main/resources/templates/userInfoDel.html

@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>Title</title>
+</head>
+<body>
+<h3>用户删除界面</h3>
+</body>
+</html>

+ 16 - 0
spring-boot-shiro/src/test/java/com/neo/SpringBootShiroApplicationTests.java

@@ -0,0 +1,16 @@
+package com.neo;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class SpringBootShiroApplicationTests {
+
+	@Test
+	public void contextLoads() {
+	}
+
+}