shiro授权的源码分析

从realm中获取所有需要的用户,角色,权限

从Subject开始,

The term <em>principal</em> is just a fancy security term for any identifying attribute(s) of an application
user, such as a username, or user id, or public key, or anything else you might use in your application to
identify a user.

打开boolean isPermitted(Permission permission)到达DelegatingSubject

public boolean isPermitted(Permission permission) {
        return hasPrincipals() && securityManager.isPermitted(getPrincipals(), permission);
    }

是securityManager在工作

打开isPermitted,到达AuthorizingSecurityManager

public boolean isPermitted(PrincipalCollection principals, Permission permission) {
        return this.authorizer.isPermitted(principals, permission);
    }

此处是插曲,插曲开始=========================================================

AuthorizingSecurityManager是什么?

Shiro support of a {@link SecurityManager} class hierarchy that delegates all
authorization (access control) operations to a wrapped {@link Authorizer Authorizer} instance. That is,
this class implements all the <tt>Authorizer</tt> methods in the {@link SecurityManager SecurityManager}
interface, but in reality, those methods are merely passthrough calls to the underlying ‘real‘
<tt>Authorizer</tt> instance.

先要找authorizer:

public abstract class AuthorizingSecurityManager extends AuthenticatingSecurityManager {

    /**
     * The wrapped instance to which all of this <tt>SecurityManager</tt> authorization calls are delegated.
     */
    private Authorizer authorizer;

    /**
     * Default no-arg constructor that initializes an internal default
     * {@link org.apache.shiro.authz.ModularRealmAuthorizer ModularRealmAuthorizer}.
     */
    public AuthorizingSecurityManager() {
        super();
        this.authorizer = new ModularRealmAuthorizer();
    }

    /**
     * Returns the underlying wrapped <tt>Authorizer</tt> instance to which this <tt>SecurityManager</tt>
     * implementation delegates all of its authorization calls.
     *
     * @return the wrapped <tt>Authorizer</tt> used by this <tt>SecurityManager</tt> implementation.
     */
    public Authorizer getAuthorizer() {
        return authorizer;
    }

    /**
     * Sets the underlying <tt>Authorizer</tt> instance to which this <tt>SecurityManager</tt> implementation will
     * delegate all of its authorization calls.
     *
     * @param authorizer the <tt>Authorizer</tt> this <tt>SecurityManager</tt> should wrap and delegate all of its
     *                   authorization calls to.
     */
    public void setAuthorizer(Authorizer authorizer) {
        if (authorizer == null) {
            String msg = "Authorizer argument cannot be null.";
            throw new IllegalArgumentException(msg);
        }
        this.authorizer = authorizer;
    }

找到了,原来AuthorizingSecurityManager中的authorizer是new ModularRealmAuthorizer()

插曲结束=========================================================

打开this.authorizer.isPermitted(principals, permission)

看到:

知道authorizer是new ModularRealmAuthorizer(),所以点开ModularRealmAuthorizer看到:

public boolean isPermitted(PrincipalCollection principals, Permission permission) {
        assertRealmsConfigured();
        for (Realm realm : getRealms()) {
            if (!(realm instanceof Authorizer)) continue;
            if (((Authorizer) realm).isPermitted(principals, permission)) {
                return true;
            }
        }
        return false;
    }

这里出现了Realm

打开getRealms()到达了ModularRealmAuthorizer,神奇:

public ModularRealmAuthorizer(Collection<Realm> realms) {
        setRealms(realms);
    }

看到在ModularRealmAuthorizer的构造器中注入了realm,

原来AuthorizingSecurityManager在初始化的时候,已经把realm注入到属性authorizer中了就是ModularRealmAuthorizer中了

接下来打开(Authorizer) realm).isPermitted(principals, permission)

应该选择AuthorizingRealm,打开:

public boolean isPermitted(PrincipalCollection principals, Permission permission) {
        AuthorizationInfo info = getAuthorizationInfo(principals);
        return isPermitted(permission, info);
    }

打开getAuthorizationInfo(principals)

protected AuthorizationInfo getAuthorizationInfo(PrincipalCollection principals) {

        if (principals == null) {
            return null;
        }

        AuthorizationInfo info = null;

        if (log.isTraceEnabled()) {
            log.trace("Retrieving AuthorizationInfo for principals [" + principals + "]");
        }

        Cache<Object, AuthorizationInfo> cache = getAvailableAuthorizationCache();
        if (cache != null) {
            if (log.isTraceEnabled()) {
                log.trace("Attempting to retrieve the AuthorizationInfo from cache.");
            }
            Object key = getAuthorizationCacheKey(principals);
            info = cache.get(key);
            if (log.isTraceEnabled()) {
                if (info == null) {
                    log.trace("No AuthorizationInfo found in cache for principals [" + principals + "]");
                } else {
                    log.trace("AuthorizationInfo found in cache for principals [" + principals + "]");
                }
            }
        }

        if (info == null) {
            // Call template method if the info was not found in a cache
            info = doGetAuthorizationInfo(principals);
            // If the info is not null and the cache has been created, then cache the authorization info.
            if (info != null && cache != null) {
                if (log.isTraceEnabled()) {
                    log.trace("Caching authorization info for principals: [" + principals + "].");
                }
                Object key = getAuthorizationCacheKey(principals);
                cache.put(key, info);
            }
        }

        return info;
    }

首次登录,缓存是空的,所以应该看info==null的部分,打开doGetAuthorizationInfo(principals)

走到头了,到这授权就走到头了

