一 、shiro框架

Shiro是Apache 的一个强大且易用的Java安全框架,执行身份验证、授权、密码学和会话管理。Shiro 主要分为两个部分就是认证和授权两部分

1.Subject代表了当前用户的安全操作

2.SecurityManager:它是Shiro框架的核心,典型的Facade模式,Shiro通过SecurityManager来管理内部组件实例,并通过它来提供安全管理的各种服务。

3.Authenticator即认证器,对用户身份进行认证,Authenticator是一个接口,shiro提供ModularRealmAuthenticator实现类,通过ModularRealmAuthenticator基本上可以满足大多数需求,也可以自定义认证器。

4.Authorizer即授权器,用户通过认证器认证通过,在访问功能时需要通过授权器判断用户是否有此功能的操作权限。

5.Realm充当了Shiro与应用安全数据间的“桥梁”或者“连接器”。也就是说,当对用户执行认证(登录)和授权(访问控制)验证时,Shiro会从应用配置的Realm中查找用户及其权限信息。

6.sessionManager即会话管理,shiro框架定义了一套会话管理,它不依赖web容器的session,所以shiro可以使用在非web应用上。

二:引入依赖

<?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>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>ch06</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>ch06</name>
<description>Demo project for Spring Boot</description>
<packaging>jar</packaging> <properties>
<java.version>1.8</java.version>
<druid.verzion>1.1.10</druid.verzion>
<pagehelper.version>1.2.10</pagehelper.version>
<mybatis.version>2.0.0</mybatis.version>
<thymeleaf-layout-dialect.version>2.0.4</thymeleaf-layout-dialect.version>
</properties> <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- 排除默认的tomcat -->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency> <!-- 重新依赖Jetty的starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jetty</artifactId>
</dependency> <dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.version}</version>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency> <dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency> <!--shiro整合spring-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency> <dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.verzion}</version>
</dependency> <!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper-spring-boot-starter -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${pagehelper.version}</version>
</dependency> <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</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>
<plugins>
<!-- spring boot maven插件 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- 跳过单元测试 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build> </project>

二:yml配置:

1.application-dao.yml

