文章目录

  • 开篇必读:
  • 一、开发环境
  • 二、项目搭建
  • 三、配置 shiro 配置类
    • 1、自定义 Realm 类。
    • 2、创建shiro配置类。
  • 四、创建页面、Controller、 Service等。
  • 五、修改自定义 MyRealm
  • 六、配置资源访问权限 ShiroConfig

开篇必读:

shiro这个框架虽然学习难度不高,但是底层封装很深,一篇博客也讲不明白,这东西估计得再写几篇文章,这篇文章主要是搭建一下shiro的项目架构,有shiro的基础功能。后期要添加的东西也不少,以这篇博客搭建的项目为基础,要想学shiro得一段时间,不是说你懂了就是你会了,你得动手写代码。键盘敲不烂,薪资不过万。后面继续更新,全部看完咱们不敢保证你一定会学会shiro,但一定会有收获。
坚持!

一、开发环境

名称 版本
IntelliJ IDEA 2019.3.5 x64
JDK 1.8
MySQL mysql-5.7.31-winx64
SpringBoot 2.0+
Maven apache-maven-3.6.3
shiro 1 .4.0
MyBatis 2.1.0

二、项目搭建

1、创建一个SpringBoot项目导入相关pom依赖:

   <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.2.RELEASE</version><relativePath/><!-- lookup parent from repository --></parent><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.1.3.RELEASE</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><version>2.1.3.RELEASE</version><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.1.3.RELEASE</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><scope>test</scope><version>4.12</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><!--连接池--><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.16</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.4.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.0</version></dependency><dependency><groupId>com.github.theborakompanioni</groupId><artifactId>thymeleaf-extras-shiro</artifactId><version>2.0.0</version></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><fork>true</fork><addResources>true</addResources></configuration></plugin></plugins></build>
</project>

2、在 resources 中创建 application.yml 配置文件。
详细配置如下:
如果你的idea是老版本可能因为系统找不到MyBatis的mapper目录而报错,你可以在resource 目录下创建mapper文件夹,也可以将 yml 配置文件中与MyBatis相关的配置暂时关掉 (注释掉的意思,配置文件中注释使用#号)。

server:port: 8080
spring:application:name: shiro-springbootdatasource:url: jdbc:mysql://localhost:3306/hibernateusername: rootpassword: 123456driver-class-name: com.mysql.jdbc.Drivertype: com.alibaba.druid.pool.xa.DruidXADataSourcethymeleaf:cache: falsemvc:static-path-pattern: /templates/user/**
mybatis:mapper-locations: classpath:mapper/*.xmltype-aliases-package: com.zkr.mingyu.entityconfiguration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
logging:level:com.example.demo.dao : debug

SpringBoot开启热部署方法如下:见我另一篇博客介绍。
飞机票:SpringBoot 项目如何开启热部署

3、创建 SpringBoot 启动器 Application.class:

启动类源码:

package com.zkr.mingyu;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class,args);}}

测试项目是否可以正常启动,访问 localhost:8080 端口,查看是否运行正常。

三、配置 shiro 配置类

目前的项目目录:

编写配置类与 SpringBoot 进行整合。
配置类内容具体如下:
从底层往上描述:
如果页面中不使用shiro标签,也可以不写Shiro与Thymeleaf整合配置类。

  1. 自定义Realm。
  2. 创建 安全管理器 DefaultWebSecuityManager。
  3. 创建 ShiroFilterFactoryBean
  4. Shiro与Thymeleaf整合配置类。为了页面支持shiro标签)。

全文最重要最关键的两个点,一个是自定义 Realm 以及shiro 的配置类了。全文核心

1、自定义 Realm 类。

(1)创建 MyRealm 类,继承 AuthorizingRealm 类,必须继承。
(2)实现 doGetAuthorizationInfo、doGetAuthenticationInfo 方法。
要实现登录,doGetAuthenticationInfo 是核心,账号密码在doGetAuthenticationInfo() 方法中做校验。
而授权操作则在 doGetAuthorizationInfo() 方法中操作,比如页面资源限制,用户可以访问哪个资源,执行哪些操作等。都在这个方法中配置。

package com.zkr.mingyu.shiro;import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;import java.io.Serializable;public class MyRealm extends AuthorizingRealm implements Serializable {/*** 授权* @param principals* @return*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {System.out.println("执行授权方法: doGetAuthorizationInfo");return null;}/*** 认证* @param token* @return* @throws AuthenticationException*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {System.out.println("执行认证方法: doGetAuthenticationInfo");return null;}
}

2、创建shiro配置类。

这个配置类很重要,仔细读一下,一环扣一环。后期密码加密(MD5 + salt + 散列)都在这个类中配置,以及与 Thymeleaf 整合配置等等。

package com.zkr.mingyu.config;import com.zkr.mingyu.shiro.MyRealm;
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;/**标注 @Configuration 注解,* 标注这是一个配置类,* 让项目启动时加载该配置类。*/
@Configuration
public class ShiroConfig {/*** 创建ShiroFilterFactory* 设置权限规则 需要注入securityManage* @param securityManager* @return*/@Beanpublic ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager){ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();shiroFilterFactoryBean.setSecurityManager(securityManager);return shiroFilterFactoryBean;}/*** 创建安全管理器,* 并为 securityManager 注入自定义的 Realm 类* @param realm* @return*/@Beanpublic DefaultWebSecurityManager getSecurityManager(MyRealm realm){DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();securityManager.setRealm(realm);return securityManager;}/*** 配置自定义 Realm 类* @Bean 将 MyRealm 注入到 Spring 容器当中* @return*/@Beanpublic MyRealm getMyRealm(){return new MyRealm();}}

