`
Dead_knight
  • 浏览: 1202207 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
博客专栏
752c8642-b795-3fe6-946e-a4e845bffdec
Spring Securi...
浏览量:240599
33caa84e-18a6-3036-a82b-6e2106a4de63
clojure专题
浏览量:49035
E17ca077-44df-3816-a3fe-471c43f6e1e5
WebLogic11g
浏览量:237054
社区版块
存档分类
最新评论

Shiro源码分析-初始化-Realm

阅读更多
在上一篇介绍SecurityManager的初始化过程中,也有realm的粗略介绍。
realm的概念在安全领域随处可见:
各种中间件的realm、spring security的realm、shiro的realm。。。如下:
tomcat的realm:http://tomcat.apache.org/tomcat-7.0-doc/realm-howto.html
weblogic的realm:http://edocs.weblogicfans.net/wls/docs92/secintro/realm_chap.html
spring security的realmhttp://www.oschina.net/translate/spring-security-basic-authentication?lang=eng

tomcat官网对realm的定义是这样的:
A Realm is a "database" of usernames and passwords that identify valid users of a web application (or set of web applications), plus an enumeration of the list of roles associated with each valid user. You can think of roles as similar to groups in Unix-like operating systems, because access to specific web application resources is granted to all users possessing a particular role (rather than enumerating the list of associated usernames). A particular user can have any number of roles associated with their username.

我个人理解realm相当于管理账号密码、角色、权限的仓库。有异议的,欢迎一起讨论。

原谅我的啰嗦,先进入正题。
Shiro的realm类图如下:

由图可见,Realm主要还是认证、授权服务,并提供cache支持。

shiro提供了几种realm可供项目选择,一般项目中比较常用的应该是JdbcRealm,运行测试用例一般使用IniRealm。
开涛在讲解身份验证的章节中演示了两种realm的方式(ini、jdbc)
http://jinnianshilongnian.iteye.com/blog/2019547

一、Ini方式的realm:

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

还记得在前一篇介绍SecurityManager初始化中,关于realm的创建了么?

没错,就是这里。根据ini配置中的users、roles段落来解析成IniRealm的对象实例。
下面,简单跟踪一下代码吧:
    //IniRealm构造函数会调用此方法完成解析操作
    private void processDefinitions(Ini ini) {
        if (CollectionUtils.isEmpty(ini)) {
            log.warn("{} defined, but the ini instance is null or empty.", getClass().getSimpleName());
            return;
        }

        Ini.Section rolesSection = ini.getSection(ROLES_SECTION_NAME);
        if (!CollectionUtils.isEmpty(rolesSection)) {
            log.debug("Discovered the [{}] section.  Processing...", ROLES_SECTION_NAME);
            //解析roles段落交给父类完成
            processRoleDefinitions(rolesSection);
        }

        Ini.Section usersSection = ini.getSection(USERS_SECTION_NAME);
        if (!CollectionUtils.isEmpty(usersSection)) {
            log.debug("Discovered the [{}] section.  Processing...", USERS_SECTION_NAME);
            //解析users段落交给父类完成
            processUserDefinitions(usersSection);
        } else {
            ......
        }
    }

IniRealm的父类TextConfigurationRealm根据子类的users、roles配置完成解析操作
    //解析roles,并构造SimpleRole对象
    protected void processRoleDefinitions(Map<String, String> roleDefs) {
        if (roleDefs == null || roleDefs.isEmpty()) {
            return;
        }
        for (String rolename : roleDefs.keySet()) {
            String value = roleDefs.get(rolename);

            SimpleRole role = getRole(rolename);
            if (role == null) {
                role = new SimpleRole(rolename);
                add(role);
            }

            Set<Permission> permissions = PermissionUtils.resolveDelimitedPermissions(value, getPermissionResolver());
            role.setPermissions(permissions);
        }
    }

    //解析users,并构造SimpleAccount对象
    protected void processUserDefinitions(Map<String, String> userDefs) {
        if (userDefs == null || userDefs.isEmpty()) {
            return;
        }
        for (String username : userDefs.keySet()) {

            String value = userDefs.get(username);

            String[] passwordAndRolesArray = StringUtils.split(value);

            String password = passwordAndRolesArray[0];

            SimpleAccount account = getUser(username);
            if (account == null) {
                account = new SimpleAccount(username, password, getName());
                add(account);
            }
            account.setCredentials(password);

            if (passwordAndRolesArray.length > 1) {
                for (int i = 1; i < passwordAndRolesArray.length; i++) {
                    String rolename = passwordAndRolesArray[i];
                    account.addRole(rolename);

                    SimpleRole role = getRole(rolename);
                    if (role != null) {
                        account.addObjectPermissions(role.getPermissions());
                    }
                }
            } else {
                account.setRoles(null);
            }
        }
    }


二、Jdbc方式的realm:
jdbcRealm=org.apache.shiro.realm.jdbc.JdbcRealm
dataSource=com.alibaba.druid.pool.DruidDataSource
dataSource.driverClassName=com.mysql.jdbc.Driver
dataSource.url=jdbc:mysql://localhost:3306/shiro
dataSource.username=root
dataSource.password=root
jdbcRealm.dataSource=$dataSource
securityManager.realms=$jdbcRealm

由于shiro支持在ini中配置依赖注入,那么JdbcRealm中的sql信息也是可配置的。
jdbcRealm.authenticationQuery=用户查询
jdbcRealm.userRolesQuery=角色查询
jdbcRealm.permissionsQuery=权限查询

当然,如果不习惯这种方式,可以直接自定义Realm,并继承自AuthorizingRealm或者JdbcRealm都可以。
JdbcRealm通过查询数据库的认证实体、角色、权限,构造的对象分别是:SimpleAuthenticationInfo、SimpleAuthorizationInfo。
实际上,IniRealm方式构造的SimpleAccount、SimpleRole与JdbcRealm方式构造的SimpleAuthenticationInfo、SimpleAuthorizationInfo一一对应,且都实现认证接口AuthenticationInfo、授权接口AuthorizationInfo。关于更详细的讲解放在后面的认证、授权部分。

三、RealmFactory:
Shiro不仅支持Realm类型,还支持RealmFactory类型,在初始化的时候,如果配置中存在RealmFactory实现类,则直接调用其Collection<Realm> getRealms()方法。
该方式在多个realm的情况下很实用。

四、与Spring Security的比较:
Spring Security的Realm仅仅是用在basic认证方式。
Shiro的realm与Spring Security的UserDetailsService非常相似。但是命名确非常迷糊,下面进一步分析:
先看UserDetailsService接口定义:
//根据用户名称获取UserDetails
public interface UserDetailsService {
    UserDetails loadUserByUsername(String username)
        throws UsernameNotFoundException, DataAccessException;
}

UserDetails接口定义:
public interface UserDetails extends Serializable {
    //获取授权的集合
    Collection<GrantedAuthority> getAuthorities();
    String getPassword();
    String getUsername();
    boolean isAccountNonExpired();
    boolean isAccountNonLocked();
    boolean isCredentialsNonExpired();
    boolean isEnabled();
}

由此可看出,Spring Security的UserDetailsService获取的UserDetails已经拥有了授权信息。只是从接口命名中无法得知。

而Shiro的realm是把职责分解了,层次更清晰些。
后续在分析shiro的过程中,会增加与SpringSecurity的比较。
3
2
分享到:
评论
4 楼 岁月之眸 2016-03-08  
我靠
3 楼 jacking124 2014-04-08  
不错的,赞一个!!感情真心好!
2 楼 Dead_knight 2014-04-08  
endual 写道
一个讲源码,涛*哥讲应用,真是好啊。

其实我是与涛*哥说好的~~
1 楼 endual 2014-04-08  
一个讲源码,涛*哥讲应用,真是好啊。

相关推荐

    Shiro1.2.2_源码(压缩包)

    10. **配置与生命周期管理(Configuration & Lifecycle Management)**:Shiro 通过 XML 配置文件或 Java API 进行初始化,提供了对象的生命周期管理,如 Bean 的初始化、销毁等。 通过对 Shiro1.2.2 的源码分析,...

    SpringBoot-Shiro整合权限管理源码

    - **配置文件**:`ShiroConfig.java`包含了Shiro的初始化配置。 - ** Realm 实现**:`MyRealm.java`是自定义的Realm,负责从数据库获取用户信息进行认证和授权。 - **过滤器链**:配置了各种Shiro过滤器,如`...

    jsp+数据库+shiro 源码及文档

    1. **配置Shiro**:在Web应用的初始化阶段,需配置Shiro的安全管理器,并注入Realm。 Realm连接到数据库,处理认证和授权请求。 2. **认证流程**:用户登录时,JSP页面收集用户名和密码,通过HTTP请求发送到服务器...

    尚硅谷Shiro视频教程

    尚硅谷_Shiro_从数据表中初始化资源和权限 · 23.尚硅谷_Shiro_会话管理 · 24. 尚硅谷_Shiro_SessionDao · 25.尚硅谷_Shiro_缓存 · 26.尚硅谷_Shiro_认证和记住我的区别 · 27.尚硅谷_Shiro_实现Rememberme

    boot-shiro.zip

    Shiro的配置类(如ShiroConfig)会初始化Shiro的环境,包括安全管理器、 Realm(认证和授权的来源)、过滤器等。 Shiro的核心组件包括Subject(当前操作用户)、SecurityManager(安全管理器)、Realm(认证和授权...

    shiro-example

    1. **[main]**:初始化对象,如 SecurityManager、Realm、CachingProvider 等。 2. **[users]**:列出预定义的用户和他们的密码,通常在测试阶段使用。 3. **[roles]**:定义角色及其对应的权限。 4. **[filters]**...

    shiro入门

    3. **编写安全代码**:在应用启动时初始化 SecurityManager,并使用 `Subject` 接口进行认证和授权操作。 4. **过滤器配置**:在 Web 应用中配置 Shiro 过滤器链,拦截并处理请求。 5. **测试**:编写测试用例,模拟...

    springboot整合shiro视频

    通过分析该项目的源码,我们可以更深入地理解Shiro在实际项目中的运用。 五、最佳实践 1. 分离Shiro配置:将Shiro的配置独立出来,避免污染主配置,提高代码可维护性。 2. 使用Spring Security增强:Spring ...

    SpringBoot+Shiro权限管理系统脚手架.zip

    1. **Spring Boot初始化**:了解如何创建Spring Boot项目,配置pom.xml文件,添加依赖,启动类的编写等。 2. **Shiro配置**:学习如何配置Shiro,包括SecurityManager、Filter Chain定义、Realm实现,以及自定义...

    SpringBootShiro-Demo.rar

    4. **SpringBoot启动器**:SpringBoot的自动配置特性使得我们可以自定义Shiro的启动器,以便在应用启动时初始化Shiro配置。 5. **会话管理**:Shiro可以集成SpringBoot的Session管理,提供跨域session共享、session...

    Java后台管理系统开发平台,使用SpringBoot、Shiro、Layui等,界面美观实用。.zip

    2. Shiro的配置和使用:学习如何配置Shiro Realm,进行用户认证和授权,以及如何处理Session管理。 3. Layui的布局和组件使用:熟悉Layui的基本结构,学习如何组合和定制组件以满足需求。 4. 数据库设计和操作:查看...

    后端+springboot+网上商城+毕业设计

    6. **Shiro安全框架**:理解Shiro的基本组件,如Subject、Realm、Session管理等,并能实现登录、权限控制、记住我等功能。 7. **支付接口集成**:商城系统通常需要集成第三方支付平台,如支付宝、微信支付,学习...

Global site tag (gtag.js) - Google Analytics