shiro入门

2023-11-04

1、概述

Apache Shiro 是一个功能强大且易于使用的 Java 安全(权限)框架。借助 Shiro 您可以快速轻松地保护任何应用程序一一从最小的移动应用程序到最大的 Web 和企业应用程序。

作用:Shiro可以帮我们完成 :认证授权、加密、会话管理、与 Web 集成、缓存等。

2、Shiro 与 SpringSecurity 的对比

  • 1、Spring Security 基于 pring 开发,项目若使用 Spring 作为基础,配合 SpringSecurity 做权限更加方便,而 Shiro需要和 Spring 进行整合开发;
  • 2、Spring Security 功能比 Shiro 更加丰富些,例如安全维护方面;
  • 3、Spring Security 社区资源相对比 Shiro 更加丰富:;
  • 4、Shiro的配置和使用比较简单,Spring Security 上手复杂些;
  • 5、Shiro 依赖性低,不需要任何框架和容器,可以独立运行.Spring Security 依赖Spring容器;
  • 6、shiro 不仅仅可以使用在 web 中,它可以工作在任何应用环境中。在集群会话时 Shiro最重要的一个好处或许就是它的会话是独立于容器的;

3、Shiro核心架构

 

 

Subject即主体,外部应用与subject进行交互,subject记录了当前的操作用户,将用户的概念理解为当前操作的主体。外部程序通过subject进行认证授权,而subject是通过SecurityManager安全管理器进行认证授权

SecurityManager即安全管理器,对全部的subject进行安全管理,它是shiro的核心,负责对所有的subject进行安全管理。通过SecurityManager可以完成subject的认证、授权等,实质上SecurityManager是通过Authenticator进行认证,通过Authorizer进行授权,通过SessionManager进行会话管理等

SecurityManager是一个接口,继承了Authenticator, Authorizer, SessionManager这三个接口

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

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

Realm即领域,相当于datasource数据源,securityManager进行安全认证需要通过Realm获取用户权限数据,比如:如果用户身份数据在数据库那么realm就需要从数据库获取用户身份信息

sessionManager即会话管理,shiro框架定义了一套会话管理,它不依赖web容器的session,所以shiro可以使用在非web应用上,也可以将分布式应用的会话集中在一点管理,此特性可使它实现单点登录

SessionDAO即会话dao,是对session会话操作的一套接口,比如要将session存储到数据库,可以通过jdbc将会话存储到数据库

CacheManager即缓存管理,将用户权限数据存储在缓存,这样可以提高性能Cryptography
Cryptography即密码管理,shiro提供了一套加密/解密的组件,方便开发。比如提供常用的散列、加/解密等功能。

token 

1、token定义:服务端生成的一串字符串,可以解决频繁登录的问题
作为客户端进行请求的一个令牌:

  • 第一次登录后,服务器生成一个token返回给客户端;
  • 客户端只需要带上token来请求数据即可,无需再次带上用户名和密码;

2、目的:为了减轻服务器的压力,减少频繁的查询数据库,使服务器更加健壮

4、Shiro的登录认证

1.创建数据库并创建用户表;
2.创建项目病配置ssm,完成根据用户名查询用户信息;
3.创建自定义Realm,继承AuthorizingRealm,使用mybtais查询数据库的盐值和密码,交给shiro进行验证;

流程

1.数据库与表创建

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `uid` int(11) NOT NULL AUTO_INCREMENT,
  `uname` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `pwd` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
  `sex` varchar(2) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `address` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `state` int(2) DEFAULT NULL,
  `salt` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  PRIMARY KEY (`uid`) USING BTREE,
  UNIQUE INDEX `uname`(`uname`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'admin', '727d8b2b4c59366d7ace58d4eda4cfee', '女', '河南洛阳', 1, '9C2AB20283F9450389330033D64686DD');
INSERT INTO `user` VALUES (2, 'zs', '83f12ba7c4357b87167e240a22c15248', '男', '河南郑州', 1, '262F995823C94D1CAE7596B47E8AB657');

select * from user

2.创建模块项目,使用maven+ssm+shiro

 3.搭建ssm框架,编写根据用户名查询用户信息的三层架构

shiro在spring.xml中的配置

 dao层 

@Repository
public interface UserDao {
    @Select("select * from user where uname = #{uname}")
    User selectByName(String uname);
}

 service层

public interface UserService {
    User selectByName(String uname);
}

实现类 

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    UserDao userDao;

    @Override
    public User selectByName(String uname) {
        return userDao.selectByName(uname);
    }
}

controller层进行shiro认证

@Controller
public class UserController {