# spring整合配置
spring:
# 数据源配置
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/weather?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC
username: root
password: root
# 使用druid连接池,当使用其他连接池的时候,可以指定type类型为对应的数据源
type: com.alibaba.druid.pool.DruidDataSource
druid:
maxActive: 1000
initialSize: 10
maxWait: 1000
minIdle: 10
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: select 1
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
maxPoolPreparedStatementPerConnectionSize: 0
# 监控
stat-view-servlet:
url-pattern: /druid/*
reset-enable: false
login-username: admin
login-password: admin
allow: 127.0.0.1
web-stat-filter:
url-pattern: /*
exclusions: /druid/*,*.js,*.css,*.html,*.png,*.jpg
# mybatis配置
mybatis:
type-aliases-package: edu.nf.ch06.entity
mapper-locations: classpath:/mapper/*.xml
# 分页插件配置
pagehelper:
# 数据库方言
helper-dialect: mysql
# 分页合理化参数,默认值为false。当该参数设置为 true 时,pageNum<=0 时会查询第一页
reasonable: true
# 分页参数
support-methods-arguments: true

2.application-dao.yml

# web容器配置
server:
# 设置tomcat(如果切换了Jetty,
# 那么这里换成Jetty的相关配置,并把tomcat的配置注释)
#tomcat:
#uri-encoding: UTF-8
# 指定端口
port: 8081
# 指定项目的ContextPath路径,8080后面紧跟着的项目名
servlet:
context-path: /ch06
spring:
# 配置http字符编码过滤器配置(CharacterEncodingFilter)
http:
encoding:
charset: UTF-8
enabled: true
force: true
# jackson日期格式化和时区设置
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8

三:导入数据库(这里用city_name当做用户名,city_code做为密码)

/*
Navicat Premium Data Transfer Source Server : 192.168.5.8
Source Server Type : MySQL
Source Server Version : 50723
Source Host : localhost:3306
Source Schema : weather Target Server Type : MySQL
Target Server Version : 50723
File Encoding : 65001 Date: 12/07/2019 16:08:07
*/ SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0; -- ----------------------------
-- Table structure for city_info
-- ----------------------------
DROP TABLE IF EXISTS `city_info`;
CREATE TABLE `city_info` (
`city_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '城市编号',
`city_name` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '城市名称',
`city_code` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '城市编码',
`province` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '省份',
`url` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`city_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ----------------------------
-- Records of city_info
-- ----------------------------
INSERT INTO `city_info` VALUES (1, '江西', '', NULL, 'add:user');
INSERT INTO `city_info` VALUES (2, '广东', '', NULL, 'update:user'); SET FOREIGN_KEY_CHECKS = 1;

四:Controller层

package edu.nf.ch06.controller;

import edu.nf.ch06.entity.City;
import edu.nf.ch06.service.CityService;
import edu.nf.ch06.vo.ResponseVO;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import java.util.List; /**
* @author ywb
* @date 2019-07-08
*/
@RestController
public class CityController extends BaseController{ @Autowired
private CityService cityService; @GetMapping("/list_city") public ResponseVO listCity(){
List<City> list = cityService.listCity();
return success(list);
}
  
@RequestMapping("/add")
public String add(){
System.out.println("具有添加权限");
return "具有add权限";
}
@RequestMapping("/update")
public String update(){
System.out.println("具有修改权限");
return "具有update权限";
} @RequestMapping("/test")
@RequiresPermissions(value={"weather:city:test","super"})
public String test(){
System.out.println("测试权限");
return "测试注解RequiresPermissions是否有用";
} @RequestMapping("/index")
@RequiresRoles(value={"江西"})
public String index(){
System.out.println("修改");
return "江西登入的用户有此权限";
} @RequestMapping("/unAuth")
public String unAuth(){
System.out.println("修改");
return "未经授权,无法访问此页面";
} @RequestMapping("/login")
public String login(String cityName, String cityCode, Model model){
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(cityName,cityCode);
try {
subject.login(token);
return "登入成功";
} catch (UnknownAccountException e) {
model.addAttribute("msg","用户名不存在");
return "用户名错误";
} catch (IncorrectCredentialsException e) {
model.addAttribute("msg","密码错误");
return "密码错误";
}
} }

五:Shiro配置类

package edu.nf.ch06.shiro;

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.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver; import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Properties; /**
* @author : ywb
* @date : 2019/7/8
*/
@Configuration
public class ShiroConfig { @Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//设置安全管理器
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
//添加一些Shiro的内置过滤器
/**
* Shiro 的内置过滤器可以实现权限的相关拦截
* 常用过滤器
* 1.anon:无需认证
* 2.authc:必须认证才能访问
* 3.user:如果使用rememberme功能可以访问
* 4.perms:该资源必须得到资源权限才能访问
* 5.role:该资源必须得到权限资源脆才能访问
*/
Map<String,String> filterMap =new LinkedHashMap<String,String>();
// filterMap.put("/list_city","authc");
// filterMap.put("/add","anon");
// filterMap.put("/update","anon");
filterMap.put("/login","anon");
filterMap.put("/add","perms[add:user]");
filterMap.put("/update","perms[update:user]");
// filterMap.put("list_city","authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
//授权过滤器
//注意当授权拦截后,shiro会自动跳转到未授权的页面 //修改调整的登入页面
// shiroFilterFactoryBean.setLoginUrl("");
//登入失败之后需要跳转的页面或需要请求的接口
shiroFilterFactoryBean.setUnauthorizedUrl("/unAuth");
return shiroFilterFactoryBean;
}
@Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("weatherRealm") WeatherRealm weatherRealm){
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
//DefaultWebSecurityManager需要关联一个Realm
defaultWebSecurityManager.setRealm(weatherRealm);
return defaultWebSecurityManager;
}
/**
* 创建realm
*/
@Bean(name = "weatherRealm")
public WeatherRealm getRealm(){
return new WeatherRealm();
} /**
* 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions)
* 配置以下两个bean(DefaultAdvisorAutoProxyCreator和AuthorizationAttributeSourceAdvisor)即可实现此功能
* @return
*/
@Bean
public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
advisorAutoProxyCreator.setProxyTargetClass(true);
return advisorAutoProxyCreator;
} /**
* 开启 shiro 的@RequiresPermissions注解
* @param securityManager
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
} /**
* shiro出现权限异常可通过此异常实现制定页面的跳转(或接口跳转)
* @return
*/
@Bean
public SimpleMappingExceptionResolver simpleMappingExceptionResolver() {
SimpleMappingExceptionResolver resolver = new SimpleMappingExceptionResolver();
Properties properties = new Properties(); /*未授权处理页*/
properties.setProperty("org.apache.shiro.authz.UnauthorizedException", "/error.html");
/*身份没有验证*/
properties.setProperty("org.apache.shiro.authz.UnauthenticatedException", "/error.html");
resolver.setExceptionMappings(properties);
return resolver;
} }

