写点什么

Shiro 简介及 SpringBoot 集成 Shiro(狂神说视频简易版)

作者:刘大猫
  • 2025-06-01
    黑龙江
  • 本文字数:5581 字

    阅读完需:约 18 分钟

说明:该文章为《狂神说 SpringBoot 集成 Shiro》视频的自己总结的文章

b站视频学习连接


@[TOC]

一、Shiro 简介

1.1 什么是 Shiro

Apache Shiro 是一个 Java 的安全(权限)框架。Shiro 可以非常容易的开发出足够好的应用,其不仅可以用在 JavaSE 环境,也可以用在 JavaEE 环境。Shiro 可以完成,认证,授权,加密,会话管理,Web 集成,缓存等。下载地址:http://shiro.apac he.org/

1.2 有哪些功能


1.3Shiro 架构(外部)


1.4Shiro 架构(内部)


二、QuickStart.java

了解下列方法的用处


三、SpringBoot 集成 Shiro

页面效果

项目结构

第 1 步:pom 导入 shiro 和 thymeleaf 依赖

<!--Shiro 和 spring整合的依赖--><dependency>    <groupId>org.apache.shiro</groupId>    <artifactId>shiro-spring</artifactId>    <version>1.4.1</version></dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> <version>2.6.7</version></dependency>
复制代码

第 2 步:创建页面

login.html

login.html


<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head>    <meta charset="UTF-8">    <title>登录页面</title></head><body><p style="color: red" th:text="${msg}"></p><!--login是controller使用shiro做登录验证的方法--><form th:action="@{/shiro/login}">    <p>        用户名:<input type="text" name="username">    </p>
<p> 密码:<input type="text" name="password"> </p> <p><input type="submit"></p></form></body></html>
复制代码

index.html

index.html


<!DOCTYPE html><html lang="en" xmlns:th="http://www.thymeleaf.org"><head>    <meta charset="UTF-8">    <title>Title</title></head><body><h1>首页</h1><p th:text="${msg1}"></p>
<!--/user/add是controller的一个路径--><a th:href="@{/shiro/user/add}">add</a><a th:href="@{/shiro/user/update}">update</a></body></html>
复制代码

add.html

add.html


<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>add</title></head><body><h1>add</h1></body></html>
复制代码

update.html

update.html


<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>update</title></head><body><h1>update</h1></body></html>
复制代码

第 3 步:创建配置项

ShiroConfig

package com.example.demo.config;
import com.example.demo.bean.UserRealm;import org.apache.shiro.spring.web.ShiroFilterFactoryBean;import org.apache.shiro.web.mgt.DefaultWebSecurityManager;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashMap;import java.util.Map;
//声明为配置类@Configurationpublic class ShiroConfig {

//创建过滤器 ShiroFilterFactoryBean 3 @Bean public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){ ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean(); //设置安全管理器 shiroFilterFactoryBean.setSecurityManager(securityManager); /* 添加Shiro内置过滤器,常用的有如下过滤器: anon: 无需认证就可以访问 authc: 必须认证才可以访问 user: 如果使用了记住我功能就可以直接访问 perms: 拥有某个资源权限才可以访问 role: 拥有某个角色权限才可以访问 */ Map<String,String> filterMap=new LinkedHashMap<String, String>(); //设置过滤器,还没登录前要想访问controller的add和update必须通过登录认证才允许访问 filterMap.put("/shiro/user/add","authc"); //这里user/*可以通配符的 filterMap.put("/shiro/user/update","authc"); filterMap.put("/shiro/queryList","authc"); shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap); //修改到要跳转的login页面(shrio没security会帮你自动生成一个登录的,得自己写); shiroFilterFactoryBean.setLoginUrl("/shiro/toLogin"); //toLogin是controller的一个跳到登录页面的方法
return shiroFilterFactoryBean; }
//创建安全管理器 DefaultWebSecurityManager 2 @Bean(name = "securityManager") public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){ DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager(); //关联Realm securityManager.setRealm(userRealm); return securityManager; }
//创建 realm 对象 1 @Bean public UserRealm userRealm(){ return new UserRealm(); }}
复制代码

Realm

package com.example.demo.bean;
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.authc.UsernamePasswordToken;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 java.util.HashSet;import java.util.Set;
//自定义Realm 必须要的 给ShrioConfig第三步用的public class UserRealm extends AuthorizingRealm{
//执行授权逻辑 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("执行了=>授权逻辑PrincipalCollection");
//从数据库查用户判断是否为admin账户,设置isAdmin属性为【true/false】 boolean isAdmin = true; SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); // 角色列表 Set roles = new HashSet<String>(); // 功能列表 Set<String> menus = new HashSet<String>(); //判断管理员拥有所有权限 if(isAdmin) { info.addRole("admin"); info.addStringPermission("*:*:*"); } else { //非管理员添加权限 //从数据库查询角色和权限,赋值给roles和menus info.setRoles(roles); info.setStringPermissions(menus); } return info; }
//执行认证逻辑 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("执行了=>认证逻辑AuthenticationToken"); //假设数据库的用户名和密码 String name="root"; String password="root";
//1.判断用户名 //把token转为我们认识的,也是从controller那个token来的 UsernamePasswordToken userToken = (UsernamePasswordToken) token; if (!userToken.getUsername().equals(name)){ //用户名不存在 return null; //shiro底层就会抛出 UnknownAccountException }
//2. 验证密码,我们可以使用一个AuthenticationInfo实现类 SimpleAuthenticationInfo // shiro会自动帮我们验证!重点是第二个参数就是要验证的密码! //第一个参数是传给上面的授权方法获得当前用户的,现在暂时设置为空先 return new SimpleAuthenticationInfo("",password,""); }}
复制代码