    @RequestMapping("/login")
    public String login(String uname, String pwd, HttpSession session){
        //1 获取 Subject 对象
        Subject subject = SecurityUtils.getSubject();
        //2 封装请求数据到 token 对象中
        AuthenticationToken token = new UsernamePasswordToken(uname,pwd);
        //3 调用 login 方法进行登录认证
        try{
            //验证主体是否能够登录
            subject.login(token);
            session.setAttribute("user",token.getPrincipal().toString());
            return "main";
        }catch(UnknownAccountException e){
            System.out.println("用户名不存在!!");
            return "login";
        }catch(IncorrectCredentialsException e){
            System.out.println("密码错误!");
            return "login";
        }catch(AuthenticationException e){
            System.out.println("登录失败!");
            return "login";
        }
    }
}
/**
 * 地址和页面的映射,项目中没有页面请求,全是地址请求
 */
@Controller
public class PageController {

    @RequestMapping({"/","/index"})
    public String index(){
        return "index";
    }

    @RequestMapping("/loginUI")
    public String home(){
        return "login";
    }

    @RequestMapping("/main")
    public String phone(){
        return "main";
    }
    
}

web.xml中配置shiro的过滤器

<!-- shiro配置 -->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filterclass>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

shiro层测试

public class Shiro01 {
    public static void main(String[] args) {
//        //Java加盐加密
//        Digester md5 = new Digester(DigestAlgorithm.MD5);
//        md5.setSalt("9C2AB20283F9450389330033D64686DD".getBytes());//加盐
//        md5.setDigestCount(1024);//加散列值
//        String md5Pwd = md5.digestHex("123");
//        System.out.println(md5Pwd);


        //控制台获取
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String username = sc.next();
        System.out.println("请输入密码:");
        String password = sc.next();

        //1.使用INi格式工厂模型来创建对象
        IniSecurityManagerFactory securityManagerFactory = new IniSecurityManagerFactory("classpath:shiro.ini");
        //2.获取安全管理器
        SecurityManager securityManager = securityManagerFactory.getInstance();
        //3.让安全管理器开始工作
        SecurityUtils.setSecurityManager(securityManager);
        //4.获取系统访问的主体:就是登录系统的用户信息
        Subject subject = SecurityUtils.getSubject();
        //4.1模拟客户端传输过来的用户名和密码---创建对应的令牌 token
        AuthenticationToken token = new UsernamePasswordToken(username,password);
        try{
            //5.验证主体是否能够登录
            subject.login(token);
            System.out.println("登录成功!");
        }catch(UnknownAccountException e){
            System.out.println("用户名不存在!!");
        }catch(IncorrectCredentialsException e){
            System.out.println("密码错误!");
        }catch(AuthenticationException e){
            System.out.println("认证失败,不知道出了什么问题!");
        }
    }
}

创建MyRealm继承AuthorizingRealm  

package com.zhan.shiro;

