shiro入门

news2025/1/11 9:11:18

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;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/717120.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

车载通信,来看看SOA架构通信如何跨系统的

SOA车载跨系统通信 在车载系统中实现跨系统通信时&#xff0c;SOA架构&#xff08;Service-Oriented Architecture&#xff0c;面向服务的架构&#xff09;可以提供一种有效的解决方案。以下是一种基于SOA的车载跨系统通信的概述&#xff1a; 定义服务接口&#xff1a;首先&a…

2023年无线蓝牙耳机排行榜,十款无线蓝牙耳机品牌推荐

蓝牙耳机作为现代生活必备的电子产品之一&#xff0c;我们在选购时的选择就显得尤为重要。随着各大科技公司对蓝牙耳机功能的不断完善&#xff0c;用户对于耳机的期望也越来越高&#xff0c;音质、性能、降噪、舒适度等方面都成为了用户选择蓝牙耳机时考虑的因素。接下来我们一…

从零开始 Spring Boot 57:JPA中的一对多关系

从零开始 Spring Boot 57&#xff1a;JPA中的一对多关系 图源&#xff1a;简书 (jianshu.com) 在上篇文章中我们介绍了如何在 JPA 中实现实体的一对一关系&#xff0c;在关系型数据库设计中&#xff0c;除了一对一关系&#xff0c;还存在一对多关系。本篇文章介绍如何在 JPA 中…

Android仿淘宝、京东、拼多多搜索历史

详情见代码 &#xff1a;https://github.com/yixiaolunhui/FSearchHistory

计算机网络概述(一)

因特网概述 网络&#xff0c;互联网与因特网的区别联系&#xff1a; 以上是使用有线和无线链路连接的两个网络。那么&#xff0c;要让这两个网络连接起来&#xff0c;就需要路由器。若干个网络通过多个路由器互联起来&#xff0c;就称为了互联网。 因特网是当今世界上最大的互…

基于springboot+vue的高校二手交易系统(源代码+数据库)080

基于springbootvue的高校二手交易系统(源代码数据库)080 一、系统介绍 本项目前后端分离 本系统分为管理员、用户两种角色 用户角色包含以下功能&#xff1a; 登录、注册、(商品搜索、发布、收藏、下单)、评论、个人信息修改、密码修改、我的发布、我的订单、收藏夹 管理…

使用android studio将网站打包成apk(可以直接使用替换为自己的网站连接即可)

公司有这个需求生成一个webapp应用。前面一直在使用web与Android混合开发&#xff0c;越是后面你就发现越有意思。hbuildX官网不怎么维护&#xff0c;虽然一直说这是潮流&#xff0c;uni-app开发也挺火的&#xff0c;但是安卓开发特别是适配不同的手机型号&#xff0c;真的是头…

详解JS 作用域与作用域链、IIFE模式、js执行过程

文章目录 一、什么是作用域二. 全局作用域、函数作用域、块级作用域全局作用域函数作用域注意 if、for循环、while循环变量 块级作用域 二、什么是作用域链1. 什么是自由变量2.什么是作用域链3. 关于自由变量的取值 三、IIFE模式由来语法基本语法带参 四、JavaScript 执行过程编…

C++ 数据结构B 树

目录 1. 常见的搜索结构 2. B树概念 3. B-树的插入分析 4. B-树的插入实现 4.1 B-树的节点设计 4.2 插入key的过程 4.4 B-树的简单验证 4.5 B-树的性能分析 4.6 B-树的删除 5. B树和B*树 5.1 B树 5.2 B*树 5.3 总结 6. B-树的应用 6.1 索引 6.2 MySQL索引简介 6…

浅谈建筑项目中的智能照明系统的设计

张心志 安科瑞电气股份有限公司 上海嘉定 201801 【摘要】&#xff1a;建筑智能照明工程中智能照明控制系统发展迅速&#xff0c;具有舒适性和节能性两方面优势。智能照明控制系统已经处于模块化高速发展阶段&#xff0c;如今更好的控制方案成为制约系统发展的瓶颈。文章在研…

工作总是忙不完是什么原因?时间管理软件帮你解决问题

