Shiro学习_01(入门)

Shrio简介

Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。

shiro主要功能

  • Subject: 主体,代表了当前 “用户”,这个用户不一定是一个具体的人,与当前应用交互的任何东西都是 Subject,如网络爬虫,机器人等;即一个抽象概念;
    所有 Subject 都绑定到 SecurityManager,与 Subject 的所有交互都会委托给 SecurityManager;
    可以把 Subject 认为是一个门面;SecurityManager 才是实际的执行者;

  • SecurityManager: 安全管理器;即所有与安全有关的操作都会与 SecurityManager 交互;且它管理着所有 Subject;
    可以看出它是 Shiro 的核心,它负责与后边介绍的其他组件进行交互,
    可以把它看成SpringMVC的 DispatcherServlet 前端控制器;

  • Realm: 域,Shiro 从从 Realm 获取安全数据(如用户、角色、权限),就是说 SecurityManager 要验证用户身份,
    那么它需要从 Realm 获取相应的用户进行比较以确定用户身份是否合法;
    也需要从 Realm 得到用户相应的角色 / 权限进行验证用户是否能进行操作;
    可以把 Realm 看成 DataSource,即安全数据源。

  • 简单的一个 Shiro 应用:
    1、应用代码通过 Subject 来进行认证和授权,而 Subject 又委托给 SecurityManager;
    2、我们需要给 Shiro 的 SecurityManager 注入 Realm,从而让 SecurityManager 能得到合法的用户及其权限进行判断。

Shiro架构

  • Shrio不提供维护用户/权限,而是通过Realm让开发人员自己住入

Subject:主体,可以看到主体可以是任何可以与应用交互的 “用户”;

SecurityManager:相当于 SpringMVC 中的 DispatcherServlet 或者 Struts2 中的 FilterDispatcher;是 Shiro 的心脏;
所有具体的交互都通过 SecurityManager 进行控制;它管理着所有 Subject、且负责进行认证和授权、及会话、缓存的管理。

Authenticator:认证器,负责主体认证的,这是一个扩展点,如果用户觉得 Shiro 默认的不好,可以自定义实现;
其需要认证策略(Authentication Strategy),即什么情况下算用户认证通过了;

Authrizer:授权器,或者访问控制器,用来决定主体是否有权限进行相应的操作;即控制着用户能访问应用中的哪些功能;

Realm:可以有 1 个或多个 Realm,可以认为是安全实体数据源,即用于获取安全实体的;
可以是 JDBC 实现,也可以是 LDAP 实现,或者内存实现等等;由用户提供;
注意:Shiro 不知道你的用户 / 权限存储在哪及以何种格式存储;所以我们一般在应用中都需要实现自己的 Realm;

SessionManager:如果写过 Servlet 就应该知道 Session 的概念,Session 呢需要有人去管理它的生命周期,这个组件就是 SessionManager;
而 Shiro 并不仅仅可以用在 Web 环境,也可以用在如普通的 JavaSE 环境、EJB 等环境;
所以Shiro 抽象了一个自己的 Session 来管理主体与应用之间交互的数据;
这样的话,比如我们在 Web 环境用,刚开始是一台 Web 服务器;接着又上了台 EJB 服务器;
这时想把两台服务器的会话数据放到一个地方,这个时候就可以实现自己的分布式会话(如把数据放到 Memcached 服务器);

SessionDAO:DAO 大家都用过,数据访问对象,用于会话的 CRUD,
比如我们想把 Session 保存到数据库,那么可以实现自己的 SessionDAO,通过如 JDBC 写到数据库;
比如想把 Session 放到 Memcached 中,可以实现自己的 Memcached SessionDAO;
另外 SessionDAO 中可以使用 Cache 进行缓存,以提高性能;

CacheManager:缓存控制器,来管理如用户、角色、权限等的缓存的;因为这些数据基本上很少去改变,放到缓存中后可以提高访问的性能

Cryptography:密码模块,Shiro 提供了一些常见的加密组件用于如密码加密 / 解密的。

创建Springboot工程,导入shiro依赖

<dependency>
        <groupId>org.apache.shiro</groupId>
        <artifactId>shiro-core</artifactId>
        <version>1.7.1</version>
</dependency>
<!-- 这里有用到日志打印,所以引入 -->
<dependency>
         <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>1.7.30</version>
        <scope>test</scope>
</dependency>

创建shiro.ini文件

  • 在resources下创建shiro.ini
[users]
shiro=123456
boot=456789

测试代码

