From 70d15853208bb989bb91909143ec8fad2462883b Mon Sep 17 00:00:00 2001 From: ityouknow Date: Mon, 26 Jun 2017 18:02:19 +0800 Subject: [PATCH] add springboot shiro demo --- README.md | 4 +- README_EN.md | 1 + spring-boot-shiro/mvnw | 225 ++++++++++++++++++ spring-boot-shiro/mvnw.cmd | 143 +++++++++++ spring-boot-shiro/pom.xml | 79 ++++++ .../com/neo/SpringBootShiroApplication.java | 12 + .../java/com/neo/config/MyShiroRealm.java | 60 +++++ .../main/java/com/neo/config/ShiroConfig.java | 98 ++++++++ .../main/java/com/neo/dao/UserInfoDao.java | 9 + .../java/com/neo/entity/SysPermission.java | 94 ++++++++ .../src/main/java/com/neo/entity/SysRole.java | 71 ++++++ .../main/java/com/neo/entity/UserInfo.java | 86 +++++++ .../java/com/neo/sevice/UserInfoService.java | 8 + .../neo/sevice/impl/UserInfoServiceImpl.java | 19 ++ .../main/java/com/neo/web/HomeController.java | 52 ++++ .../java/com/neo/web/UserInfoController.java | 40 ++++ .../src/main/resources/application.yml | 23 ++ .../src/main/resources/database/import.sql | 12 + .../src/main/resources/templates/403.html | 10 + .../src/main/resources/templates/index.html | 10 + .../src/main/resources/templates/login.html | 15 ++ .../main/resources/templates/userInfo.html | 10 + .../main/resources/templates/userInfoAdd.html | 10 + .../main/resources/templates/userInfoDel.html | 10 + .../neo/SpringBootShiroApplicationTests.java | 16 ++ 25 files changed, 1116 insertions(+), 1 deletion(-) create mode 100644 spring-boot-shiro/mvnw create mode 100644 spring-boot-shiro/mvnw.cmd create mode 100644 spring-boot-shiro/pom.xml create mode 100644 spring-boot-shiro/src/main/java/com/neo/SpringBootShiroApplication.java create mode 100644 spring-boot-shiro/src/main/java/com/neo/config/MyShiroRealm.java create mode 100644 spring-boot-shiro/src/main/java/com/neo/config/ShiroConfig.java create mode 100644 spring-boot-shiro/src/main/java/com/neo/dao/UserInfoDao.java create mode 100644 spring-boot-shiro/src/main/java/com/neo/entity/SysPermission.java create mode 100644 spring-boot-shiro/src/main/java/com/neo/entity/SysRole.java create mode 100644 spring-boot-shiro/src/main/java/com/neo/entity/UserInfo.java create mode 100644 spring-boot-shiro/src/main/java/com/neo/sevice/UserInfoService.java create mode 100644 spring-boot-shiro/src/main/java/com/neo/sevice/impl/UserInfoServiceImpl.java create mode 100644 spring-boot-shiro/src/main/java/com/neo/web/HomeController.java create mode 100644 spring-boot-shiro/src/main/java/com/neo/web/UserInfoController.java create mode 100644 spring-boot-shiro/src/main/resources/application.yml create mode 100644 spring-boot-shiro/src/main/resources/database/import.sql create mode 100644 spring-boot-shiro/src/main/resources/templates/403.html create mode 100644 spring-boot-shiro/src/main/resources/templates/index.html create mode 100644 spring-boot-shiro/src/main/resources/templates/login.html create mode 100644 spring-boot-shiro/src/main/resources/templates/userInfo.html create mode 100644 spring-boot-shiro/src/main/resources/templates/userInfoAdd.html create mode 100644 spring-boot-shiro/src/main/resources/templates/userInfoDel.html create mode 100644 spring-boot-shiro/src/test/java/com/neo/SpringBootShiroApplicationTests.java diff --git a/README.md b/README.md index 1e21444..362a6c7 100644 --- a/README.md +++ b/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-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-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实战开源软件) @@ -39,7 +40,8 @@ Spring boot使用的各种示例,以最简单、最实用为标准 - [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实战:我们的第一款开源软件](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)的形式反馈给我,我后续来完善。 diff --git a/README_EN.md b/README_EN.md index d427470..96f4ae9 100644 --- a/README_EN.md +++ b/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-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-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 diff --git a/spring-boot-shiro/mvnw b/spring-boot-shiro/mvnw new file mode 100644 index 0000000..5bf251c --- /dev/null +++ b/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 "$@" diff --git a/spring-boot-shiro/mvnw.cmd b/spring-boot-shiro/mvnw.cmd new file mode 100644 index 0000000..019bd74 --- /dev/null +++ b/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% diff --git a/spring-boot-shiro/pom.xml b/spring-boot-shiro/pom.xml new file mode 100644 index 0000000..3d357ea --- /dev/null +++ b/spring-boot-shiro/pom.xml @@ -0,0 +1,79 @@ + + + 4.0.0 + + com.neo + spring-boot-shiro + 0.0.1-SNAPSHOT + jar + + spring-boot-shiro + Demo project for Spring Boot + + + org.springframework.boot + spring-boot-starter-parent + 1.5.4.RELEASE + + + + + UTF-8 + UTF-8 + 1.8 + + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.boot + spring-boot-starter-thymeleaf + + + net.sourceforge.nekohtml + nekohtml + 1.9.22 + + + org.springframework.boot + spring-boot-starter-web + + + org.apache.shiro + shiro-spring + 1.4.0 + + + mysql + mysql-connector-java + runtime + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-devtools + true + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + + diff --git a/spring-boot-shiro/src/main/java/com/neo/SpringBootShiroApplication.java b/spring-boot-shiro/src/main/java/com/neo/SpringBootShiroApplication.java new file mode 100644 index 0000000..2766a39 --- /dev/null +++ b/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); + } +} diff --git a/spring-boot-shiro/src/main/java/com/neo/config/MyShiroRealm.java b/spring-boot-shiro/src/main/java/com/neo/config/MyShiroRealm.java new file mode 100644 index 0000000..7bdf951 --- /dev/null +++ b/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; + } + +} \ No newline at end of file diff --git a/spring-boot-shiro/src/main/java/com/neo/config/ShiroConfig.java b/spring-boot-shiro/src/main/java/com/neo/config/ShiroConfig.java new file mode 100644 index 0000000..00f524b --- /dev/null +++ b/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 filterChainDefinitionMap = new LinkedHashMap(); + // 配置不会被拦截的链接 顺序判断 + filterChainDefinitionMap.put("/static/**", "anon"); + //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了 + filterChainDefinitionMap.put("/logout", "logout"); + //:这是一个坑呢,一不小心代码就不好使了; + // + 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; + } +} \ No newline at end of file diff --git a/spring-boot-shiro/src/main/java/com/neo/dao/UserInfoDao.java b/spring-boot-shiro/src/main/java/com/neo/dao/UserInfoDao.java new file mode 100644 index 0000000..f24938d --- /dev/null +++ b/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 { + /**通过username查找用户信息;*/ + public UserInfo findByUsername(String username); +} \ No newline at end of file diff --git a/spring-boot-shiro/src/main/java/com/neo/entity/SysPermission.java b/spring-boot-shiro/src/main/java/com/neo/entity/SysPermission.java new file mode 100644 index 0000000..18f67b9 --- /dev/null +++ b/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 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 getRoles() { + return roles; + } + + public void setRoles(List roles) { + this.roles = roles; + } +} \ No newline at end of file diff --git a/spring-boot-shiro/src/main/java/com/neo/entity/SysRole.java b/spring-boot-shiro/src/main/java/com/neo/entity/SysRole.java new file mode 100644 index 0000000..9261866 --- /dev/null +++ b/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 permissions; + + // 用户 - 角色关系定义; + @ManyToMany + @JoinTable(name="SysUserRole",joinColumns={@JoinColumn(name="roleId")},inverseJoinColumns={@JoinColumn(name="uid")}) + private List 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 getPermissions() { + return permissions; + } + + public void setPermissions(List permissions) { + this.permissions = permissions; + } + + public List getUserInfos() { + return userInfos; + } + + public void setUserInfos(List userInfos) { + this.userInfos = userInfos; + } +} \ No newline at end of file diff --git a/spring-boot-shiro/src/main/java/com/neo/entity/UserInfo.java b/spring-boot-shiro/src/main/java/com/neo/entity/UserInfo.java new file mode 100644 index 0000000..63753b4 --- /dev/null +++ b/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 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 getRoleList() { + return roleList; + } + + public void setRoleList(List roleList) { + this.roleList = roleList; + } + + /** + * 密码盐. + * @return + */ + public String getCredentialsSalt(){ + return this.username+this.salt; + } + //重新对盐重新进行了定义,用户名+salt,这样就更加不容易被破解 +} \ No newline at end of file diff --git a/spring-boot-shiro/src/main/java/com/neo/sevice/UserInfoService.java b/spring-boot-shiro/src/main/java/com/neo/sevice/UserInfoService.java new file mode 100644 index 0000000..149b90c --- /dev/null +++ b/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); +} \ No newline at end of file diff --git a/spring-boot-shiro/src/main/java/com/neo/sevice/impl/UserInfoServiceImpl.java b/spring-boot-shiro/src/main/java/com/neo/sevice/impl/UserInfoServiceImpl.java new file mode 100644 index 0000000..58792d4 --- /dev/null +++ b/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); + } +} \ No newline at end of file diff --git a/spring-boot-shiro/src/main/java/com/neo/web/HomeController.java b/spring-boot-shiro/src/main/java/com/neo/web/HomeController.java new file mode 100644 index 0000000..d1c0696 --- /dev/null +++ b/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 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"; + } + +} \ No newline at end of file diff --git a/spring-boot-shiro/src/main/java/com/neo/web/UserInfoController.java b/spring-boot-shiro/src/main/java/com/neo/web/UserInfoController.java new file mode 100644 index 0000000..4e8bde7 --- /dev/null +++ b/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"; + } +} \ No newline at end of file diff --git a/spring-boot-shiro/src/main/resources/application.yml b/spring-boot-shiro/src/main/resources/application.yml new file mode 100644 index 0000000..6104d85 --- /dev/null +++ b/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 \ No newline at end of file diff --git a/spring-boot-shiro/src/main/resources/database/import.sql b/spring-boot-shiro/src/main/resources/database/import.sql new file mode 100644 index 0000000..224013c --- /dev/null +++ b/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); + + diff --git a/spring-boot-shiro/src/main/resources/templates/403.html b/spring-boot-shiro/src/main/resources/templates/403.html new file mode 100644 index 0000000..67ec640 --- /dev/null +++ b/spring-boot-shiro/src/main/resources/templates/403.html @@ -0,0 +1,10 @@ + + + + + Title + + +