2.WeatherRealm.java

package edu.nf.ch06.shiro;

import edu.nf.ch06.dao.CityDao;
import edu.nf.ch06.entity.City;
import edu.nf.ch06.service.CityService;
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.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired; import java.util.ArrayList;
import java.util.List; /**
* @author : ywb
* @date : 2019/7/8
*/
public class WeatherRealm extends AuthorizingRealm {
@Autowired
private CityService cityService;
/**
* 执行授权逻辑
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行授权逻辑");
//给资源进行授权
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// info.addStringPermission("user:add"); List<String> roles = new ArrayList<>();
Subject subject = SecurityUtils.getSubject();
City city = (City)subject.getPrincipal();
City dbCity = cityService.findUserById(city.getCityId());
info.addStringPermission(dbCity.getUrl());
roles.add(dbCity.getCityName());
info.addRoles(roles);
return info;
} /**
* 执行认证逻辑
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { // String userName = "ywb";
// String password = "123";
UsernamePasswordToken passwordToken = (UsernamePasswordToken)authenticationToken;
City city = cityService.getCityByName(passwordToken.getUsername());
//取出用户名并且判断用户名是否和数据库一致
if(city==null){
return null;//Shiro底层有抛出一个异常表示用户名不存在
}
System.out.println("执行认证逻辑");
//判断密码
return new SimpleAuthenticationInfo(city,city.getCityCode(),"");
}
}

六:测试

1.通过用户名:江西 登入的用户具有添加没有修改权限

2.通过用户名:广东登入的用户具有修改没有添加权限

3.需要了解更多进入:http://shiro.apache.org/

Springboot+Shiro+Mybatis+mysql的更多相关文章

  1. Springboot集成mybatis(mysql),mail,mongodb,cassandra,scheduler,redis,kafka,shiro,websocket

    https://blog.csdn.net/a123demi/article/details/78234023  : Springboot集成mybatis(mysql),mail,mongodb,c ...

  2. SpringBoot+Shiro+mybatis整合实战

    SpringBoot+Shiro+mybatis整合 1. 使用Springboot版本2.0.4 与shiro的版本 引入springboot和shiro依赖 <?xml version=&q ...

  3. SpringBoot 整合 Mybatis + Mysql——XML配置方式

    一.介绍 SpringBoot有两种方法与数据库建立连接,一种是集成Mybatis,另一种用JdbcTemplate,本文主要讨论集成Mybatis方式. SpringBoot整合Mybatis也有两 ...

  4. shiro学习(五、springboot+shiro+mybatis+thymeleaf)

    入门shiro(感觉成功了)首先感谢狂神,然后我就一本正经的复制代码了 项目结构 运行效果 数据库 <dependencies> <!-- thymeleaf-shiro整合包 -- ...

  5. SpringBoot 使用Mybatis+MySql

    pom配置 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http: ...

  6. springboot+eureka+mybatis+mysql环境下报504 Gateway Time-out

    1.test环境下的数据库配置的 driver和url有问题, 在工程日志中的表现是不能打印出最新的日志,在部署前的日志能看到报错:

  7. SpringBoot&Shiro实现用户认证

    SpringBoot&Shiro实现用户认证 实现思路 思路:实现认证功能主要可以归纳为3点 1.定义一个ShiroConfig配置类,配置 SecurityManager Bean , Se ...

  8. springboot + shiro + mysql + mybatis 工程快速搭建

    1. 新建 springboot 工程 2. 随便起个名字 3. 初始化工程 4. 导入 shiro 和 thymeleaf 依赖 <!-- thymeleaf依赖 --> <dep ...

  9. SpringBoot整合mybatis、shiro、redis实现基于数据库的细粒度动态权限管理系统实例

    1.前言 本文主要介绍使用SpringBoot与shiro实现基于数据库的细粒度动态权限管理系统实例. 使用技术:SpringBoot.mybatis.shiro.thymeleaf.pagehelp ...

随机推荐

  1. Java虚拟机详解(五)------JVM参数(持续更新)

    JVM参数有很多,其实我们直接使用默认的JVM参数,不去修改都可以满足大多数情况.但是如果你想在有限的硬件资源下,部署的系统达到最大的运行效率,那么进行相关的JVM参数设置是必不可少的.下面我们就来对 ...

  2. 网页如何设置favicon.ico

    1.首先制作ico图,并命名favicon.ico 2.将文件放在项目的根目录下

  3. (18)ASP.NET Core 基于现有数据库创建EF模型(反向工程)

    1.简介 Entity Framework Core可通过数据库提供给应用程序的插件访问许多不同的数据库.我们可以通过使用Entity Framework Core构建执行基本数据访问的ASP.NET ...

  4. imwrite imshow机制

    今天在做数据增强的时候,遇到一个奇怪的问题.调用imwite生成的图片,在本地用图片查看器打开的时候是正常的.但是在代码里imshow的时候是一片亮白. 代码类似如下 gaussian_img = a ...

  5. testng学习笔记-- 场景和module

    一.定义 TestNG是一个测试框架,其灵感来自JUnit和NUnit,但引入了一些新的功能,使其功能更强大,使用更方便. TestNG是一个开源自动化测试框架;TestNG表示下一代(Next Ge ...

  6. 从零开始搭建前后端分离的NetCore(EF Core CodeFirst+Au)+Vue的项目框架之二autofac解耦

    在 上一篇 中将项目的基本骨架搭起来能正常跑通,这一篇将讲到,如何通过autofac将DbContext和model进行解耦,只用添加model,而不用在DbContext中添加DbSet. 在这里就 ...

  7. Springboot整合html 报java.lang.IllegalArgumentException: Root element name cannot be null

    解决: <!DOCTYPE><html> 改为 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitiona ...

  8. vue-cli报错:Class constructor FileManager cannot be invoked without 'new'

    bug:vue-cli3开发的项目,今天项目重新下载依赖启动项目的时候出现错误:Class constructor FileManager cannot be invoked without 'new ...

  9. 9043Markdown常用用法

    1.标题 1.1 方法一:==和--标记 =和-标记语法格式如下: 我是标题一 == 我是标题二 -- 组成: 1标题文字:我是标题一 2回车换行 3标记:== (为一级标题)--(为二级标题) 效果 ...

  10. Cassandra查询操作趟坑记录

    例子表 CREATE TABLE employee ( name TEXT, age SMALLINT, phone TEXT, bornDate DATE, createDate timestamp ...