spring-boot整合shiro

spring-boot可用於快速搭建java項目的手腳架,shiro是輕量級java安全框架,看demo中,如何把2者結合至一起。
spring-boot,視圖層推薦的是thymeleaf,考慮到shiro有jsp的標籤庫,我們demo使用jsp。

1.引入maven依賴

<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/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com</groupId>
	<artifactId>spring-boot-shiro</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>
	<name>spring-boot-shiro</name>
	<url>http://maven.apache.org</url>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.2.RELEASE</version>
	</parent>
	
	<properties>
	    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	    <!-- set thymeleaf version -->
	    <thymeleaf.version>3.0.10.RELEASE</thymeleaf.version>
	    <thymeleaf-layout-dialect.version>2.0.0</thymeleaf-layout-dialect.version>
	    <!--set java version-->
	    <java.version>1.8</java.version>
		<shiro-version>1.4.0</shiro-version>
		<druid.version>1.1.10</druid.version>

		<targetJavaProject>${basedir}/src/main/java</targetJavaProject>
		<targetMapperPackage>com.ly.dao</targetMapperPackage>
		<targetModelPackage>com.ly.entity</targetModelPackage>
		<!--  XML生成路徑  -->
		<targetResourcesProject>${basedir}/src/main/java</targetResourcesProject>
		<targetXMLPackage>mapper</targetXMLPackage>


	  </properties>

	<dependencies>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
			<exclusions>
				<exclusion>
					<groupId>org.springframework.boot</groupId>
					<artifactId>spring-boot-starter-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.3.2</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>

		<!-- 分頁插件 -->
		<dependency>
			<groupId>com.github.pagehelper</groupId>
			<artifactId>pagehelper-spring-boot-starter</artifactId>
			<version>1.2.5</version>
		</dependency>
		<!-- alibaba的druid數據庫連接池 -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid-spring-boot-starter</artifactId>
			<version>1.1.9</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-log4j2</artifactId>
		</dependency>

		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-core</artifactId>
			<version>${shiro-version}</version>
		</dependency>

		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-web</artifactId>
			<version>${shiro-version}</version>
		</dependency>

		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-ehcache</artifactId>
			<version>${shiro-version}</version>
		</dependency>

		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-quartz</artifactId>
			<version>${shiro-version}</version>
		</dependency>

		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-spring</artifactId>
			<version>${shiro-version}</version>
		</dependency>

		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
			<scope>provided</scope>
		</dependency>

		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>

		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>


	</dependencies>
	<build>

		<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
			<plugins>

				<plugin>
					<groupId>org.mybatis.generator</groupId>
					<artifactId>mybatis-generator-maven-plugin</artifactId>
					<version>1.3.2</version>
					<configuration>
						<configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
						<verbose>true</verbose>
						<overwrite>true</overwrite>
					</configuration>
					<executions>
						<execution>
							<id>Generate MyBatis Artifacts</id>
							<goals>
								<goal>generate</goal>
							</goals>
						</execution>
					</executions>
					<dependencies>
						<dependency>
							<groupId>org.mybatis.generator</groupId>
							<artifactId>mybatis-generator-core</artifactId>
							<version>1.3.2</version>
						</dependency>

						<dependency>
							<groupId>mysql</groupId>
							<artifactId>mysql-connector-java</artifactId>
							<version>5.1.46</version>
						</dependency>

					</dependencies>
				</plugin>


			</plugins>
		</pluginManagement>




		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

2.配置spring-shiro的java配置類

package com.ly.config;


