首页 > 其他分享 >【Shiro】1.快速入门

【Shiro】1.快速入门

时间:2024-09-26 09:35:05浏览次数:7  
标签:用户名 入门 用户 认证 println 授权 快速 Shiro

Shiro官网地址:Shiro 官网:https://shiro.apache.org/

Shiro简介

概述

Apache Shiro是Java的一个安全框架。Shiro可以帮助我们完成:认证、授权、加密、会话管理、与Web集成、缓存等。使用 Shiro 易于理解的 API,您可以快速轻松地保护任何应用程序—从最小的移动应用程序到最大的 web 和企业应用程序。

Shiro 的架构图如下:

 优点

  • 易于理解的 Java Security API
  • 简单的身份认证,支持多种数据源
  • 对角色的简单的授权,支持细粒度的授权
  • 不跟任何的框架或者容器捆绑,可以独立运行

特性

特性 说明
Authentication 身份认证/登录。验证用户是不是拥有相应的身份
Authorization 授权(验证授权)。验证某个已认证的用户是否拥有某个权限,即判断用户是否能做事情
SessionManagement 会话管理。即用户登录后就是一次会话,在没退出之前,它的所有信息都在会话中
Cryptography 加密。保护数据的安全性,如密码加密存储到数据库,而不是明文存储。
Caching 缓存。比如用户登录后,其用户信息,拥有的角色/权限不必每次都去查,提高效率。
Concurrency 支持多线程应用的并发验证。即如在一个线程中开启另一个线程,能把权限自动传播过去。
Testing 提供测试支持。
RunAs 允许一个用户假装另一个用户(如果他们允许)的身份进行访问
RememberMe 记住我。这是非常常见的功能。即一次登录后,下次在进入系统是不用登录了。

架构

架构 说明
Subject 主体。代表了当前的“用户”,这个用户不一定是一个具体的人,与当前应用交互的任何东西都是Subject,如网络爬虫, 机器人等;即一个抽象概念;所有Subject都绑定到SercurityManager,与Subject的所有交互都会委托给SecurityManager;可以把Subject认为是一个门面;SecurityManager才是实际的执行者。
SecurityManage 安全管理器。即所有与安全有关的操作都会与SecurityManager交互;且它管理着所有Subject; 可以看出它是Shiro的核心,它负责与后边介绍的其他组件进行交互。

Realm
域。Shiro从Realm获取安全数据(如用户,角色,权限),就是说SecurityManager要验证用户身份, 那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法;也需要从Realm得到用户相应的角色/权限进行验证用户是否能进行操作;可以有1个或多个Realm,我们一般在应用中都需要实现自己的Realm。
SessionManager 会话管理。如果写过Servlet就应该知道Session的概念,Session需要有人去管理它的生命周期,这个组件就是SessionManager。
SessionDAO 即会话 dao。是对 session 会话操作的一套接口,比如要将 session 存储到数据库,可以通过 jdbc 将会话存储到数据库。
CacheManager 缓存控制器。来管理如用户,角色,权限等的缓存的;因为这些数据基本上很少去改变,放到缓存中后可以提高访问的性能。

Shiro 认证、授权

认证

身份认证:就是判断一个用户是否为合法用户的处理过程。最常用的简单身份认证方式是系统通过核对用户输入的用户名和口令,看其是否与系统中存储的该用户的用户名和口令一致,来判断用户身份是否正确

在认证过程中,涉及三个概念:

  •     Subject:主体。主体可以是用户、程序等,进行认证的都称为主体
  •     Principal:身份信息,是主体(Subject)进行身份认证的标识,标识必须具有唯一性。如:用户名、手机号、邮箱地址等,一个主体可以有多个身份,但是必须有一个主身份(Primary Principal)。
  •     Credential:凭证信息。只有主体自己知道的安全信息,如密码、证书等

授权

授权方式:

  •     基于角色
  •     基于资源

权限字符串
权限字符串的规则是:资源标识符:操作:资源实例标识符,意思是:对哪个资源的哪个实例具有什么操作,“:”是资源/操作/实例的分割符,权限字符串也可以使用 * 通配符。如:

  •     用户创建权限:user:create,或user:create:*
  •     用户修改实例 001 的权限:user:update:001
  •     用户实例 001 的所有权限:user:*:001

快速入门

引入POM依赖

<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-core</artifactId>
    <version>1.13.0</version>
</dependency>

创建初始化文件

shiro.ini:位于 resources 资源目录下。

# 约定写法
[users]
# 用户名=密码(,角色)
christy=123456,admin
zzc=666666,super
tide=654321,guest

[roles]
super=*
admin=guest:*
guest=user:delete:zhangsan

建立测试类