import com.zhan.bean.User;
import com.zhan.service.UserService;
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.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * token 里面是客户端发来的信息(包含输入的用户名和密码
 * 自定义Realm,通过mybatis查询数据库的密码和盐值,让shiro进行身份验证
 */
@Component
public class MyRealm extends AuthorizingRealm {

    @Autowired
    UserService userService;

    /**
     * shiro 进行授权操作
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }

    /**
     * shiro 进行认证操作
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //token 是主体传过来的身份令牌
        //1.获取用户身份信息
        String uname = token.getPrincipal().toString();
        //2.调用业务层获取永固信息(数据库中)
        User user = userService.selectByName(uname);
        //判断并将数据完成封装
        if(user!=null){
            AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                    token.getPrincipal(),//令牌身份信息对象
                    user.getPwd(),//用户数据库的密码
                    ByteSource.Util.bytes(user.getSalt().getBytes()),//加密时的盐值
                    uname//用户名
            );
            return authenticationInfo;
        }
        return null;
    }
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

shiro入门 的相关文章

  • 关于STM32中ADC原理

    该文章内容来源于江协助科技 如有侵权 联系删除 目录 ADC原理 逐次逼近型ADC ADC框图介绍 注入通道 规则通道介绍 ADC基本结构 重点 转换模式 数据对齐 内部校准 ADC原理可以将引脚上连续变化模拟电压转换为内存中存储的数字变量
  • 区块链Fabric-从入门到实战(一)

    加密算法 加密算法分对称加密算法和非对称加密算法 在区块链中主要使用的时非对称加密算法 非对称加密是指为满足安全性需求和所有权验证需求而集成到区块链中的加密技术 非对称加密在加密和解密过程中 使用两个非对称的密钥 分别为公钥和私钥 非对称密
  • Android studio设置快捷键

    Android studio 设置快捷键 因为习惯用eclipse快捷键 所以将Androidstudio的快捷键设置成eclipse快捷键一致 首先在setting keymap 复制一份eclipse 这样就是eclipse的快捷键 以
  • 如何用matlab画泰勒图

    前几天写文章 想画一些泰勒图 我觉得其实这个泰勒图吧 包含的信息也并不多 只是看起来比较直观 且看起来逼格比较高 就谷歌了一下怎么画 先找到的是这个代码 但是有毒 死活跑不通 不知为何 且评论里大家和我的问题都一毛一样 遂重找 http c
  • ctfshow web15-web25详细思路

    web15 提示 公开的信息比如邮箱 可能造成信息泄露 产生严重后果 进入题目后看到有个QQ邮箱 我们搜一下它的QQ 没啥信息 返回到刚才的网站加后缀看能不能进去后台 不知道用户名密码哎 那忘记密码吧 发现一个信息 刚才搜的QQ用户在西安
  • 十、Update 存储过程

    文章目录 修改数据的要求 存储过程中的数据库异常 我们需要数据库异常 MariaDB 发起异常 SIGNAL和RESIGNAL mariaDB 捕获异常 捕获指定异常 捕获自定义异常 获取异常消息 update 锁及其测试 Update 锁
  • 通过Dockerfile启动容器遇到的两个不常见错误

    1 报错 ImportError cannot import name cached property from werkzeug 安装更高级的版本 pip install Werkzeug 0 16 0 2 已安装pip 执行python
  • Python入门--关键字

    关键字是Python编程语言中具有特殊含义的保留单词 不能用作变量名 函数名 类名或其他标识符 以下是Python 3 9 0版本中的关键字列表 False None True and as assert async await break
  • 将 varchar 转换为数据类型 numeric 时出现算术溢出错误

    SQL Server 2005 中 如果使用5位以上的字符串转换为numeric时就会出现 将 varchar 转换为数据类型 numeric 时出现算术溢出错误 这样的错误 如果使用5位以下 含5位 的就不会出错
  • Python笔记18-继承&函数重写

    一 继承 重点掌握 1 概念 如果两个或者两个以上的类具有相同的属性和方法 我们可以抽取一个类出来 在抽取出来的类中声明各个类公共的部分 被抽取出来的类 父类 father class 超类 super class 基类 base clas
  • Java List转换成String数组

    实现代码 List
  • Android阿里云推送离线通知集成踩坑之路

    最近因为公司后台服务器买的是阿里云的服务 所以把友盟的推送换成了阿里云推送 首先不得不说 文档写得很差 兼容性和适配做得也不是很好 加了技术支持群 但是里面的同学问一个问题半天才有回复 好了 不扯谈 直接上代码 1 添加依赖 由于公司项目是
  • C++ 计算数组长度

    实现程序如下 include
  • Sublime Text3 BracketHighlighter

    BracketHighlighter 括号匹配插件 修改Preferences gt Package Settings gt BracketHighlighter gt Bracket Settings 修改settings User文件
  • 深入理解Gradle、Maven等JAVA项目的构建工具

    目录 简单概括构建工具的作用 构建工具的具体作用 Gradle和Maven的比较 简单概括构建工具的作用 构建工具用于自动化构建 编译 测试 和打包软件项目极大地简化软件开发的过程 提高开发效率和可靠性 让开发者更加专注于业务逻辑和代码实现
  • 云计算基本概念

    云计算的定义 1 云计算是同时描述一个系统平台或者一类应用程序的术语 云计算平台按需进行动态部署 Provision 部署 Configuration 重新部署 Reconfigure 以及取消服务 Deprovision 等 在云计算平台
  • Reducer buckets have been rebuilt in this iteration.

    在跑torch多GPU报错 Reducer buckets have been rebuilt in this iteration 原因是torch版本问题 torch1 7以上的distributed py发生更改导致报错 这玩意是dis
  • pymysql 重连

    self conn ping reconnect True
  • js给json格式的数组中每一项添加

    for let i 0 i lt this theme length i for let j 0 j lt dayarr length j this theme i day dayarr j

随机推荐

  • DevExpress GridControl复合表头(多行表头)设置

    首先 DevExpress XtraGrid的GridControl复合表头或多行表头的示例 界面如下图所示 实现步骤 1 将DevExpress的GridControl转换为BandedGridView 具体如下图 2 设置显示列及绑定的
  • SpringBoot 整合 kafka 遇到的版本不对应问题

    SpringBoot 整合 kafka 需要在SpringBoot项目里增加kafka的jar 而最为关键的一点是版本要对应好 如果你的SpringBoot是2 0 3版本
  • 国际版阿里云/腾讯云:弹性高性能计算E-HPC入门概述

    入门概述 本文介绍E HPC的运用流程 帮助您快速上手运用弹性高性能核算 下文以创立集群 在集群中安装GROMACS软件并运转水分子算例进行高性能核算为例 介绍弹性高性能核算的运用流程 帮助您快速上手运用弹性高性能核算 运用流程如下图所示
  • Jmeter —— 录制脚本

    1 第一步 添加http代理服务器 在测试计划 添加 非测试元件 http代理服务器 2 第二步 添加线程组 这个线程组是用来放录制的脚本 不添加也可以 就直接放在代理服务器下 测试计划 添加 线程 线程组 顺便讲一下线程组执行顺序 set
  • Idea快捷键(快速开发)

    Idea快捷键 快捷键 功能 Alt Enter 快速修复选择 Alt Insert 生成代码 如set get 构造方法等 Alt 切换到左侧视图 Alt 切换到右侧视图 Shift Shift 搜索文件 Ctrl D 复制当前一行 插入
  • CH8-排序

    文章目录 1 基本概念和排序方法概述 1 1 排序方法的分类 1 2 存储结构 顺序表 2 插入排序 2 1 插入排序的种类 直接插入 折半插入 希尔排序 3 交换排序 3 1 冒泡排序 3 2 快速排序 4 选择排序 4 1 直接排序 4
  • 【Spring Security】UserDetails 接口介绍

    文章目录 UserDetails 的作用 UserDetails 接口中各个方法详解 UserDetails 的作用 UserDetails 在 Spring Security 框架中主要担任获取用户信息的接口 通过该接口就能拿到用户的信息
  • Android Studio 优先源码编译的framework.jar(使用系统隐藏的api)

    引言 场景 做系统开发或者想使用隐藏的api时 通常只能使用反射的方式 缺点 需要使用的api或变量太多时不方便使用 解决办法 将需要在编译时使用的jar包参与编译 不编译到产品apk里 使app运行时调用的是系统api 步骤 每一步都必须
  • 【DirectX12】2.示例三角形绘制

    示例三角形绘制 1 效果 下面只贴出关于dx的代码 有时间再详细说明 2 标头 h pragma once include pch h include LVEDebug h include LVESystem h include
  • bootstrap点击删除按钮弹出确认框实现

  • orge工具

    tortoisehg 3 2 1 x64 msi mercurial 3 2 1 x64 msi
  • 微信支付宝大规模补贴抢占刷脸支付入口

    刷脸支付相较于二维码 优势在于去掉了手机这一介质 但介质的缺失 也意味着人脸信息的泄露变得更加容易 刷脸支付的基本原理就是将终端硬件采集到的信息与云端的存储的信息进行比对 看信息是否一致 然后解锁完成人脸支付 如果云端生物数据库发生信息泄露
  • 【华为OD统一考试A卷

    华为OD统一考试A卷 B卷 新题库说明 2023年5月份 华为官方已经将的 2022 0223Q 1 2 3 4 统一修改为OD统一考试 A卷 和OD统一考试 B卷 你收到的链接上面会标注A卷还是B卷 请注意 根据反馈 目前大部分收到的都是
  • 微信小程序设置允许转发分享onShareAppMessage(Object object)

    在需要分享的页面js文件中写 Page onShareAppMessage const promise new Promise resolve gt setTimeout gt resolve title 自定义转发标题 2000 retu
  • 基于概率论的分类方法:朴素贝叶斯

    需要分类器做出分类决策 可以使分类器给出各个类别的概率估计值 然后选择概率最高的作为其的类别 在这里使用到了概率论中的贝叶斯公式 P A B P A P B A P B 其中P A B 是后验概率 P A 是先验概率 P B A P B 为
  • Python数据分析与展示第三课

    Matplotlib是python优秀的数据可视化第三方库 数据可视化 将数据以特定的图形图像的形式展现出来 Matplotlib由各种可视化的类构成的 使用方式 import matplotlib pyplot as plt as plt
  • 论文收录引用证明常见问题汇总

    学术论文在毕业 评职称 保研 考博 留学等方面均有重要意义 因此往往需要开具检索证明 然而 开具检索证明的前提是论文必须被收录 1 什么是论文收录引用证明 论文收录引用证明是用来证明作者在科研领域中的实力和成就 当用户需要查询其论文在指定数
  • 单链表实现多项式相加

    这个小项目用C语言实现 代码中有我的注释 思路 用链表的每个节点存储表达式的每一项 因此每个链表就是一个表达式 链表节点类型的定义 struct Node DataType elem 项的系数 Variate ch 常量和变量的标志 规定如
  • rand()每次产生的随机数都一样

    写了个程序 每次产生的随机数都是一样的 在调用之前已经初始化了随机数种子 用的是当前时间 可是还是得到一样的数 for int i 0 i lt 100000 i srand unsigned time NULL cout lt
  • shiro入门

    1 概述 Apache Shiro 是一个功能强大且易于使用的 Java 安全 权限 框架 借助 Shiro 您可以快速轻松地保护任何应用程序一一从最小的移动应用程序到最大的 Web 和企业应用程序 作用 Shiro可以帮我们完成 认证 授