shiro讲解之 Realm

shiro讲解之 Realm

本章节我们将详细讲解一下Shiro的 Realm。


概念

  • 官方文档

    • As mentioned above, Realms act as the ‘bridge’ or ‘connector’ between Shiro and your application’s security data. When it comes time to actually interact with security-related data like user accounts to perform authentication (login) and authorization (access control), Shiro looks up many of these things from one or more Realms configured for an application. You can configure as many Realms as you need (usually one per data source) and Shiro will coordinate with them as necessary for both authentication and authorization.
  • 通常理解

    • 通常而言我们对Shiro Realm 的理解应在于她是 Shiro 和我们应用程序之间的一个桥梁,用于在认证和授权时对安全数据的对比和校验。比如在进行登录验证时,我们的数据对比是在Realm(一般默认该Realm 继承了 AuthorizingRealm )的 doGetAuthenticationInfo 中实现,又例如授权时对用户角色的权限的判定也将在 doGetAuthenticationInfo 中实现。
  • Shiro Realm 在应用中的位置

    这里写图片描述


实例

以下我们将说明下Realm 在 Spring Context中的一些配置问题。此处我们已单Realm 为例。多Realm的配置与;逻辑将在后续章节中说明。

  • Realm 在Spring Context中的配置

    • 在SecurityManager Bean中的配置
      由Shiro 的设计架构我们知道SecurityManager是 Shiro 主要核心功能的实际实现者(参照Shiro Detailed Architecture),因而我们自定义的Realm 因交由 SecurityManager 统一管理。

      • SecurityManager Bean

        <!-- 1.配置SecurityManager -->
        <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
        <property name="cacheManager" ref="cacheManager" />
        <property name="realm" ref="shiroRealm"></property>
        </bean>
        

        以上为一个较为标准的 SecurityManager 配置(未配置sessionMode)。

      • Realm Bean

        <!-- 3.配置Realm -->
        <bean id="shiroRealm" class="com.shiro.example.interceptor.realm.ShiroRealm">
        <property name="credentialsMatcher">
            <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
                <property name="hashAlgorithmName" value="SHA-1"></property>
                <property name="hashIterations" value="1024"></property>
            </bean>
        </property>
        </bean>
        

        以上Realm 我们设置了加密方法和加密次数。

  • 一个Realm 例子

    package com.shiro.example.interceptor.realm;
    
    import java.util.HashSet;
    import java.util.Set;
    
    import org.apache.shiro.authc.AuthenticationException;
    import org.apache.shiro.authc.AuthenticationInfo;
    import org.apache.shiro.authc.AuthenticationToken;
    import org.apache.shiro.authc.LockedAccountException;
    import org.apache.shiro.authc.SimpleAuthenticationInfo;
    import org.apache.shiro.authc.UnknownAccountException;
    import org.apache.shiro.authc.UsernamePasswordToken;
    import org.apache.shiro.authz.AuthorizationInfo;
    import org.apache.shiro.authz.SimpleAuthorizationInfo;
    import org.apache.shiro.crypto.hash.SimpleHash;
    import org.apache.shiro.realm.AuthorizingRealm;
    import org.apache.shiro.subject.PrincipalCollection;
    import org.apache.shiro.util.ByteSource;
    
    import com.shiro.example.entity.SubjectEntity;
    
    public class ShiroRealm extends AuthorizingRealm {
    
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            System.out.println("[FirstRealm] doGetAuthenticationInfo");
    
            // 1. 把 AuthenticationToken 转换为 UsernamePasswordToken
            UsernamePasswordToken upToken = (UsernamePasswordToken) token;
    
            // 2. 从 UsernamePasswordToken 中来获取 username
            String username = upToken.getUsername();
    
            // 3. 调用数据库的方法, 从数据库中查询 username 对应的用户记录
            SubjectEntity principals = new SubjectEntity("580655386dc0bef1105a44f9dcbe4a1d3a7b0781", "Dustyone");
    
            // 4. 若用户不存在, 则可以抛出 UnknownAccountException 异常
            if ("unknown".equals(username)) {
                throw new UnknownAccountException("用户不存在!");
            }
    
            // 5. 根据用户信息的情况, 决定是否需要抛出其他的 AuthenticationException 异常.
            if ("monster".equals(username)) {
                throw new LockedAccountException("用户被锁定");
            }
    
            // 6. 根据用户的情况, 来构建 AuthenticationInfo 对象并返回. 通常使用的实现类为:
            // SimpleAuthenticationInfo
            // 以下信息是从数据库中获取的.
            // 1). principal: 认证的实体信息. 可以是 username, 也可以是数据表对应的用户的实体类对象.
            Object principal = principals.getUsername();
            // 2). credentials: 密码.
            Object credentials = principals.getPassword(); // "fc1709d0a95a6be30bc5926fdb7f22f4";
    
            // 3). realmName: 当前 realm 对象的 name. 调用父类的 getName() 方法即可
            String realmName = getName();
            // 4). 盐值.
            ByteSource credentialsSalt = ByteSource.Util.bytes(username);
            /*
             * SimpleAuthenticationInfo info = new
             * SimpleAuthenticationInfo(principal, credentials, realmName);
             */
            SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, credentials, credentialsSalt,realmName);
    
    
            return info;
        }
    
    
    
        // 授权会被 shiro 回调的方法
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            // 1. 从 PrincipalCollection 中来获取登录用户的信息
            Object principal = principals.getPrimaryPrincipal();
    
            // 2. 利用登录的用户的信息来用户当前用户的角色或权限(可能需要查询数据库)
            Set<String> roles = new HashSet<>();
            roles.add("user");
            if ("admin".equals(principal)) {
                roles.add("admin");
            }
    
            // 3. 创建 SimpleAuthorizationInfo, 并设置其 roles 属性.
            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);
    
            // 4. 返回 SimpleAuthorizationInfo 对象.
            return info;
        }
    }
    

Realm类型

下面我们将列举Shiro 封装了哪些原始Realm 可供我我们继承使用。

这里写图片描述

  • Realm (Shiro 最基础 Realm)

    • CachingRealm (负责缓存处理)

      • AuthenticatingRealm (负责身份认证)

        • AuthorizingRealm (统一负责身份认证和授权)

          • AbstractLdapRealm (使用虚拟的轻量目录访问协议)
            Shiro 的认证和签权可以通过 LDAP 来实现

            • ActiveDirectoryRealm
              Shiro 认证和授权将通过 Active Directory 来实现。
          • DefaultLdapRealm (使用默认LDAP 实现认证和授权)

            • JndiLdapRealm
              该 Realm 在 1.1 V 之后 被 DefaultLdapRealm 替代
          • JdbcRealm (使用JDBC 实现认证和授权)

          • ShiroRealm (我们自定义的Realm)

          • SimpleAccountRealm (向上编程设计)

            shiro对于通过文本方式定义账号、权限提供了Ini、Properties两种方式。SimpleAccountRealm类的users、roles集合分别用来保存账号、权限信息。

            • TextConfigurationRealm (向上编程设计)
              根据子类的users、roles配置完成解析操作

              • IniRealm (从ini配置文件中读取用户的信息并更具该信息进行认证和授权)

              • PropertiesRealm (从Property配置文件中读取用户的信息并更具该信息进行认证和授权)


小结

  • Shiro 提供了丰富多样的 Realm 类型即说明了 Shiro 支持多渠道数据交互模式来进行用户的认证和授权,比如使用 ini、property 文件,使用 JDBC 与数据库交互(可以 ini 文件的形式也可以使用纯 持久化语句)、LDAP 和 Active Directory。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值