这里,分为3个步骤:准备、认证、授权。

 1     @Test
 2     public  void testShiroAuthor() {
 3         //准备阶段//
 4         // 1.创建安全管理器对象
 5         DefaultSecurityManager securityManager = new DefaultSecurityManager();
 6         // 2.给安全管理器设置 Realm(域)
 7         securityManager.setRealm(new IniRealm("classpath:shiro.ini"));
 8         // 3.给全局安全工具类 SecurityUtils 设置安全管理器
 9         SecurityUtils.setSecurityManager(securityManager);
10         // 4.拿到当前的 Subject
11         Subject subject = SecurityUtils.getSubject();
12         // 5.创建令牌
13         AuthenticationToken token = new UsernamePasswordToken("christy","123456");
14         System.out.println("token=" + token.getPrincipal() + " " + token.getCredentials() );    //  token=christy [C@7adda9cc
15         try {
16             //认证阶段//
17             // 6.用户认证
18             System.out.println("认证状态:" + subject.isAuthenticated());        // 认证状态:false
19             subject.login(token);
20             System.out.println("认证状态:" + subject.isAuthenticated());        // 认证状态:true
21         } catch (UnknownAccountException e){
22             e.printStackTrace();
23             System.out.println("认证失败:用户不存在!");
24         } catch (IncorrectCredentialsException e){
25             e.printStackTrace();
26             System.out.println("认证失败:密码不正确!");
27         } catch (Exception e){
28             e.printStackTrace();
29         }
30         //授权//
31         // 7.角色授权
32         System.out.println("角色授权:" +subject.hasRole("admin"));      // 角色授权:true
33         // 8.资源授权
34         System.out.println("资源授权"+subject.isPermitted("guest:update:01"));  //资源授权true
35     }

自定义Realm

前面的测试类。用户名、密码、角色授权都是放在.ini的初始文件中。实际业务中,我们的用户名、密码和角色授权等基础信息。可能存储在数据库中。此时,我们可以自定义Realm。

查看源代码知:有两个抽象方法:

    认证:AuthenticatingRealm#doGetAuthenticationInfo(AuthenticationToken)
    授权:AuthorizingRealm#doGetAuthorizationInfo(PrincipalCollection)

且:AuthorizingRealm 继承于 AuthenticatingRealm。意味着自定义的 Reaml 只要继承 AuthorizingRealm,便可重写认证、授权方法

自定义 Reaml

 1 public class CustomerRealm extends AuthorizingRealm {
 2 
 3     // 授权
 4     @Override
 5     protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
 6         return null;
 7     }
 8 
 9     /**
10      * 认证方法
11      * @param authenticationToken the authentication token containing the user's principal and credentials.
12      * @return
13      * @throws AuthenticationException
14      */
15     @Override
16     protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
17         String username = "christy";        // 返回查询到的结果
18         String password = "123456";         // 返回查询到的结果
19         // 在token中获取用户名
20         String principal = (String) authenticationToken.getPrincipal();
21         System.out.println("获取到用户输入的用户名"+principal);
22         // 模拟根据身份信息从数据库查询,假设根据用户名,查询到 用户名:principal  密码 123456
23         if(username.equals(principal)){
24             // 参数说明:用户名 | 密码 | 当前realm的名字
25             return new SimpleAuthenticationInfo(principal,password, this.getName());
26         }
27         return null;
28     }
29 
30 }

测试

1 DefaultSecurityManager securityManager = new DefaultSecurityManager();
2 securityManager.setRealm(new CustomerRealm());

实现授权

前面给Realm认证。并未授权。这里重写授权方法。

/**
 *  授权
 * @param principalCollection the primary identifying principals of the AuthorizationInfo that should be retrieved.
 * @return
 */
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    // 从系统返回的身份信息集合中获取主身份信息(用户名)
    String primaryPrincipal = (String) principalCollection.getPrimaryPrincipal();
    System.out.println("用户名" + primaryPrincipal);
    // TODO 根据用户名获取当前用户的角色信息,以及权限信息
    SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
    // 将数据库中查询到的角色信息赋值给权限对象
    simpleAuthorizationInfo.addRole("admin");
    simpleAuthorizationInfo.addRole("user");
    // 将数据库中查询权限信息赋值给权限对象
    simpleAuthorizationInfo.addStringPermission("user:*:01");
    simpleAuthorizationInfo.addStringPermission("product:create");
    return simpleAuthorizationInfo;
}

授权打印的测试方法,这里省略。

加密

按照前面的操作。密码直接存于数据库中,这样并不安全。我们希望数据库存储的是加密后的密码。