ShiroController

package com.example.demo.controller;
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.authz.annotation.RequiresPermissions;import org.apache.shiro.subject.Subject;import org.springframework.stereotype.Controller;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.ResponseBody;
import java.util.ArrayList;import java.util.List;
@Controller@RequestMapping("/shiro")public class ShiroController { // 加/代表默认跳到这 @RequestMapping({"/","/index"}) public String toIndex(Model model){ model.addAttribute("msg1","hello,Shiro"); return "shiroUser/index"; } @RequestMapping("/user/add") public String toAdd(){ return "shiroUser/add"; } @RequestMapping("/user/update") public String toUpdate(){ return "shiroUser/update"; }
//跳到登录登录页面的方法 @RequestMapping("/toLogin") public String toLogin(){ return "shiroUser/login"; } //登录操作 @RequestMapping("/login") public String login(String username, String password, Model model){ //使用shiro,编写认证操作 //1. 获取Subject Subject subject = SecurityUtils.getSubject(); //2. 封装用户的数据,token是根据用户名和密码生成的 UsernamePasswordToken token = new UsernamePasswordToken(username, password); //token.setRememberMe(true); //记住我
//
//3. 执行登录的方法,只要没有异常就代表登录成功! try { subject.login(token); //执行登录,shiro帮我们弄的,很麻烦的,会跳到UserRealm的认证方法认证的 //登录成功!返回首页 return "shiroUser/index"; }catch (UnknownAccountException e){ //用户名不存在 model.addAttribute("msg","用户名不存在"); return "shiroUser/login"; }catch (IncorrectCredentialsException e) { //密码错误 model.addAttribute("msg","密码错误"); return "shiroUser/login"; } }
//假的批量查询 @RequiresPermissions("sysconfig:edit:view") @ResponseBody @GetMapping("/queryList") public List queryList(){ List list = new ArrayList(); //查询数据库封装list return list; }}
复制代码

四、注意点讲解

<font color='red'>注意点 1:</font>讲解执行流程首先访问默认路径 http://localhost:8888/shiro/ =》 走进 ShiroConfig 的过滤器 getShiroFilterFactoryBean 方法 =》如果未登录就对进入登录页面;如果已登录就直接跳转 add 或者 update 页面。


<font color='red'>注意点 2:</font>


问题:UserRealm 的 doGetAuthorizationInfo 授权方法何时执行?


<font color='red'>答案:</font>当执行下方方法时就会进入授权方法中


  1. subject.hasRole(“admin”) 或 subject.isPermitted(“admin”):自己去调用这个是否有什么角色或者是否有什么权限的时候;

  2. @RequiresRoles(“admin”) :在方法上加注解的时候;

  3. [@shiro.hasPermission name =“admin”] [/@shiro.hasPermission]:在页面上加 shiro 标签的时候,即进这个页面的时候扫描到有这个标签的时候。


问题:UserRealm 的 doGetAuthenticationInfo 认证方法何时执行?


<font color='red'>答案:</font>当执行登录方法中的<font color='red'>subject.login(token);</font>这段代码时,shiro 就会自动帮我们跳转到 UserRealm 的认证方法认证的。


<font color='red'>注意点 3:</font>


问题:ShiroConfig 干啥用的?


<font color='red'>答案:</font>


  • 第 1 步:创建 realm 对象

  • 第 2 步:创建安全管理器 DefaultWebSecurityManager

  • 第 3 步:创建过滤器 ShiroFilterFactoryBea


<font color='red'>注意点 4:</font>


问题:UserRealm 干啥用的?


<font color='red'>答案:</font>用来定义授权逻辑和认证逻辑,其中授权逻辑就是定义哪些角色拥有哪些访问权限,认证逻辑用来校验用户输入的信息是否正确,比如用户名是否正确、密码是否正确、用户名长度或密码输入格式是否正确等等。


授权方法<font color='red'>doGetAuthorizationInfo</font>使用 SimpleAuthorizationInfo 对象<font color='red'>设置角色和权限</font>认证方法<font color='red'>doGetAuthenticationInfo</font>使用 SimpleAuthenticationInfo 对象<font color='red'>设置验证密码</font>


<font color='red'>注意点 5:</font>


注解 @RequiresPermissions("sysconfig:edit:view")干啥用的?


<font color='red'>答案:</font>只有登录用户权限包含"sysconfig:edit:view"的时候才能调通 @RequiresPermissions 注解指定的方法接口,否则压根调不通接口。

用户头像

刘大猫

关注

还未添加个人签名 2022-08-23 加入

还未添加个人简介

评论

发布
暂无评论
Shiro简介及SpringBoot集成Shiro(狂神说视频简易版)_人工智能_刘大猫_InfoQ写作社区