四、创建页面、Controller、 Service等。

1、在 resource 目录下创建 templeates 文件夹,用来存放 html 页面。并创建index、 login 页面。
index:

login:

2、Controller、 Service、 dao 等
现在的目录结构:

Controller:

package com.zkr.mingyu.controller;import com.zkr.mingyu.entity.User;
import com.zkr.mingyu.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;import javax.annotation.Resource;@Controller
public class UserController {@Resourceprivate UserService userService;@RequestMapping("/index")public String login(User user, Model model) {Subject subject = SecurityUtils.getSubject();UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword());try {subject.login(token);return "index";} catch (UnknownAccountException e) {model.addAttribute("msg", "用户名错误!");return "login";} catch (IncorrectCredentialsException e) {model.addAttribute("msg", "密码错误!");return "login";}}@RequestMapping("/login")public String index() {return "login";}@RequestMapping("/loginOut")public String loginOut() {Subject subject = SecurityUtils.getSubject();subject.logout();return "login";}@RequestMapping("/update")public String update() {return "/user/update";}}

Service:

package com.zkr.mingyu.service;import com.zkr.mingyu.entity.User;
import org.apache.ibatis.annotations.Param;public interface UserService {/*** 根据用户名查找用户* @param userName* @return*/User findByUserName(@Param("username") String userName);}

ServiceImpl:

package com.zkr.mingyu.service;import com.zkr.mingyu.dao.UserMapper;
import com.zkr.mingyu.entity.User;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import javax.annotation.Resource;@Service
@Transactional //开启事务
public class UserServiceImpl implements UserService {@Resourceprivate UserMapper userMapper;@Overridepublic User findByUserName(String userName) {return userMapper.findByUserName(userName);}
}

Dao:

package com.zkr.mingyu.dao;import com.zkr.mingyu.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;@Mapper
public interface UserMapper {/*** 根据用户名查找用户* @param userName* @return*/User findByUserName(@Param("username") String userName);}

entity:

package com.zkr.mingyu.entity;import java.io.Serializable;public class User implements Serializable {/*** id*/private Integer id;/*** 账号*/private String username;/*** 密码*/private String password;/*** 权限*/private String auth;/*** 随机盐*/private String salt;public User() {}public User(Integer id, String username, String password, String auth, String salt) {this.id = id;this.username = username;this.password = password;this.auth = auth;this.salt = salt;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getAuth() {return auth;}public void setAuth(String auth) {this.auth = auth;}public String getSalt() {return salt;}public void setSalt(String salt) {this.salt = salt;}@Overridepublic String toString() {return "User{" +"id=" + id +", username='" + username + '\'' +", password='" + password + '\'' +", auth='" + auth + '\'' +", salt='" + salt + '\'' +'}';}}

Mapper:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zkr.mingyu.dao.UserMapper"><select id="findByUserName" parameterType="String" resultType="user">select id, username, password from user where username = #{username}</select>
</mapper>

五、修改自定义 MyRealm

自定义 MyRealm 类中 doGetAuthenticationInfo()方法主要配置用户认证。
doGetAuthorizationInfo()方法主要配置用户权限配置,说白了也就是给这个用户赋予什么角色、都有哪些权限。以及对某些资源是否可以访问,如果可以访问,那么该用户可以对这个资源执行哪些操作。操作 == CRUD呗。

package com.zkr.mingyu.shiro;import com.zkr.mingyu.entity.User;
import com.zkr.mingyu.service.UserService;
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.springframework.beans.factory.annotation.Autowired;import java.io.Serializable;public class MyRealm extends AuthorizingRealm implements Serializable {@Autowiredprivate UserService userService;/*** 执行授权逻辑* 权限要和资源对应* 权限声明该用户可以访问系统中哪些资源,对系统中哪些资源进行操作* 不同的用户,拥有不同的权限* @param principals* @return*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {System.out.println("执行授权方法: doGetAuthorizationInfo");SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();User user = (User) principals.getPrimaryPrincipal();User byUserName = userService.findByUserName(user.getUsername());/*** 这个方法中为授权操作* 基本常用方法有:*//*** 控制台打印结果:* getRoles: null* getObjectPermissions: null* getStringPermissions: [user:add]* getClass: class org.apache.shiro.authz.SimpleAuthorizationInfo*///获取用户角色/* System.out.println("getRoles: " + info.getRoles());System.out.println("getObjectPermissions: " + info.getObjectPermissions());//获取用户权限System.out.println("getStringPermissions: " + info.getStringPermissions());System.out.println("getClass: " + info.getClass());*/return null;}/*** 认证* @param token* @return* @throws AuthenticationException*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {System.out.println("执行认证方法: doGetAuthenticationInfo");String username = (String) token.getPrincipal();User user = userService.findByUserName(username);if(user == null){return null;}return new SimpleAuthenticationInfo(user,user.getPassword(),this.getName());}
}

这是我写的另一个 MyRealm 配置,简单看看了解一下就可。后期还会继续更新,这篇博客开篇也说了,是搭建项目基本框架。后期后在文末添加新的博客链接,最近有时间抓紧谢谢,分享这份知识。

六、配置资源访问权限 ShiroConfig

ShiroFilterFactoryBean 方法主要配置某些资源需要哪些权限才能访问。以及配置默认的登录页面的 URL 地址。访问某些权限不足的资源跳转到哪个页面,都在这里配置。
DefaultWebSecurityManager 是一个安全管理器,后期我们要做密码加密操作(密码 + 盐 + MD5 + 哈希散列)的时候,我们就要在 DefaultWebSecurityManager() 方法中配置自定义的密码 管理器。

package com.zkr.mingyu.config;import com.zkr.mingyu.shiro.MyRealm;
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 java.util.LinkedHashMap;
import java.util.Map;/**标注 @Configuration 注解,* 标注这是一个配置类,* 让项目启动时加载该配置类。*/
@Configuration
public class ShiroConfig {/*** 创建ShiroFilterFactory* 设置权限规则 需要注入securityManage* @param securityManager* @return*/@Beanpublic ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager){ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();shiroFilterFactoryBean.setSecurityManager(securityManager);/*** Shiro内置过滤器,可实现权限相关的拦截器*      常用的过滤器:*      anon: 无需认证(登录) 可以访问*      authc: 必须认证才可以访问*      user:如果使用rememberMe的功能可以直接访问*      perms: 该资源必须得到资源权限才可以访问*      role: 该资源必须得到角色权限才可以访问*/Map<String, String> filterMap = new LinkedHashMap<String,String>();filterMap.put("/login","anon");filterMap.put("/index","anon");filterMap.put("/*","authc");shiroFilterFactoryBean.setLoginUrl("/login");shiroFilterFactoryBean.setUnauthorizedUrl("/noauth");shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);return shiroFilterFactoryBean;}/*** 创建安全管理器,* 并为 securityManager 注入自定义的 Realm 类* @param realm* @return*/@Beanpublic DefaultWebSecurityManager getSecurityManager(MyRealm realm){DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();securityManager.setRealm(realm);return securityManager;}/*** 配置自定义 Realm 类* @Bean 将 MyRealm 注入到 Spring 容器当中* @return*/@Beanpublic MyRealm getMyRealm(){return new MyRealm();}}

代码不多,简单写个 demo 后期一步一步完善,有时间继续更新新的文章。比如密码加密、资源权限细分、会话、缓存等。
后期写好了新的功能,我会放在文章头、文章尾附上链接。看完点个赞,你的赞就是我更新的动力!收藏文章,后期在文章头部有新博客的链接。

附上一句话 (共勉):
滚水看不到倒影,盛怒看不到真相。