import com.ly.service.PermissionService;
import com.ly.service.UserService;
import com.ly.shiro.filter.PermissionFilter;
import com.ly.shiro.filter.realm.SampleRealm;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

    private final String AUTHENTICATION_CACHE_NAME = "authenticationCache";
    private final String AUTHORIZATION_CACHE_NAME = "authenticationCache";

    @Bean("sampleRealm")
    public Realm realm(UserService userService, PermissionService permissionService){
        SampleRealm sampleRealm = new SampleRealm();
        sampleRealm.setUserService(userService);
        sampleRealm.setPermissionService(permissionService);
        sampleRealm.setCachingEnabled(true);
        sampleRealm.setAuthenticationCachingEnabled(true);
        sampleRealm.setAuthenticationCacheName(AUTHENTICATION_CACHE_NAME);
        sampleRealm.setAuthorizationCachingEnabled(true);
        sampleRealm.setAuthorizationCacheName(AUTHORIZATION_CACHE_NAME);
        return sampleRealm;
    }

    @Bean
    public SessionManager sessionManager(){
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setSessionValidationSchedulerEnabled(true);
        sessionManager.setSessionIdCookieEnabled(true);
        return sessionManager;
    }

    @Bean
    public CacheManager cacheManager(){
        EhCacheManager cacheManager = new EhCacheManager();
        cacheManager.setCacheManagerConfigFile("classpath:ehcache.xml");
        return  cacheManager;
    }

    @Bean
    public SecurityManager securityManager(Realm sampleRealm,SessionManager sessionManager,CacheManager cacheManager){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(sampleRealm);
        securityManager.setSessionManager(sessionManager);
        securityManager.setCacheManager(cacheManager);
        return securityManager;
    }

    @Bean("shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager, PermissionFilter permissionFilter){
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        factoryBean.setSecurityManager(securityManager);


        //oauth過濾
        Map<String, Filter> filters = new HashMap<>();
        filters.put("permission", permissionFilter);
        factoryBean.setFilters(filters);

        Map<String,String> filterMap = new HashMap<>();
        filterMap.put("/login","anon");
        filterMap.put("/unauthorized.jsp","anon");
        filterMap.put("/login.jsp","anon");
        filterMap.put("/logout","logout");
        filterMap.put("/**","user,permission");
        factoryBean.setFilterChainDefinitionMap(filterMap);
        return factoryBean;
    }


}

自定義shiro的相關配置類
最核心的
realm,securityManager,ShiroFilterFactoryBean 3個配置類,
realm: 用於認證,獲取角色,和權限數據,
securityManager: shiro的核心處理器,負責shiro各部分的組件的聚合,以及被委託處理subject對象的操作。
ShiroFilterFactoryBean: 權限訪問的url攔截配置。

3.權限設計

/*
Navicat MySQL Data Transfer

Source Server         : ly
Source Server Version : 50096
Source Host           : localhost:3306
Source Database       : shiro

Target Server Type    : MYSQL
Target Server Version : 50096
File Encoding         : 65001

Date: 2019-10-20 13:51:37
*/
CREATE DATABASE IF NOT EXISTS `shiro`;

USE `shiro`;



SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for permission
-- ----------------------------
DROP TABLE IF EXISTS `permission`;
CREATE TABLE `permission` (
  `id` bigint(20) unsigned NOT NULL auto_increment,
  `parent_id` bigint(20) default NULL COMMENT '父菜單ID,一級菜單爲0',
  `name` varchar(50) default NULL COMMENT '菜單名稱',
  `url` varchar(200) default NULL COMMENT '權限url,並不是真正的url,只是一個權限標識字符串',
  `type` int(11) default NULL COMMENT '類型   0:目錄   1:菜單   2:按鈕',
  `order_num` int(11) default NULL COMMENT '排序',
  `has_delete` tinyint(4) default '0' COMMENT '是否被刪除了 0:可用  1:被刪除',
  `create_time` datetime default NULL COMMENT '創建時間',
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of permission
-- ----------------------------
INSERT INTO `permission` VALUES ('1', '0', '權限管理', 'permission', '0', null, '0', '2019-07-20 19:33:49');
INSERT INTO `permission` VALUES ('2', '1', '添加', 'permission:create', '1', null, '0', '2019-07-21 19:34:48');
INSERT INTO `permission` VALUES ('3', '1', '編輯', 'permission:update', '1', null, '0', '2019-07-21 19:35:15');
INSERT INTO `permission` VALUES ('4', '1', '查詢', 'permission:select', '1', null, '0', '2019-07-21 19:36:11');
INSERT INTO `permission` VALUES ('5', '0', '用戶管理', 'user', '0', null, '0', '2019-07-20 20:07:00');
INSERT INTO `permission` VALUES ('6', '0', '角色管理', 'role', '0', null, '0', null);
INSERT INTO `permission` VALUES ('7', '6', '查詢', 'role:select', '1', null, '0', null);
INSERT INTO `permission` VALUES ('14', '5', '添加', 'user:add', '1', null, null, null);
INSERT INTO `permission` VALUES ('15', '5', '查看', 'user:select', '1', null, null, null);

-- ----------------------------
-- Table structure for role
-- ----------------------------
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
  `id` bigint(20) unsigned NOT NULL auto_increment,
  `role_name` varchar(100) default NULL COMMENT '角色名稱',
  `remark` varchar(100) default NULL COMMENT '備註',
  `has_delete` tinyint(4) default '0' COMMENT '是否被刪除了 0:可用  1:被刪除',
  `create_time` datetime default NULL COMMENT '創建時間',
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=201 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of role
-- ----------------------------
INSERT INTO `role` VALUES ('1', 'Z05P4H', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('2', '3ZL1H8', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('3', 'PU56FK', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('4', 'MGDF4A', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('5', '3KJ1LV', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('6', 'I0IKAO', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('7', 'KQ25GX', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('8', '8FERKL', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('9', 'BPMYYV', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('10', 'IX5ZE2', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('11', '3CE0T0', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('12', 'OCNAFC', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('13', 'E0U7FK', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('14', 'JY62TV', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('15', 'X1G21Y', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('16', 'OKTDCP', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('17', 'EXHKGI', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('18', '7K4ZKX', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('19', 'VK69S4', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('20', 'A3JIVT', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('21', 'I1QIB3', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('22', 'KHTJAT', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('23', '9UHURA', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('24', '5VWY3J', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('25', 'FJFIB1', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('26', '976AYX', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('27', 'PQLQWD', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('28', '2A9HJB', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('29', 'ZVIX3N', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('30', '2ABNEY', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('31', 'M641SW', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('32', '3SO014', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('33', 'KGLL8B', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('34', 'YS1U3Y', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('35', 'JR8UJ5', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('36', '5C7ZCT', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('37', '0KTFN1', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('38', '5P013D', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('39', 'N2CLWP', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('40', 'U41V8I', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('41', 'X2LS6H', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('42', 'W2LR36', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('43', 'KAT6EH', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('44', '8OQN1A', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('45', '9JTI2U', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('46', '1O71II', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('47', '2QH6IY', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('48', 'BOF23B', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('49', '87C4KG', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('50', 'KJZAHJ', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('51', '9OKUGU', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('52', 'RCE1YO', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('53', 'JMHMNB', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('54', 'OHC9AN', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('55', 'E36OWF', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('56', 'ERNWJZ', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('57', 'DU59S7', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('58', 'MGHZKT', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('59', 'CDSVZ8', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('60', 'BT45GS', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('61', 'JEBF6M', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('62', 'M78HQ7', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('63', 'SDJLBR', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('64', 'W9JWVO', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('65', 'SXAM9F', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('66', 'FTSI8N', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('67', 'KVMHJ9', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('68', 'QTX76C', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('69', '4OXOJQ', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('70', '24CF4C', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('71', 'CPF34D', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('72', 'IFMS49', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('73', 'VMHKC3', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('74', 'GYD25M', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('75', 'NDYL4S', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('76', 'MQRNXR', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('77', '0PJMHI', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('78', '30OG6I', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('79', '1N70F5', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('80', 'FN2BF7', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('81', 'Q0WFGZ', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('82', 'JR5HZF', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('83', '7Q3B76', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('84', '7IW0EY', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('85', 'L2MUDA', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('86', 'CWGLNE', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('87', '391G47', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('88', 'NNAKWT', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('89', 'DF20T2', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('90', 'V8ITJ9', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('91', 'RYJUKA', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('92', 'S46LD2', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('93', '8XYZ4L', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('94', 'MDXJZ8', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('95', '7B05P1', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('96', '28X071', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('97', 'MZ3I7L', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('98', '9K3QDP', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('99', 'CM5USD', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('100', 'IEG5EK', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('101', 'MFA60H', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('102', 'CCPG7O', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('103', 'RQEU0G', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('104', 'B5WZ86', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('105', '9RZNBO', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('106', 'F4CBM2', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('107', 'JIX3O3', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('108', 'H6C83U', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('109', 'USCCQN', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('110', '2FV4YG', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('111', 'FSMS1T', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('112', 'X9HNS1', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('113', 'RRIAWM', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('114', 'GDKOPG', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('115', '7OSUVS', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('116', 'DJJ41R', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('117', 'O4NT45', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('118', 'CDQNYX', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('119', 'QWAPO9', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('120', 'CXJZ9D', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('121', '27WUJ5', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('122', '30T1RN', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('123', 'ZXPQMV', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('124', 'GO3EPC', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('125', 'KSA3KM', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('126', 'CT46HX', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('127', '78IVUK', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('128', 'D4I6DC', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('129', 'N4QBBO', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('130', 'F5HZF5', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('131', 'GW52V6', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('132', '8NL1CO', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('133', 'EV56GR', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('134', 'DMZ2EU', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('135', 'X77DBG', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('136', 'A2IB4N', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('137', 'U9R237', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('138', 'R8WQ21', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('139', '114I8J', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('140', '2O851O', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('141', 'CQKPRQ', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('142', 'DOACYN', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('143', 'GCBLY0', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('144', '5TKE93', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('145', 'QESRH2', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('146', 'XGGV3S', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('147', 'MT8OQK', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('148', 'OOEZQO', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('149', '7Y8AOK', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('150', 'TEJIW0', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('151', 'COEWD5', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('152', 'LJY3MV', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('153', 'J0G7NM', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('154', '9CZVDA', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('155', 'CT2XGG', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('156', 'V1JLBU', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('157', 'AWLAOH', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('158', 'FN03G1', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('159', 'STOZXM', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('160', 'E28VOS', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('161', 'W52U1O', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('162', '9BRV4Z', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('163', 'LZ4P6Q', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('164', '4EMYWN', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('165', 'INOG8S', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('166', 'B5SI7H', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('167', 'VTJ7GM', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('168', 'S0PKON', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('169', '72PCN8', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('170', '7B0180', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('171', 'DSTSGX', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('172', 'BRXANG', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('173', 'B6ZF5H', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('174', 'W4X9IU', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('175', 'LHKGKI', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('176', 'VUKAS0', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('177', 'QLVHSK', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('178', 'FH6C70', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('179', 'G9Z2G0', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('180', 'RQETW0', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('181', 'F0U7HU', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('182', 'R8UKC1', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('183', '6Q3BAJ', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('184', 'THX63Z', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('185', 'LZ72RJ', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('186', 'GNWIVW', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('187', 'SA4QCF', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('188', '7PXK0D', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('189', 'T0JPXH', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('190', 'OWIWVP', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('191', 'WEAAJS', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('192', 'DHB6WY', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('193', '5VUNRT', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('194', 'TNRW8I', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('195', 'SHYE38', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('196', 'XY05O0', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('197', '000015', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('198', 'LK3RI8', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('199', 'OQJL9M', null, '0', '2019-06-16 19:30:00');
INSERT INTO `role` VALUES ('200', 'AJTI3W', null, '0', '2019-06-16 19:30:00');

-- ----------------------------
-- Table structure for role_permission
-- ----------------------------
DROP TABLE IF EXISTS `role_permission`;
CREATE TABLE `role_permission` (
  `id` bigint(20) unsigned NOT NULL auto_increment,
  `role_id` bigint(20) default NULL COMMENT '角色ID',
  `pid` bigint(20) default NULL COMMENT '權限ID',
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=40 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of role_permission
-- ----------------------------
INSERT INTO `role_permission` VALUES ('21', '3', '1');
INSERT INTO `role_permission` VALUES ('22', '3', '2');
INSERT INTO `role_permission` VALUES ('23', '3', '3');
INSERT INTO `role_permission` VALUES ('24', '3', '4');
INSERT INTO `role_permission` VALUES ('25', '2', '1');
INSERT INTO `role_permission` VALUES ('26', '2', '2');
INSERT INTO `role_permission` VALUES ('27', '2', '3');
INSERT INTO `role_permission` VALUES ('28', '2', '4');
INSERT INTO `role_permission` VALUES ('29', '2', '5');
INSERT INTO `role_permission` VALUES ('30', '2', '14');
INSERT INTO `role_permission` VALUES ('31', '2', '6');
INSERT INTO `role_permission` VALUES ('32', '2', '7');
INSERT INTO `role_permission` VALUES ('33', '1', '1');
INSERT INTO `role_permission` VALUES ('34', '1', '2');
INSERT INTO `role_permission` VALUES ('35', '1', '3');
INSERT INTO `role_permission` VALUES ('36', '1', '5');
INSERT INTO `role_permission` VALUES ('37', '1', '14');
INSERT INTO `role_permission` VALUES ('38', '1', '15');
INSERT INTO `role_permission` VALUES ('39', '1', '6');

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` bigint(20) unsigned NOT NULL auto_increment,
  `username` varchar(50) NOT NULL COMMENT '用戶名',
  `password` varchar(100) default NULL COMMENT '密碼',
  `salt` varchar(20) default NULL COMMENT '鹽',
  `email` varchar(100) default NULL COMMENT '郵箱',
  `mobile` varchar(100) default NULL COMMENT '手機號',
  `status` tinyint(4) default NULL COMMENT '狀態  0:禁用  1:正常',
  `has_delete` tinyint(4) default '0' COMMENT '是否被刪除了 0:可用  1:被刪除',
  `create_time` datetime default NULL COMMENT '創建時間',
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', 'ly', 'a', null, null, null, null, '0', null);

-- ----------------------------
-- Table structure for user_role
-- ----------------------------
DROP TABLE IF EXISTS `user_role`;
CREATE TABLE `user_role` (
  `id` bigint(20) unsigned NOT NULL auto_increment,
  `user_id` bigint(20) default NULL COMMENT '用戶ID',
  `role_id` bigint(20) default NULL COMMENT '角色ID',
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of user_role
-- ----------------------------
INSERT INTO `user_role` VALUES ('1', '1', '1');



權限設計比較簡單,用戶和角色,一對多,角色和權限一對多。demo爲了方便操作,採用的是用戶和角色1對1,角色和權限1對多。
shiro具體的realm如下

package com.ly.shiro.filter.realm;

import com.ly.entity.Permission;
import com.ly.entity.Role;
import com.ly.entity.User;
import com.ly.service.PermissionService;
import com.ly.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class SampleRealm extends AuthorizingRealm {

    private UserService userService;

    private PermissionService permissionService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String username = (String) SecurityUtils.getSubject().getPrincipal();
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();

        Session session = SecurityUtils.getSubject().getSession();
        User user = (User) session.getAttribute("loginUserInfo");

        if(user != null){
            Set<String> roleSets = new HashSet<>();
            List<Integer> roleIds = new ArrayList<>();
            if(user.getRoleList() != null){
                for(Role role:user.getRoleList()){
                    roleSets.add(role.getRoleName());
                    roleIds.add(role.getId());
                }
            }
            simpleAuthorizationInfo.setRoles(roleSets);

            Permission permission = new Permission();
            permission.setRoleIds(roleIds);
            List<Permission> permissionList = permissionService.selectPermission(permission);
            Set<String> permissionSet = new HashSet<>();
            if(permissionList != null){
                for(Permission p:permissionList){
                    permissionSet.add(p.getUrl());
                }
            }
            simpleAuthorizationInfo.setStringPermissions(permissionSet);

        }

        return simpleAuthorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String username = (String)authenticationToken.getPrincipal();
        String password = new String((char[]) authenticationToken.getCredentials());

        User user = new User();
        user.setUsername(username);
        user.setPassword(password);

        User result = userService.login(user);
        if(result == null){
            throw new AccountException("賬號不存在或密碼錯誤");
        }

        Session session = SecurityUtils.getSubject().getSession();
        session.setAttribute("loginUserInfo",result);

        return new SimpleAuthenticationInfo(
            username,password,getName()
        );
    }

    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    @Override
    public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
        super.clearCachedAuthorizationInfo(principals);
    }

    @Override
    public void clearCachedAuthenticationInfo(PrincipalCollection principals) {
        super.clearCachedAuthenticationInfo(principals);
    }

    @Override
    public void clearCache(PrincipalCollection principals) {
        super.clearCache(principals);
    }

    public void clearAllCachedAuthorizationInfo() {
        getAuthorizationCache().clear();
    }

    public void clearAllCachedAuthenticationInfo() {
        getAuthenticationCache().clear();
    }

    public void clearAllCache() {
        clearAllCachedAuthenticationInfo();
        clearAllCachedAuthorizationInfo();
    }

    public PermissionService getPermissionService() {
        return permissionService;
    }

    public void setPermissionService(PermissionService permissionService) {
        this.permissionService = permissionService;
    }
}

4.權限url的驗證和攔截

系統在初始化時,會讀取classpath下面的shiro_auth.properties文件,該文件保存這權限字符串和實際的url地址的映射。
在這裏插入圖片描述
會保存到一個map對象中,以url爲key,value爲權限字符串。
具體的過濾器攔截如下

package com.ly.shiro.filter;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

@Component("permissionFilter")
public class PermissionFilter extends AccessControlFilter implements InitializingBean {

	private Map<String,String> urlMappingMap;

	@Autowired
	private urlMappingPermissionReader reader;


	@Override
	protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {

		Subject subject = SecurityUtils.getSubject();
		if(null != mappedValue){
			String[] arra = (String[])mappedValue;
			for (String permission : arra) {
				if(subject.isPermitted(permission)){
					return Boolean.TRUE;
				}
			}
		}

		HttpServletRequest httpRequest = ((HttpServletRequest)request);
		String uri = httpRequest.getRequestURI();//獲取URI
		String basePath = httpRequest.getContextPath();//獲取basePath
		if(null != uri && uri.startsWith(basePath)){
			uri = uri.replaceFirst(basePath, "");
			//從map中獲取真實的url映射的權限url,從而判斷用戶的權限集合中是否存在對應的權限
			String permissionUrl = urlMappingMap.get(uri);
			if(!StringUtils.isEmpty(permissionUrl)){
				if(subject.isPermitted(permissionUrl)){
					return Boolean.TRUE;
				}
			}else{
				//如果沒有真實的url沒有建立,其對應關係,就返回true
				return true;
			}

		}



		return false;
	}

	@Override
	protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {

		WebUtils.toHttp(response).sendError(HttpServletResponse.SC_UNAUTHORIZED);
		return false;
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		urlMappingMap = reader.getMappingMap();
	}
}

執行腳本
在這裏插入圖片描述
輸入地址訪問:
http://localhost:9090/shiro/login.jsp

4.相關代碼

https://github.com/haozhi-ly/spring-boot-tutorial/tree/master/spring-boot-shiro

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章