Shiro基础

Shiro

介绍

什么是shiro?

  • Apache Shiro 是一个ava 的安全(权限)框架。

  • Shiro 可以非常容易的开发出足够好的应用,其不仅可以用在javaSE环境,也可以用在JavaEE环境

  • Shiro可以完成,认证,授权,加密,会话管理,Web集成,缓存等

  • 下载地址:http://shiro.apache.org/

    image-20251207155559350

架构

  • 外部

    image-20251207161826923

    • subject:应用代码直接交互的对象是Subject,也就是说Shiro的对外API核心就是Subject,subject代表了当前的用户,这个用户不一定是一个具体的人,与当前立用交互的任何东西都是Subject,如网络爬虫,机器人等,与Subject的所有交互都会委托给SecurityManager;subject其实是一个门面,SecurityManageer才是实际的执行者
    • SecurityManager:安全管理器,即所有与安全有关自]操作都会与SercurityManager交互,并且它管理着所有的Subject,可以看出它是Shiro的核心,它负责与Shiro的其他组件进行交互,它相当于SpringMVc的DispatcherServlet的角色
    • Realm:Shiro从Realm获取安全数据(如用户,角色权限),就是说SecurityManager要验证用户身份那么它需要从Realm 获取相应的用户进行比较,来确”定用户的身份是否合法;也需要从Realm得到用户相应的角色、权限,进行验证用户的操作是否能够进行,可把Realm看成Datasource;
  • 内部

    image-20251207162432090

    • Subject:任何可以与应用交互的’用户’,
    • Security Manager:相当于SpringMVC中的DispatcherServlet;是Shiro的心脏,所有具体的交互都通过Security Manager进行控制,它管理者所有的Subject,且负责进行认证,授权,会话,及缓存的管理。
    • Authenticator:负责Subject认证,是一个扩展点,可以自定义实现;可以使用认证策略(AuthenticationStrategy),即什么情况下算用户认证通过了;
    • Authorizer:授权器,即访问控制器,用来决定主体是否有权限进行相应的操作;即控制着用户能访问应用中的那些功能;
    • Realm:可以有一个或者多个的realm,可以认为是安全实体数据源,即用于获取安全实体的,可以用IDBC实现,也可以是内存实现等等,由用户提供;所以一般在应用中都需要实现自己的realm
    • SessionManager:管理Session生命周期的组件,而Shiro并不仅仅可以用在Web环境,也可以用在普通的avaSE环境中
    • CacheManager:缓存控制器,来管理如用户,角色,权限等缓存的;因为这些数据基本上很少改变,放到缓存中后可以提高访问的性能,
    • cryptography:密码模块,Shiro 提高了一些常见的加密组件用于密码加密,解密等

配置

(快速启动)

  1. 导入pom

  2. 配置shiro.ini

    image-20251207164144814

  3. Quickstart

内容

subjet

  • 先调用获取 对象并且获取session

    image-20251207190340167

  • 判断认证

    image-20251208102635199

    验证错误就爆出异常

    (用户名不对,密码不对,错误太多锁定账户)

  • 存储用户

    image-20251208102942569

  • 角色测试(在shiro.ini里面配置)

    image-20251208103238881

  • 对应角色权限测试(在shiro.ini里面配置)

    image-20251208103402043

  • 最后注销

    image-20251208103427549

