(二)Shiro之一些重要的组件和工具类

由于笔者水平有限,难免有说不清楚,或者理解有偏差的地方,望指正。


SecurityManager:
SecurityManager是shiro的核心组件,安全管理器;它的主要实现类有DefaultWebSecurityManager,并且当你在不指定的情况下会通过以下方法进行:

protected WebSecurityManager createDefaultSecurityManager() {
		//该方法是在AbstractShiroFilter中的方法,这是在web应用中用到的过滤器,一般会在web.xml中配置ShiroFilter 而,shiroFilter则extends AbstractShiroFilter;所以当在shiro.ini中不指定或者与Spring集成的时候;便会生成这个默认的安全器类
        return new DefaultWebSecurityManager();
 }

SecurityManager接口继承了Authenticator, Authorizer, SessionManager三个接口;
并且提供了一下三个方法:

    //登录
    Subject login(Subject subject, AuthenticationToken authenticationToken) throws AuthenticationException;
    //登出
    void logout(Subject subject);
    //创建Subject
    Subject createSubject(SubjectContext context);

SecurityUtils:
以下是它所含的代码:

private static SecurityManager securityManager;
public static Subject getSubject() {
        Subject subject = ThreadContext.getSubject();
        if (subject == null) {
            subject = (new Subject.Builder()).buildSubject();
            ThreadContext.bind(subject);
        }
        return subject;
    }
    public static void setSecurityManager(SecurityManager securityManager) {
        SecurityUtils.securityManager = securityManager;
    }
    public static SecurityManager getSecurityManager() throws UnavailableSecurityManagerException {
        SecurityManager securityManager = ThreadContext.getSecurityManager();
        if (securityManager == null) {
            securityManager = SecurityUtils.securityManager;
        }
        if (securityManager == null) {
            String msg = "No SecurityManager accessible to the calling code, either bound to the " +
                    ThreadContext.class.getName() + " or as a vm static singleton.  This is an invalid application " +
                    "configuration.";
            throw new UnavailableSecurityManagerException(msg);
        }
        return securityManager;
    }

可以将安全管理器组件,利用setSecurityManagement()方法设置到私有对象securityManager中,然后获取到Subject对象,然后进行登录登出的操作。

Subject:
Subject current = SecurityUtils.getSubject();`Subject是一个接口;从SecurityUtils工具类中的getSubject()静态方法中获取得到,
方法如下:

public static Subject getSubject() {
        Subject subject = ThreadContext.getSubject();
        if (subject == null) {
            subject = (new Subject.Builder()).buildSubject();
            ThreadContext.bind(subject);
        }
        return subject;
    }

可以看出,是从当前线程上下文中获取得到的;而它代表的是:A Subject represents state and security operations for a single application user. These operations include authentication (login/logout), authorization (access control), and session access. It is Shiro’s primary mechanism for single-user security functionality.

UsernamePasswordToken:
一个包含用户名和密码的令牌,这是需要去校验的用户信息,Subject提供了login(token)方法;

Realm
realm是shiro中一个比较重要的接口,它提供了供应用进行安全实体如:用户、角色和权限的认证和授权操作。对接的数据源可以是jdbc、file system i/o、jpa等

    String getName();

    boolean supports(AuthenticationToken token);

    AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException;

但是在使用过程中,大家一般不会直接去实现Realm接口进行自定义操作,而是往往继承它的子类:AuthenticatingRealm 、AuthorizingRealm;一般只需要继承AuthorizingRealm便可以,因为它同时继承了AuthenticatingRealm;有以下两个方法需要实现:

@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		//进行授权认证
		return null;
	}

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		//进行身份验证
		return new SimpleAuthenticationInfo(username, password, "myRealm");
	}

当然,需要注意的是自定义的Realm实现类需要在初始化的配置文件或者是spring的xml中进行添加,注给RealmSecurityManager的realms属性

 private Collection<Realm> realms;
 public void setRealms(Collection<Realm> realms) {
        if (realms == null) {
            throw new IllegalArgumentException("Realms collection argument cannot be null.");
        }
        if (realms.isEmpty()) {
            throw new IllegalArgumentException("Realms collection argument cannot be empty.");
        }
        this.realms = realms;
        afterRealmsSet();
    }
原文地址:https://www.cnblogs.com/Kevin-1992/p/12608425.html