springboot 4 - shiro简介

Apache Shiro是一个强大的Java安全框架,提供认证、授权、加密和会话管理等功能。本文详细介绍了Shiro的核心组件、架构、配置基础及权限管理,适合希望深入了解Shiro的开发者。

 Apache Shiro 是一个强大易用的 Java 安全框架,提供了认证、授权、加密和会话管理等功能 。
    Shiro 能做什么 ???
      认证:验证用户的身份
      授权:对用户执行访问控制:判断用户是否被允许做某事
      管理:在任何环境下使用 Session API,即使没有 Web 或EJB 容器。
      加密:以更简洁易用的方式使用加密功能,保护或隐藏数据防止被偷窥
      Realms:聚集一个或多个用户安全数据的数据源
      单点登录(SSO)功能:为没有关联到登录的用户启用 "Remember Me“ 服务

  Shiro 的主要功能

 

Shiro 的四大核心部分

    Authentication(身份验证):简称为“登录”,即证明用户是谁。

    Authorization(授权):访问控制的过程,即决定是否有权限去访问受保护的资源。

    Session Management(会话管理):管理用户特定的会话,即使在非 Web 或 EJB 应用程序。

    Cryptography(加密):通过使用加密算法保持数据安全

  shiro 还提供以下扩展:

    Web Support:主要针对web应用提供一些常用功能。

    Caching:缓存可以使应用程序运行更有效率。

    Concurrency:多线程相关功能。

    Testing:帮助我们进行测试相关功能

    "Run As":一个允许用户假设为另一个用户身份(如果允许)的功能,有时候在管理脚本很有用。

    "Remember Me" :记住用户身份,提供类似购物车功能。

 

Shiro 架构 3 个核心组件

 

 

 Subject :正与系统进行交互的人,或某一个第三方服务。所有 Subject 实例都被绑定到(且这是必须的)一个SecurityManager 上。

  SecurityManager:Shiro 架构的心脏,用来协调内部各安全组件,管理内部组件实例,并通过它来提供安全管理的各种服务。当 Shiro 与一个 Subject 进行交互时,实质上是幕后的 SecurityManager 处理所有繁重的

Subject 安全操作。

  Realms :本质上是一个特定安全的 DAO。当配置 Shiro 时,必须指定至少一个 Realm 用来进行身份验证或授权。Shiro 提供了多种可用的 Realms 来获取安全相关的数据。如关系数据库(JDBC),INI 及属性文件等。可以

定义自己 Realm 实现来代表自定义的数据源。

 

Shiro 架构

  

 

Authenticator :执行对用户的身份验证(登录)的组件。Authenticator 从一个或多个 Realm 中获得数据以验证用户的身份。 若存在多个realm,则接口 AuthenticationStrategy 会确定什么样算是验证成功(例如,如果一个 Realm 成功,而其他的均失败,是否登录成功)。

  Authorizer :验证用户能否访问应用中的受保护的资源。

  SessionManager :可在任何应用或架构层一致地使用 Session API

  SessionDAO:SessionManager 执行 Session 持久化(CRUD)操作。

  CacheManager :对 Shiro 组件提供缓存支持。

  Cryptography:Shiro 的 API 大幅度简化 Java API 中繁琐的密码加密

  Realms:Shiro 通过 Realms 来获取相应的安全数据

 

 Shiro 配置基础:users

  Shiro 被设计成能够在任何环境下工作,从简单的命令行应用程序到企业群集应用。由于环境的多样性,使得 Shiro 可以使用多种配置机制。

    ini 配置:ini 实际上是一个文本配置,包含了由唯一命名的项来组织的键/值对。

    [users] 部分允许定义一组静态的用户帐户

      每行的格式:username = password, roleName1, roleName2, …

Shiro 配置基础:roles

  [roles] 部分允许把定义在 [users] 部分中的角色与权限关联起来

    每行的格式:rolename = permissionDefinition1, permissionDefinition2, …

    permissionDefinition 是一个任意的字符串,但大多数人将会使用符合 org.apache.shiro.authz.permission.WildcardPermission 格式的字符串。

  注意:

    如果一个独立的 permissionDefinition 需要被内部逗号分隔(例如,printer:5thFloor:print,info),则需要用户双引号环绕该定义,以避免错误解析。  

    如果角色不想关联权限,则不需要在 [roles] 部分把它们列出来。只需定义在 [user] 部分中定义角色名就足以创建尚不存在的角色。

    仅定义非空的 [users] 或 [roles] 部分就将自动地触发org.apache.shiro.realm.text.IniRealm 实例的创建