Shiro 中提供了一整套的加密算法,并且提供了随机盐。Shiro 使用指定的加密算法将用户密码和随机盐进行加密,并按照指定的散列次数将散列后的密码存储在数据库中。由于随机盐每个用户可以不同,这就极大的提高了密码的安全性。
Md5Hash:有三个构造方法:

  • public Md5Hash(Object source):只加密
  • public Md5Hash(Object source, Object salt):加密、加盐
  • public Md5Hash(Object source, Object salt, int hashIterations):加密、加盐、加散列次数

加密方法示例:

1 String passwod = "123456";
2 // 只加密
3 System.out.println(new Md5Hash(passwod).toHex()); // e10adc3949ba59abbe56e057f20f883e
4 // 加密、加盐
5 System.out.println(new Md5Hash(passwod,"1q2w3e").toHex());  // 9eab7472e164bb8c1b823ae960467f74
6 // 加密、加盐、加散列次数
7 System.out.println(new Md5Hash(passwod,"1q2w3e",1024).toHex()); // 41a4e25bcf1272844e38b19047dd68a0

加密加盐后的认证方法:

 @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String username = "christy";        // 返回到查询的用户名
        String passwordToMd5 = "41a4e25bcf1272844e38b19047dd68a0";         // 返回加密后的密码
        // 在token中获取用户名
        String principal = (String) authenticationToken.getPrincipal();
        System.out.println("获取到用户输入的用户名"+principal);
        // 模拟根据身份信息从数据库查询,假设根据用户名,查询到 用户名:principal  密码 123456
        if(username.equals(principal)){
            // 参数说明:用户名 | 密码 | 当前realm的名字
            return new SimpleAuthenticationInfo(principal,passwordToMd5, this.getName());
        }
        return null;
    }

 参考网址

https://blog.csdn.net/sco5282/article/details/133642535

标签:用户名,入门,用户,认证,println,授权,快速,Shiro
From: https://www.cnblogs.com/luyj00436/p/18427417

相关文章

  • 黑马PM-基础入门-认识产品经理
    合格的产品经理什么是产品什么是产品经理想清楚产品怎么做的人产品经理的分类产品经理的岗位职责产品经理的能力素质产品经理未来趋势C端-轻量化应用开发,智能终端,视频内容创作,电商消费升级AR购物,虚拟社交,自动驾驶B端-基础侧云数智物赋能,云服务,业务侧低代......
  • 黑马PM-基础入门-问题思考维度
    抓住核心用户为什么要抓住核心用户了解付费点,更好优化产品怎么描述核心用户供需关系人口特征(年龄,地域)熟悉程度(新,老,专家用户)业务场景产品定位+运营数据如何抓取核心用户场景化分析场景5要素用户停留在某个特定的空间的时间里,对应的情境下产生的故事情节就是场......
  • 黑马PM-基础入门-产品解决方案
    需求分析多多体验产品功能优先级划分功能价值用户体验......
  • 黑马PM-基础入门-项目立项
    项目方案可行性分析产品规划立项评审......
  • 黑马PM-基础入门-思维导图入门
    ......
  • 神仙级AI大模型入门教程,从入门到精通非常详细,只看这一篇就够了!!!
    2024最新全套大模型学习资料:大模型学习成长路线、书籍&学习文档、视频教程、项目实战、面试题汇总等,免费分享~有需要的同学可以通过【微信扫描下方二维码】,即可免费领取!!!一、大模型学习成长路线学习新技能,方向至关重要。正确的学习路线图可以为你节省时间,少走弯路;方向不......
  • STM32入门之定时器输入捕获部分
            IC输入捕获,与输出比较一样也有有四个通道,分别与输出比较共用4个CCR寄存器,通过通道输入电平信号,我们可以检测到电平跳变,然后将CNT的值锁存到CCR寄存器中,实现测量频率,占空比,用于电机测速等。那我们首先来介绍一下测量频率的原理         频率测量的......
  • 较快速的最大带权独立集算法
    前言重新来吧别输在过去最得意的事上。只是单纯的记录一下这个小知识点。很多时候,题目可以转化为求最大带权最小点覆盖或者是最大独立集。但是他又经常把这个范围给到\(n\le40\)这种看上去可以用指数又不太能用指数的情况。可能这个时候你就需要用到短小精悍的它。基......
  • idea怎么快速生成get set方法,快捷键是什么?
    idea怎么快速生成getset方法参考文章:IntelliJIDEA生成get/set方法的快捷键是什么1、生成某个getset方法alt+enter快捷键:alt+enter2.生成整个类或者某个getset方法alt+insert快捷键:alt+insert点击后,会出现下图弹窗,你可以多选或者单选这些属性对象,然后点击ok......
  • FPGA Verilog基本语句(语法)FPGA入门
    本篇文章主要写了在Verilog环境下,FPGA基本语法和数据类型。可以通过导航键快速进入assign语句、always语句等其他内容!对于Verilog(FPGA):module     ...                   ==》构成主体endmodulemodule模块名(【端口......