Shiro与SpringBoot整合,实现登录拦截、用户认证、用户授权等。实战demo相关推荐

  1. GitHub开源项目学习 电商系统Mall (四) mall整合SpringSecurity和JWT实现认证和授权(一)

    mall整合SpringSecurity和JWT实现认证和授权(一) https://github.com/macrozheng/mall 跳过了官方Learning中较简单的Swagger-UI的实 ...

  2. 商城项目(三)整合SpringSecurity和JWT实现认证和授权

    整合SpringSecurity和JWT实现认证和授权 环境搭建 SpringSecurity JWT Hutool 项目使用表说明 ums_admin:后台用户表 ums_role:后台用户角色表 ...

  3. GitHub开源项目学习 电商系统Mall (五) mall整合SpringSecurity和JWT实现认证和授权(二)

    mall整合SpringSecurity和JWT实现认证和授权(二) https://github.com/macrozheng/mall 登录注册功能实现 UmsAdminController类 实 ...

  4. linux认证授权系统,linux高级操作系统用户认证与授权-20210323002921.doc-原创力文档...

    HYPERLINK "/" 长沙理工大学 <Linux高级操作系统>课程设计报告 基于Linux的用户认证与授权研究 廖正磊 学 院 计算机与通信工程 专业 计算机科学 ...

  5. linux最新官方回应只峰身份,Linux的用户认证和授权研究.doc

    Linux的用户认证和授权研究 俞月败霜淘马鼻顷霸糊花他景扇遇数按吭克汝间绰嘴扮歇萝讶鹅胞榜赘胳油蓄保恐障首捉盅鄂顷陇蹲敝攀凌膝慕卵辈屉挑汤拓厌滋酞噬今级咸铭窗疼册姨命缝仓巾烟婉满册卡遮缝栏艰斡涩漠岩 ...

  6. linux认证授权系统,linux系统用户认证与授权管理.pptx

    Linux系统用户认证与授权管理;什么是用户认证/权限PAM认证机制Kerberos认证协议LDAP目录访问协议;出于系统安全考虑,Linux提供的安全机制主要有:身份标识与鉴别.文件访问控制.特权管 ...

  7. No6-3.从零搭建spring-cloud-alibaba微服务框架,实现资源端用户认证与授权等(三,no6-3)

    代码地址与接口看总目录:[学习笔记]记录冷冷-pig项目的学习过程,大概包括Authorization Server.springcloud.Mybatis Plus~~~_清晨敲代码的博客-CSDN ...

  8. Shiro与Springboot整合:配置依赖改造登录方法

    <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://mave ...

  9. SpringBoot整合过滤器、拦截器

    目录 过滤器.拦截器的区别 过滤器.拦截器的使用场景 同时存在过滤器.拦截器时的执行流程 springboot整合过滤器 编写过滤器 配置过滤器 springboot整合拦截器 编写拦截器 配置拦截器 ...

最新文章

  1. 【重学Vue】数据响应原理真的是双向绑定吗?
  2. 一位小小码蚁工作2年多感想
  3. mysql中以指定字段去重_数据库根据指定字段去重
  4. LLLYYY的数字思维
  5. 友元是c还是java_[C++]【类】友元的三种声明及注意事项
  6. 使用jsonEditor打造一个复杂json编辑器
  7. Java程序员月薪三万,需要技术达到什么水平?
  8. Unknown entity (Hibernate的findById方法参数必须加上包名)
  9. 提高设计档次的8个方法
  10. HyperLedger Fabric 1.0的Transaction处理流程
  11. android Camera相关问题及NV12剪裁旋转
  12. (day 42 - 字符翻转 ) 剑指 Offer 58 - II. 左旋转字符串
  13. C++ vector和set的区别
  14. c++ 类的定义和使用
  15. vs2010使用教程c语言编程,VS2010的使用
  16. 项目计划书——书写模板
  17. 3D打印机打印中途停止且显示挤出头温度过低
  18. 软件测试技术之项目上线流程
  19. 马陆计算机专业学校,“大路考”有变!智能化监考系统首次投入应用[图]
  20. 微信电子健康卡开放平台接口对接

热门文章

  1. 一个最简单的Java程序
  2. 又一智能汽车新赛道进入「量产期」,谁已率先分走这块蛋糕?
  3. web前端几个小知识点笔记
  4. Unity-Linerenderer画线功能
  5. python读取多个文件夹里的图片并添加标签
  6. 计算机领域项目经费预算,教学项目经费预算表.doc
  7. focusky导出html修改,Focusky怎么设置播放时间间隔 Focusky怎么自定义模板以及导出文件...
  8. cad线段总和lisp_cad lisp-求线段总长度
  9. 【长度统计】多个对象长度计算,支持线段、多段线、圆弧
  10. 商业图书阅读的原则以及一些方法习惯的养成