看到它是AuthenticatingRealm的子类,所以具有父类的所有方法,

所以授权是用的这个类的方法doGetAuthorizationInfo(PrincipalCollection principals)

所以继承这个类,重写这个方法就可以自定义自己的授权了

AuthorizingSecurityManager的继承关系:

有这些方法:

时间: 2024-12-28 20:42:53

shiro授权的源码分析的相关文章

shiro登录模块源码分析

接触和使用shiro还是有好大一段时间,可惜并没有搞明白其实的原理和机制.因为工作中使用的框架都封装好了,so......并没有去研究. 原来一直猜想的是shiro可以直接连接数据库,验证用户名和密码.但是又没在实体类中找到有什么特殊的标记注解之类的. 就有点好奇了,于是趁这两天工作不是那么紧张了,就跟了下源码. 如有不对,请留言指正.蟹蟹! 红色部分是主要代码: UsernamePasswordToken token = new UsernamePasswordToken(user.getUs

Shiro 源码分析

http://my.oschina.net/huangyong/blog/215153 Shiro 是一个非常优秀的开源项目,源码非常值得学习与研究. 我想尝试做一次 不一样 的源码分析:源码分析不再是一个人的自我享受,而是大家共同探讨与相互学习. 目录 Shiro 之 入口:EnvironmentLoaderListener[由 黄勇 分享] Shiro 之 Filter(上):ShiroFilter[由 黄勇 分享] Shiro 之 Filter(下) Shiro 之 Realm[由 Dea

【.NET Core项目实战-统一认证平台】第八章 授权篇-IdentityServer4源码分析

[.NET Core项目实战-统一认证平台]开篇及目录索引 上篇文章我介绍了如何在网关上实现客户端自定义限流功能,基本完成了关于网关的一些自定义扩展需求,后面几篇将介绍基于IdentityServer4(后面简称Ids4)的认证相关知识,在具体介绍ids4实现我们统一认证的相关功能前,我们首先需要分析下Ids4源码,便于我们彻底掌握认证的原理以及后续的扩展需求. .netcore项目实战交流群(637326624),有兴趣的朋友可以在群里交流讨论. 一.Ids4文档及源码 文档地址 http:/

Shiro 登录认证源码详解

Shiro 登录认证源码详解 Apache Shiro 是一个强大且灵活的 Java 开源安全框架,拥有登录认证.授权管理.企业级会话管理和加密等功能,相比 Spring Security 来说要更加的简单. 本文主要介绍 Shiro 的登录认证(Authentication)功能,主要从 Shiro 设计的角度去看这个登录认证的过程. 一.Shiro 总览 首先,我们思考整个认证过程的业务逻辑: 获取用户输入的用户名,密码: 从服务器数据源中获取相应的用户名和密码: 判断密码是否匹配,决定是否

keystone源码分析(一)——Paste Deploy的应用

本keystone源码分析系列基于Juno版Keystone,于2014年10月16日随Juno版OpenStack发布. Keystone作为OpenStack中的身份管理与授权模块,主要实现系统用户的身份认证.基于角色的授权管理.其他OpenStack服务的地址发现和安全策略管理等功能.Keystone作为开源云系统OpenStack中至关重要的组成部分,与OpenStack中几乎所有的其他服务(如Nova, Glance, Neutron等)都有着密切的联系.同时,Keystone作为开源

java使用websocket,并且获取HttpSession,源码分析

一:本文使用范围 此文不仅仅局限于spring boot,普通的spring工程,甚至是servlet工程,都是一样的,只不过配置一些监听器的方法不同而已. 本文经过作者实践,确认完美运行. 二:Spring boot使用websocket 2.1:依赖包 websocket本身是servlet容器所提供的服务,所以需要在web容器中运行,像我们所使用的tomcat,当然,spring boot中已经内嵌了tomcat. websocket遵循了javaee规范,所以需要引入javaee的包 <

YII框架源码分析(百度PHP大牛创作-原版-无广告无水印)

                        YII 框架源码分析             百度联盟事业部--黄银锋   目 录 1. 引言 3 1.1.Yii 简介 3 1.2.本文内容与结构 3 2.组件化与模块化 4 2.1.框架加载和运行流程 4 2.2.YiiBase 静态类 5 2.3.组件 6 2.4.模块 9 2.5 .App 应用   10 2.6 .WebApp 应用   11 3.系统组件 13 3.1.日志路由组件  13 3.2.Url 管理组件  15 3.3.异常

MapReduce源码分析之JobSubmitter(一)

JobSubmitter,顾名思义,它是MapReduce中作业提交者,而实际上JobSubmitter除了构造方法外,对外提供的唯一一个非private成员变量或方法就是submitJobInternal()方法,它是提交Job的内部方法,实现了提交Job的所有业务逻辑.本文,我们将深入研究MapReduce中用于提交Job的组件JobSubmitter. 首先,我们先看下JobSubmitter的类成员变量,如下: // 文件系统FileSystem实例 private FileSystem

ABP源码分析三十六:ABP.Web.Api

这里的内容和ABP 动态webapi没有关系.除了动态webapi,ABP必然是支持使用传统的webApi.ABP.Web.Api模块中实现了一些同意的基础功能,以方便我们创建和使用asp.net webApi. AbpApiController:这是一个抽象基类,继承自ApiController,是AB WebApi系统中所有controller的基类.如下图中,其封装了ABP核心模块中提供的大多数的功能对象.同时实现了一些公共的方法.它有四个派生类:DynamicApiController<