Shiro 的 Permissions

  基础语法之简单的字符串:即用简单的字符串来表示一个权限,如:user (相当于:user:*)

  基础语法之多层次管理:

    例如:user:query、user:edit 

    

    多个值:每个部件能够保护多个值。因此,除了授予用户 user:query 和 user:edit 权限外,也可以简单地授予他们一个:user:query, edit

    还可以用 * 号代替所有的值,如:user:* , 也可以写:*:query,表示某个用户在所有的领域都有 query 的权限

 

  基础语法之实例级访问控制

    这种情况通常会使用三个部件:域、操作、被付诸实施的实例。如:user:edit:manager

    也可以使用通配符来定义,如:user:edit:*、user:*:*、user:*:manager

    部分省略通配符:缺少的部件意味着用户可以访问所有与之匹配的值,比如:user:edit  等价于 user:edit :*、user  等价于 user:*:*

  注意:通配符只能从字符串的结尾处省略部件,也就是说 user:edit  并不等价于 user:*:edit

身份认证:Authentication

  Authentication :身份验证——通过提交用户的身份和凭证给 Shiro,以判断它们是否和应用程序预期的相匹配。

  基本概念

    Principals(身份):Subject 的 identifying attributes(标识属性)。比如我们登录提交的用户名。

    Credentials(凭证):用来作为一种起支持作用的证据,此证据包含身份证明。比如我们登录提供的密码

  认证的基本步骤

    收集Subjects 提交的Principals(身份)和Credentials(凭证);

    提交Principals(身份)和Credentials(凭证)进行身份验证;

    如果提交成功,则允许访问,否则重新进行身份验证或者阻止访问。

  AuthenticationToken:Shiro 中代表提交的 Principals(身份) 和 Credentials (凭证) 的身份验证系统的最基本接口。

  UsernamePasswordToken :AuthenticationToken 的接口的实现类,支持最常见的用户名/密码的身份验证

  提交用户名/密码进行认证

    Subject currentUser = SecurityUtils.getSubject();

    currentUser.login(token);

  处理认证成功和失败

    认证成功:没有返回,也没有异常,通过。

    认证失败,拋出异常,可以在程序中捕获并处理

  认证顺序

认证过程

 

  Step 1:应用程序代码调用 Subject.login 方法,传递创建好的包含终端用户的 Principals(身份)和 Credentials(凭证)的 AuthenticationToken 实例

  Step 2:Subject 实例,通常为 DelegatingSubject(或子类)委托应用程序的 SecurityManager 通过调用 securityManager.login(token) 开始真正的验证。

  Step 3:SubjectManager 接收 token,调用内部的 Authenticator 实例调用 authenticator.authenticate(token)。 Authenticator 通常是一个 ModularRealmAuthenticator 实例,支持在身份验证中协调一个或多个Realm 实例。

  Step 4:如果应用程序中配置了一个以上的 Realm,ModularRealmAuthenticator 实例将利用配置好的AuthenticationStrategy 来启动 Multi-Realm 认证尝试。在Realms 被身份验证调用之前,期间和以后,

AuthenticationStrategy 被调用使其能够对每个Realm 的结果作出反应。

  Step 5:每个配置的 Realm 用来帮助看它是否支持提交的AuthenticationToken。如果支持,那么支持 Realm 的 getAuthenticationInfo 方法将会伴随着提交的 token 被调用。getAuthenticationInfo 方法有效地代表一

个特定 Realm 的单一的身份验证尝试。

 注销

  logout(注销):currentUser.logout();

  调用 logout() 方法时,现有 Session 将失效,而且身份将失去关联(在Web 应用程序中,RememberMe cookie 将被删除)。

  在 Subject 注销后,该 Subject 的实例被再次认为是匿名的。

  注意:WEB 应用程序记住身份往往依靠 Cookie,然而Cookie 只能在 Response 被返回后被删除,所以建议在调用subject.logout() 后立即向终端重定向一个新的视图或页面。这样即能保证与安全相关的 Cookie 都能像预期的