1
2
3
4
5
6
Subject currentuser=securityutils.getsubject();
Session session=currentUser.getsession();
currentUser.isAuthenticated()currentuser.getPrincipal();
currentuser.hasRole('schwartz");
currentuser.isPermitted("lightsaber:wield");
currentuser.logout();

项目

Subject 用户

SecurityManager管理所有用户

Realm连接数据

  • 先写realm

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    package org.example.realm;
    
    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;
    
    public class MyRealm extends AuthorizingRealm {
    
        // 授权
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            String username = (String) principals.getPrimaryPrincipal();
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
    
            if ("admin".equals(username)) {
                info.addRole("admin");
                info.addStringPermission("user:add");
            } else if ("user".equals(username)) {
                info.addRole("user");
            }
    
            return info;
        }
  • 写ShiroConfig

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    package org.example.config;
    
    import org.example.realm.MyRealm;
    import org.apache.shiro.mgt.SecurityManager;
    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
    public class ShiroConfig {
    
        @Bean
        public MyRealm myRealm() {
            return new MyRealm();
        }
    
        @Bean
        public SecurityManager securityManager(MyRealm myRealm) {
            return new DefaultWebSecurityManager(myRealm);
        }
    
        @Bean
        public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
            ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
            bean.setSecurityManager(securityManager);
    
            Map<String, String> map = new LinkedHashMap<>();
            map.put("/login", "anon");
            map.put("/doLogin", "anon");
            map.put("/logout", "logout");
            map.put("/admin", "roles[admin]");
            map.put("/user", "roles[user]");
            map.put("/**", "authc");
    
            bean.setFilterChainDefinitionMap(map);
            bean.setLoginUrl("/login");
            bean.setUnauthorizedUrl("/unauthorized");
    
            return bean;
        }
    }
  • 用户拦截

    如下:

    1
    2
    3
    4
    5
    anon:无需认证就可以访问
    authc必须认证了才能访问
    user:必须拥有 记住我 功能才能用
    perms:拥有对某个资源的权限才能访问
    role:拥有某个角色权限才能访问

    (在ShiroConfig写)image-20251208113413489

  • 实现用户认证

    Myrealm中写

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    // 认证
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
                throws AuthenticationException {
            String username = (String) token.getPrincipal();
            String password = new String((char[]) token.getCredentials());
    
            // 写死用户测试
            if ("admin".equals(username) && "123456".equals(password)) {
                return new SimpleAuthenticationInfo(username, password, getName());
            }
            if ("user".equals(username) && "111111".equals(password)) {
                return new SimpleAuthenticationInfo(username, password, getName());
            }
    
            throw new UnknownAccountException("用户名或密码错误");
        }
    }
  • 请求授权实现

    image-20251208133552573

    对用户限制使用add

    访问会弹出401报错(401就是未授权)

  • 页面跳转

    先在MuController添加访问路径

    image-20251208133734659

  • 配置

    MyController

    image-20251208155756324

整合Mybatis(数据库)

  • 先加依赖

image-20251208123600383

  • 配置文件

    1
    2
    mybatis.type-aliases-package=org.example.shiro.pojo
    mybatis.mapper-locations=classpath:mapper/*.xml
  • 在pojo中写user类

    image-20251208123955044

  • 写mapper里面UserMapper写

    image-20251208124036312

  • 配置静态mapper

    image-20251208124206025

  • service层写UserService

    image-20251208124303564

    UserServiceImpl

    image-20251208124347267

  • 接下来就在MyRealm中写

    连接真实数据库

    image-20251208133153322

    记得把之前自己写的数据删了

区别

比较项 Apache Shiro Spring Security
背景来源 第三方安全框架 Spring 官方安全体系
集成性 较弱,需手动整合 深度集成 Spring Boot / Spring MVC
功能复杂度 简单、轻量级 功能全面、体系庞大
认证方式 基于 Subject(用户) 基于 SecurityContext(安全上下文)
授权方式 角色/权限标注支持简单 支持复杂 RBAC、ACL、权限层级
会话管理 内置,可脱离 Web 使用 依赖 Servlet 容器(或额外配置)
前后端分离支持 需自定义较多 原生支持 JWT / OAuth2 / Filter 链控制
企业级安全标准 支持少 内置防护更多(CSRF、会话固定攻击等)

Shiro基础
http://example.com/2025/12/08/Shiro/
作者
Piggy Sprint
发布于
2025年12月8日
许可协议