package com.shiro.test;

import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.subject.Subject;

@Slf4j
public class ShiroTest {
    public static void main(String[] args) {
        // 1.创建安全管理器对象
        DefaultSecurityManager securityManager = new DefaultSecurityManager();
        // 2.给安全管理器设置realm(范围)
        securityManager.setRealm(new IniRealm("classpath:shiro.ini"));
        // 3.SecurityUtils给全局安全工具类设置安全管理器
        SecurityUtils.setSecurityManager(securityManager);
        // 4.关键对象subject主体
        Subject subject = SecurityUtils.getSubject();
        // 5.创建令牌
        // 假设username、password是从数据库获取
        UsernamePasswordToken token = new UsernamePasswordToken("shiro", "123456");
        try {
            // 认证前
            log.info("认证前状态:" + subject.isAuthenticated());
            // 执行用户认证
            subject.login(token);
            // 认证后
            log.info("认证后状态:" + subject.isAuthenticated());
        } catch (AuthenticationException e) {
            e.printStackTrace();
            log.error("认证失败,用户名或密码不存在");
        }
    }
}

如果用户名密码错误

UsernamePasswordToken token = new UsernamePasswordToken("shiro", "111111");

提示异常信息

"C:\Program Files\Java\jdk1.8.0_181\bin\java.exe" "-javaagent:D:\Program Files\JetBrains\IntelliJ IDEA 2020.1\lib\idea_rt.jar=14731:D:\Program Files\JetBrains\IntelliJ IDEA 2020.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_181\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar;E:\SpringBoot_Code\shiro\target\classes;D:\Users\HL\.m2\repository\org\apache\shiro\shiro-core\1.7.1\shiro-core-1.7.1.jar;D:\Users\HL\.m2\repository\org\apache\shiro\shiro-lang\1.7.1\shiro-lang-1.7.1.jar;D:\Users\HL\.m2\repository\org\apache\shiro\shiro-cache\1.7.1\shiro-cache-1.7.1.jar;D:\Users\HL\.m2\repository\org\apache\shiro\shiro-crypto-hash\1.7.1\shiro-crypto-hash-1.7.1.jar;D:\Users\HL\.m2\repository\org\apache\shiro\shiro-crypto-core\1.7.1\shiro-crypto-core-1.7.1.jar;D:\Users\HL\.m2\repository\org\apache\shiro\shiro-crypto-cipher\1.7.1\shiro-crypto-cipher-1.7.1.jar;D:\Users\HL\.m2\repository\org\apache\shiro\shiro-config-core\1.7.1\shiro-config-core-1.7.1.jar;D:\Users\HL\.m2\repository\org\apache\shiro\shiro-config-ogdl\1.7.1\shiro-config-ogdl-1.7.1.jar;D:\Users\HL\.m2\repository\commons-beanutils\commons-beanutils\1.9.4\commons-beanutils-1.9.4.jar;D:\Users\HL\.m2\repository\commons-collections\commons-collections\3.2.2\commons-collections-3.2.2.jar;D:\Users\HL\.m2\repository\org\apache\shiro\shiro-event\1.7.1\shiro-event-1.7.1.jar;D:\Users\HL\.m2\repository\org\slf4j\slf4j-api\1.7.30\slf4j-api-1.7.30.jar;D:\Users\HL\.m2\repository\org\springframework\boot\spring-boot-starter\2.4.3\spring-boot-starter-2.4.3.jar;D:\Users\HL\.m2\repository\org\springframework\boot\spring-boot\2.4.3\spring-boot-2.4.3.jar;D:\Users\HL\.m2\repository\org\springframework\spring-context\5.3.4\spring-context-5.3.4.jar;D:\Users\HL\.m2\repository\org\springframework\spring-aop\5.3.4\spring-aop-5.3.4.jar;D:\Users\HL\.m2\repository\org\springframework\spring-beans\5.3.4\spring-beans-5.3.4.jar;D:\Users\HL\.m2\repository\org\springframework\spring-expression\5.3.4\spring-expression-5.3.4.jar;D:\Users\HL\.m2\repository\org\springframework\boot\spring-boot-autoconfigure\2.4.3\spring-boot-autoconfigure-2.4.3.jar;D:\Users\HL\.m2\repository\org\springframework\boot\spring-boot-starter-logging\2.4.3\spring-boot-starter-logging-2.4.3.jar;D:\Users\HL\.m2\repository\ch\qos\logback\logback-classic\1.2.3\logback-classic-1.2.3.jar;D:\Users\HL\.m2\repository\ch\qos\logback\logback-core\1.2.3\logback-core-1.2.3.jar;D:\Users\HL\.m2\repository\org\apache\logging\log4j\log4j-to-slf4j\2.13.3\log4j-to-slf4j-2.13.3.jar;D:\Users\HL\.m2\repository\org\apache\logging\log4j\log4j-api\2.13.3\log4j-api-2.13.3.jar;D:\Users\HL\.m2\repository\org\slf4j\jul-to-slf4j\1.7.30\jul-to-slf4j-1.7.30.jar;D:\Users\HL\.m2\repository\jakarta\annotation\jakarta.annotation-api\1.3.5\jakarta.annotation-api-1.3.5.jar;D:\Users\HL\.m2\repository\org\springframework\spring-core\5.3.4\spring-core-5.3.4.jar;D:\Users\HL\.m2\repository\org\springframework\spring-jcl\5.3.4\spring-jcl-5.3.4.jar;D:\Users\HL\.m2\repository\org\yaml\snakeyaml\1.27\snakeyaml-1.27.jar;D:\Users\HL\.m2\repository\org\springframework\boot\spring-boot-devtools\2.4.3\spring-boot-devtools-2.4.3.jar;D:\Users\HL\.m2\repository\org\projectlombok\lombok\1.18.18\lombok-1.18.18.jar" com.shiro.test.ShiroTest
15:52:36.390 [main] DEBUG org.apache.shiro.io.ResourceUtils - Opening resource from class path [shiro.ini]
15:52:36.398 [main] DEBUG org.apache.shiro.config.Ini - Parsing [users]
15:52:36.400 [main] DEBUG org.apache.shiro.realm.text.IniRealm - Discovered the [users] section.  Processing...
15:52:36.407 [main] INFO com.shiro.test.ShiroTest - 认证前状态:false
15:52:36.407 [main] DEBUG org.apache.shiro.realm.AuthenticatingRealm - Looked up AuthenticationInfo [shiro] from doGetAuthenticationInfo
15:52:36.407 [main] DEBUG org.apache.shiro.realm.AuthenticatingRealm - AuthenticationInfo caching is disabled for info [shiro].  Submitted token: [org.apache.shiro.authc.UsernamePasswordToken - shiro, rememberMe=false].
15:52:36.407 [main] DEBUG org.apache.shiro.authc.credential.SimpleCredentialsMatcher - Performing credentials equality check for tokenCredentials of type [[C and accountCredentials of type [java.lang.String]
15:52:36.408 [main] DEBUG org.apache.shiro.authc.credential.SimpleCredentialsMatcher - Both credentials arguments can be easily converted to byte arrays.  Performing array equals comparison
15:52:36.409 [main] ERROR com.shiro.test.ShiroTest - 认证失败,用户名或密码不存在
org.apache.shiro.authc.IncorrectCredentialsException: Submitted credentials for token [org.apache.shiro.authc.UsernamePasswordToken - shiro, rememberMe=false] did not match the expected credentials.
	at org.apache.shiro.realm.AuthenticatingRealm.assertCredentialsMatch(AuthenticatingRealm.java:603)
	at org.apache.shiro.realm.AuthenticatingRealm.getAuthenticationInfo(AuthenticatingRealm.java:581)
	at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doSingleRealmAuthentication(ModularRealmAuthenticator.java:180)
	at org.apache.shiro.authc.pam.ModularRealmAuthenticator.doAuthenticate(ModularRealmAuthenticator.java:273)
	at org.apache.shiro.authc.AbstractAuthenticator.authenticate(AbstractAuthenticator.java:198)
	at org.apache.shiro.mgt.AuthenticatingSecurityManager.authenticate(AuthenticatingSecurityManager.java:106)
	at org.apache.shiro.mgt.DefaultSecurityManager.login(DefaultSecurityManager.java:275)
	at org.apache.shiro.subject.support.DelegatingSubject.login(DelegatingSubject.java:260)
	at com.shiro.test.ShiroTest.main(ShiroTest.java:31)

Process finished with exit code 0

常用异常类型

  • 错误的帐号:UnknownAccountException
  • 错误的凭证(密码):IncorrectCredentialsException
  • 禁用的帐号:DisabledAccountException
  • 锁定的帐号:LockedAccountException
  • 登录失败次数过多:ExcessiveAttemptsException
  • 过期的凭证:ExpiredCredentialsException
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hanlin-hl

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值