一样被删除。

  授权: Authorization

  授权:又称访问控制—控制谁有权限在应用程序中做什么。

  授权检查的例子:用户是否能访问某个网页,编辑数据,或打使用这台打印机

  授权的三要素:权限、角色和用户 。

  需要在应用程序中对用户和权限建立关联:通常的做法是将权限分配给角色,然后将角色分配给一个或多个用户。

  权限:Shiro 安全机制最核心的元素。它在应用程序中明确声明了被允许的行为。一个格式良好的权限声明可以清晰表达出用户对该资源拥有的权限。在 Shiro 中主要通过通配符表达式来完成权限的描述。

 角色:Role

  角色:一个命名的实体, 通常代表一组行为或职责。 这些行为演化为在一个应用中能或者不能做的事情。角色通常分配给用户帐户

     一个角色拥有一个权限的集合。授权验证时,需要判断当前角色是否拥有指定的权限。这种角色权限可以对该角色进行详细的权限描述。 Shiro官方推荐使用这种方式。

  Shiro的三种授权方式

    编写代码:在 Java 代码中用像 if 和 else 块的结构执行授权检查。

    JDK 的注解:可以添加授权注解给 Java 方法

    JSP 标签库:可以控制基于角色和权限的JSP 页面输出。

编程授权

  通过使用 subject 的方法来实现角色的判断,常用的 API:

    hasRole(String roleName)

    hasRoles(List<String> roleNames)

    hasAllRoles(Collection<String> roleNames)

  断言支持:

    Shiro 还支持以断言的方式进行授权验证。断言成功,不返回任何值,程序继续执行;断言失败时,将抛出异常信息。常用方法:

    checkRole(String roleName) 、

    checkRoles(Collection<String>roleNames)、

    checkRoles(String… roleNames)

 

  基于权限对象的实现

    isPermitted(Permission p)、isPermitted(List<Permission> perms)、isPermittedAll(Collection<Permission> perms)  

  基于字符串的实现

    if (currentUser.isPermitted("printer:print:laserjet4400n"))

    isPermitted(String perm)、isPermitted(String... perms)、isPermittedAll(String... perms)

  权限的实现也都可以采用断言的方式,相关方法:

    checkPermission(Permission p)、checkPermission(String perm)、checkPermissions(Collection<Permission> perms)、checkPermissions(String... perms)

授权的顺序

 

  Step 1:应用程序或框架代码调用任何 Subject 的hasRole*, checkRole*, isPermitted*,或者checkPermission*方法的变体,传递任何所需的权限

  Step 2:Subject 的实例—通常是 DelegatingSubject(或子类),调用securityManager 的对应的方法。

  Step 3:SecurityManager 调用 org.apache.shiro.authz.Authorizer 接口的对应方法。默认情况下,authorizer 实例是一个 ModularRealmAuthorizer 实例,它支持协调任何授权操作过程中的一个或多个Realm 实例。

  Step 4:每个配置好的 Realm 被检查是否实现了相同的 Authorizer 接口。如果是,Realm 各自的 hasRole*, checkRole*,isPermitted*,或 checkPermission* 方法将被调用。

Realm

  Realm:访问应用程序安全数据(如用户、角色及权限)的组件。

  Realm 通常和数据源是一对一的对应关系,如关系数据库、文件系统或其他类似资源。Realm 实质上就是一个访问安全数据的 DAO。

  数据源通常存储身份验证数据(如密码的凭证)以及授权数据(如角色或权限),所以每个Realm 都能够执行身份验证和授权操作。

  Realms的认证实现

  Shiro 的认证过程由 Realm 执行,SecurityManager 会调用 org.apache.shiro.realm.Realm 的 getAuthenticationInfo(AuthenticationToken token) 方法。

  实际开发中,通常会提供 org.apache.shiro.realm.AuthenticatingRealm 的实现类,并在该实现类中提供 doGetAuthenticationInfo(AuthenticationToken token)方法的具体实现

    1、检查提交的进行认证的令牌信息

    2、根据令牌信息从数据源(通常为数据库)中获取用户信息

    3、对用户信息进行匹配验证。

    4、验证通过将返回一个封装了用户信息的 AuthenticationInfo 实例。

    5、验证失败则抛出 AuthenticationException 异常信息。

 

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值