Shiro 使用姿势和核心类

Shiro 使用姿势和核心类,第1张

一、 配置 shiroFilter
ShiroFilterFactoryBean 是 shiro 为 spring 提供的主 filter 的 factoryBean 类,这个factoryBean 类会创建SpringShiroFilter, 里面内置了很多 filter ,当然用户自定义的 filter 需要用户手动加进来。

 

二、 几个核心类 1. SecurityManager

 集认证、授权以及session 管理于一体,方便开发者使用。

如何使用,我们还是看源码注释:

所以下面这三行代码使我们生产中用的比较多的:

            Subject subject = SecurityUtils.getSubject();
            NoPasswordToken token = new NoPasswordToken(username);
            subject.login(token);
login 成功后会创建 subject 并将 principal 填充到 subject 中, 创建 session :

    public void login(AuthenticationToken token) throws AuthenticationException {
        clearRunAsIdentitiesInternal();
        // 1. 创建 subject 并填充 principal
        Subject subject = securityManager.login(this, token);

        PrincipalCollection principals;

        String host = null;

        if (subject instanceof DelegatingSubject) {
            DelegatingSubject delegating = (DelegatingSubject) subject;
            //we have to do this in case there are assumed identities - we don't want to lose the 'real' principals:
            principals = delegating.principals;
            host = delegating.host;
        } else {
            principals = subject.getPrincipals();
        }

        if (principals == null || principals.isEmpty()) {
            String msg = "Principals returned from securityManager.login( token ) returned a null or " +
                    "empty value.  This value must be non null and populated with one or more elements.";
            throw new IllegalStateException(msg);
        }
        this.principals = principals;
        this.authenticated = true;
        if (token instanceof HostAuthenticationToken) {
            host = ((HostAuthenticationToken) token).getHost();
        }
        if (host != null) {
            this.host = host;
        }
        // 2. 创建 session
        Session session = subject.getSession(false);
        if (session != null) {
            this.session = decorate(session);
        } else {
            this.session = null;
        }
    }
2. AuthorizingRealm

securityManager 的认证和授权的实际类,

securityManager 创建时会设置自定义的 Realm ,

    @Bean("securityManager")
    public SecurityManager securityManager() {
        DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
        manager.setRealm(authRealm());

DefaultWebSecurityManager  父类 AuthorizingSecurityManager 会在 realm 设置后,赋值代理对象 authorizer

    protected void afterRealmsSet() {
        super.afterRealmsSet();
        if (this.authorizer instanceof ModularRealmAuthorizer) {
            ((ModularRealmAuthorizer) this.authorizer).setRealms(getRealms());
        }
    }

跟进 ModularRealmAuthorizer  代码:


    /**
     * Sets the realms wrapped by this Authorizer which are consulted during an authorization check.
     *
     * @param realms the realms wrapped by this Authorizer which are consulted during an authorization check.
     */
    public void setRealms(Collection realms) {
        this.realms = realms;
        applyPermissionResolverToRealms();
        applyRolePermissionResolverToRealms();
    }

很明了, 授权代理对象 Autorizer 把权限检查又交给了 realms 刚好,你自定义的 realm 就是干这事的!实现了下面 AuthorizingRealm 的两个接口:
 


 

 我们需要代码实现的就是这两个抽象方法。

三、总结

串下流程:

1. 用户直接访问某个资源时, 会进入 shiroFilter ,shiroFilter 会通过自定义的 PermissionsAuthorizationFilter 检查权限:首先看用户是否登录,如果没登录跳转到 loginurl 地址,否则检查 subject 中的用户权限。

2. subect 中的权限信息是,以 subject.login 方式登录后填充。具体在 securityManager 中,最后又到了 Realm 中 doGetAuthenticaitonInfo 方法中。

当然也可以结合 spring-security-oauth2 服务来登录,只需要将 loginurl 转向 AuthorizationEndpoint 对应的地址即可(通常类似 https://xxxx/oauth/authorize?client_id=xxx&response_type=code&redirect_uri=https://xxxx)

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/924436.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-16
下一篇2022-05-16

发表评论

登录后才能评论

评论列表(0条)

    保存