403没有权限

+ + \ No newline at end of file diff --git a/spring-boot-shiro/src/main/resources/templates/index.html b/spring-boot-shiro/src/main/resources/templates/index.html new file mode 100644 index 0000000..34c3730 --- /dev/null +++ b/spring-boot-shiro/src/main/resources/templates/index.html @@ -0,0 +1,10 @@ + + + + + Title + + +

index

+ + \ No newline at end of file diff --git a/spring-boot-shiro/src/main/resources/templates/login.html b/spring-boot-shiro/src/main/resources/templates/login.html new file mode 100644 index 0000000..a4308af --- /dev/null +++ b/spring-boot-shiro/src/main/resources/templates/login.html @@ -0,0 +1,15 @@ + + + + + Title + + +错误信息:

+
+

账号:

+

密码:

+

+
+ + \ No newline at end of file diff --git a/spring-boot-shiro/src/main/resources/templates/userInfo.html b/spring-boot-shiro/src/main/resources/templates/userInfo.html new file mode 100644 index 0000000..3b3810d --- /dev/null +++ b/spring-boot-shiro/src/main/resources/templates/userInfo.html @@ -0,0 +1,10 @@ + + + + + Title + + +

用户查询界面

+ + \ No newline at end of file diff --git a/spring-boot-shiro/src/main/resources/templates/userInfoAdd.html b/spring-boot-shiro/src/main/resources/templates/userInfoAdd.html new file mode 100644 index 0000000..bc75fa5 --- /dev/null +++ b/spring-boot-shiro/src/main/resources/templates/userInfoAdd.html @@ -0,0 +1,10 @@ + + + + + Title + + +

用户添加界面

+ + \ No newline at end of file diff --git a/spring-boot-shiro/src/main/resources/templates/userInfoDel.html b/spring-boot-shiro/src/main/resources/templates/userInfoDel.html new file mode 100644 index 0000000..e413917 --- /dev/null +++ b/spring-boot-shiro/src/main/resources/templates/userInfoDel.html @@ -0,0 +1,10 @@ + + + + + Title + + +

用户删除界面

+ + \ No newline at end of file diff --git a/spring-boot-shiro/src/test/java/com/neo/SpringBootShiroApplicationTests.java b/spring-boot-shiro/src/test/java/com/neo/SpringBootShiroApplicationTests.java new file mode 100644 index 0000000..5581591 --- /dev/null +++ b/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() { + } + +} -- GitLab