Shiro source code analysis (1) - Shiro opening

本文在于分析Shiro源码,对于新学习的朋友可以参考
[开涛博客](http://jinnianshilongnian.iteye.com/blog/2018398)进行学习。

Introduction

  • SecurityManager: Security Manager, the core component of Shiro. Shiro manages internal component instances through SecurityManager, and provides various services for security management through it.
  • Authenticator: Authenticator, which verifies whether the AuthenticationToken is valid.
  • Authorizer: Authorizer, handles roles and permissions.
  • SessionManager: Session manager, manages Session.
  • Subject: The current operation subject, indicating the current operation user.
  • SubjectContext: Subject context data object.
  • AuthenticationToken: Authentication token information (username, password, etc.).
  • ThreadContext: Thread context object, responsible for binding objects to the current thread.

In the process of learning and using Shiro, we all know that the SecurityManager interface is the most core interface in Shiro. We will analyze along this interface.

The following code is the definition of the SecurityManager interface:

public interface SecurityManager extends Authenticator, Authorizer, SessionManager {

    /**
     * 登录
     */
    Subject login(Subject subject, AuthenticationToken authenticationToken) throws AuthenticationException;

    /**
     * 登出
     */
    void logout(Subject subject);

    /**
     * 创建Subject
     */
    Subject createSubject(SubjectContext context);

}

Three methods are defined in SecurityManager, namely login, logout and create Subject. Usually we use it like this. First create a Subject object, and then authenticate the login by calling the login method and passing in the authentication information token.

Subject subject = SecurityUtils.getSubject(); 
UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");
subject.login(token);

SecurityUtils Analysis

A convenient tool class SecurityUtils is provided in Shiro. The core function of SecurityUtils is to obtain SecurityManager and Subject. These two interfaces are peripheral interfaces provided by Shiro for use during development.

The SecurityManager is defined statically in SecurityUtils, which means that the SecurityManager object exists only in the application.

private static SecurityManager securityManager;

1. Get SecurityManager

First get it from ThreadContext, if not, get it from SecurityUtils property securityManager. There must be a SecurityManager instance object, otherwise an exception will be thrown.

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;
}

2. Get Subject

First get it from ThreadContext, if it does not exist, create a new Subject and store it in ThreadContext so that it can be obtained next time.

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

The important thing in the above code is to create the Subject through the buildSubject() method provided by the Subject.Builder class. The SubjectContext object is also created when the Subject is created, that is to say, there is a one-to-one correspondence between Subject and SubjectContext. The following code is the constructor of the Subject.Builder class.

public Builder(SecurityManager securityManager) {
	if (securityManager == null) {
		throw new NullPointerException("SecurityManager method argument cannot be null.");
	}
	this.securityManager = securityManager;
	// 创建了SubjectContext实例对象
	this.subjectContext = newSubjectContextInstance();
	if (this.subjectContext == null) {
		throw new IllegalStateException("Subject instance returned from 'newSubjectContextInstance' " +
				"cannot be null.");
	}
	this.subjectContext.setSecurityManager(securityManager);
}

The buildSubject() method actually calls the createSubject(SubjectContext subjectContext) method in the SecurityManager interface.

public Subject buildSubject() {
	return this.securityManager.createSubject(this.subjectContext);
}

Summarize

This article mainly analyzes the createSubject(SubjectContext subjectContext) method in the SecurityManager interface in detail through SecurityUtils.getSubject(). The other two methods are analyzed in detail when analyzing the Subject.

In addition, we will find that SecurityManager inherits the three interfaces of Authenticator, Authorizer and SessionManager, so as to realize various services provided by SecurityManager for security management. In the next article, Authenticator, Authorizer, and SessionManager will be analyzed separately, so that we basically have a grasp of SecurityManager.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325342355&siteId=291194637