随着市场竞争的激烈&#xff0c;有不少上班族都感受到了工作的压力&#xff0c;每天越来越多的工作任务需要完成。于是我们经常会听到这样的抱怨&#xff1a;“工作太多了&#xff0c;总是忙不完&#xff01;”那么工作总是忙不完是什么原因呢&#xff1f;其实一般来说工作总是…

GB50255-2014电气装置安装工程电力变流设备施工及验收规范

为了保证电力变流设备安装工程的施工质量&#xff0c;促进施工技术的提高&#xff0c;保证电力变流设备的安全稳定运行&#xff0c;制定本规范。 本规范适用于电力系统中除高压直流输电和柔性交流输电以外的电力变换设备的施工、调试及验收。 电力变流设备的施工、调试及验收…

linux epoll/select使用区分和实例对比

Linux内核poll&#xff0c;ppoll&#xff0c;epoll&#xff0c;select代码位置&#xff1a; poll&#xff0c;ppoll&#xff0c;select相关内核实现在在fs/select.c中; epoll_ctl和epoll_wait相关函数在fs/eventpoll.c中 epoll实测不支持监听普通文件&#xff0c;select可以…

医院中医临床护理中医理论考试题库及答案

本题库是根据最新考试大纲要求&#xff0c;结合近年来考试真题的重难点进行汇编整理组成的全真模拟试题&#xff0c;考生们可以进行专项训练&#xff0c;查漏补缺巩固知识点。本题库对热点考题和重难点题目都进行了仔细的整理和编辑&#xff0c;相信考生在经过了针对性的刷题练…

测试员拒绝当“背锅侠”,软件质量不是“测”出来的!

以前有个朋友跟我说&#xff1a;做测试这行就是在隐忍中负重前行。因为测试是软件发布前的最后一个环节&#xff0c;被称作质量出口儿&#xff0c;测试环节之前所有未做好的工作所带来的不良后果&#xff0c;似乎都能被轻松甩锅给测试人员。软件一旦出现问题&#xff0c;我们经…

django疫情防控常态化下疫情物资管理可视化系统-计算机毕设 附源码73893

django疫情防控常态化下疫情物资管理可视化系统 摘 要 信息化社会内需要与之针对性的信息获取途径&#xff0c;但是途径的扩展基本上为人们所努力的方向&#xff0c;由于站在的角度存在偏差&#xff0c;人们经常能够获得不同类型信息&#xff0c;这也是技术最为难以攻克的课题。…

YOLOv5改进系列(13)——更换激活函数之SiLU,ReLU,ELU,Hardswish,Mish,Softplus,AconC系列等

【YOLOv5改进系列】前期回顾: YOLOv5改进系列(0)——重要性能指标与训练结果评价及分析 YOLOv5改进系列(1)——添加SE注意力机制

javaWeb中的Ajax_待后期增加

前言&#xff1a; Ajax是一种在JavaWeb开发中常用的技术&#xff0c;通过它可以实现异步通信和动态加载数据&#xff0c;提升用户体验。 正文&#xff1a; 首先我们得明白异步通信&#xff0c;客户端发出请求后可以继续执行其他操作 由于原生的Ajax过于复杂 so&#xff1a; …

FastDFS【SpringBoot操作FastDFS、复习】(三)-全面详解(学习总结---从入门到深化)

目录 SpringBoot操作FastDFS 复习&#xff1a; SpringBoot操作FastDFS 由GitHub大牛tobato在原作者YuQing与yuqih发布的JAVA客户端基 础上进行了大量重构工作&#xff0c;并于GitHub上发布了FastDFS-Client1.26.5。 主要特性 1 对关键部分代码加入了单元测试&#xff0c;便于…

leetcode 21.合并两个有序链表

⭐️ 往期相关文章 &#x1f4ab;链接1&#xff1a;链表中倒数第k个结点(快慢指针问题) &#x1f4ab;链接2&#xff1a;leetcode 876.链表的中间结点(快慢指针问题) &#x1f4ab;链接3&#xff1a;leetcode 206.反转链表 &#x1f4ab;链接4&#xff1a;leetcode 203.移除链…