Apache Shiro certification process

3.1.1 Example

Shiro's process of verifying Subjects can be broken down into three different steps:

1. Collect Principals and Credentials submitted by Subjects;

2. Submit Principals (identity) and Credentials (certificates) for identity verification;

3. If the submission is successful, allow access, otherwise re-authenticate or block access.

Collect identity/credential information

//Exampleusingmostcommonscenarioofusername/passwordpair:

UsernamePasswordTokentoken=newUsernamePasswordToken(username,password);

//”RememberMe”built-in:

token.setRememberMe(true);

UsernamePasswordToken supports the most common username/password authentication mechanisms. At the same time, because it implements the RememberMeAuthenticationToken interface, we can set the "remember me" function through the token.

Submit entity/credential information

SubjectcurrentUser=SecurityUtils.getSubject();

currentUser.login(token);

After collecting the identity/credential information, we can obtain the current user through the SecurityUtils tool class, and then submit the authentication by calling the login method.

Authentication processing

try{

currentUser.login(token);

}catch(UnknownAccountExceptionuae){...

}catch(IncorrectCredentialsExceptionice){...

}catch(LockedAccountExceptionlae){...

}catch(ExcessiveAttemptsExceptioneae){...

}...catchyourown...

}catch(AuthenticationExceptionae){

//unexpectederror?

}

If the login method is executed and no exception message is thrown, then the user authentication is considered to be passed. Afterwards, you can call SecurityUtils.getSubject() anywhere in the application to get the currently authenticated user instance, and use subject.isAuthenticated() to determine whether the user has been authenticated will return true. On the contrary, if an exception is thrown during the execution of the login method, the authentication will be considered as a failure.

3.1.2 Procedure

The following will introduce in detail Shiro's internal processing when performing identity authentication.


As shown in the figure above, we use the authentication part of the Shiro architecture diagram to illustrate the internal processing sequence of Shiro authentication:

1. After the application constructs an AuthenticationToken instance of the terminal user authentication information, it calls the Subject.login method. The AuthenticationToken instance contains the Principals and Credentials of the end user.

2. An instance of Sbuject is usually an instance object of the DelegatingSubject class (or subclass). At the beginning of authentication, the securityManager instance set by the application is entrusted to call the securityManager.login(token) method.

3. After the SecurityManager receives the token (token) information, it will entrust the built-in Authenticator instance (usually an instance of the ModularRealmAuthenticator class) to call authenticator.authenticate(token). ModularRealmAuthenticator will adapt one or more Realm instances set during the authentication process. It actually provides a pluggable authentication mechanism for Shiro.

4. If multiple Realms are configured in the application, ModularRealmAuthenticator will perform the authentication process of multiple Realms according to the configured AuthenticationStrategy (authentication strategy). After Realm is called, AuthenticationStrategy will respond to the results of each Realm.

Note: If only one Realm is configured in the application, the Realm will be called directly without the need to configure the authentication policy.

5. Determine whether each Realm supports the submitted token. If it does, Realm will call getAuthenticationInfo(token); the getAuthenticationInfo method is the actual authentication processing. We write our custom authentication processing by overriding Realm's doGetAuthenticationInfo method.

3.1.3 Configuration

Authenticator

The implementation of ShiroSecurityManager uses an instance of ModularRealmAuthenticator by default. It supports both a single Realm and multiple Realms. If only one Realm is configured, ModularRealmAuthenticator will directly call the Realm to process the authentication information. If multiple Realm are configured, it will adapt the Realm according to the authentication strategy and find a suitable Realm to execute the authentication information.

If you want to configure the SecurityManager to be implemented through a custom Authenticator, you can set it in shiro.ini as follows:

[main]

authenticator = com.foo.bar.CustomAuthenticator

securityManager.authenticator = $authenticator

AuthenticationStrategy (Authentication Strategy)

When an application is configured with two or more Realms, ModularRealmAuthenticator relies on the internal AuthenticationStrategy component to determine the success or failure of authentication.

AuthenticationStrategy is a stateless component that is asked 4 times during authentication attempts (any necessary state required for these 4 interactions will be used as method parameters):

1. Be asked before any Realm is called;

2. Be asked immediately before the getAuthenticationInfo method of a single Realm is called;

3. Be asked immediately after the getAuthenticationInfo method of a single Realm is called;

4. Ask after all Realms have been called.

Another task of the authentication strategy is to aggregate all the result information of Realm and encapsulate it into an AuthenticationInfo instance, and return this information as the subject's identity information.

Shiro defines the realization of 3 authentication strategies:

AuthenticationStrategy class

description

AtLeastOneSuccessfulStrategy

As long as one (or more) Realm verification is successful, then the verification will be considered as successful

FirstSuccessfulStrategy

The first Realm verification is successful, the overall verification will be considered as successful, and subsequent Realm will be ignored

AllSuccessfulStrategy

All Realms are successful, the certification is considered as a success

The default implementation of the authentication strategy built in ModularRealmAuthenticator is the AtLeastOneSuccessfulStrategy method, because this method is also a widely used authentication strategy. Of course, you can also define the strategies you need through configuration files, such as:

[main]

authcStrategy = org.apache.shiro.authc.pam.FirstSuccessfulStrategy

seurityManager.authenticator.authenticationStrategy = $authcStrategy

...

RealmAuthentication Order (Realm authentication order)

From the authentication strategy just mentioned, we can see that the order of Realm in ModularRealmAuthenticator has an impact on authentication. ModularRealmAuthenticator will read the Realm configured in the SecurityManager. When performing authentication, it will traverse the Realm collection and call the getAuthenticationInfo method on all Realms that support the submitted token.

Implicit Ordering (ImplicitOrdering)

当使用Shiro 的INI 配置文件格式时,根据你在INI文件中定义好的顺序依次被处理。比如:

blahRealm = com.company.blah.Realm

fooRealm = com.company.foo.Realm

barRealm = com.company.another.Realm

SecurityManager 根据这三个Realm 的配置顺序调用,依次是blahRealm,fooRealm 和barRealm顺序调用。与下面这样的效果是一样的。

securityManager.realms = $blahRealm, $fooRealm, $barRealm

使用这种方法,你并不需要设置SecurityManager 的Realm 属性——每个定义好的realm 将会自动地被添加到realm 的属性。

显示排列(ExplicitOrdering)

明确地定义Realm的先后顺序,显式地配置securityManager.realms 的属性以表明你需要引用的Realm和它们的调用顺序。比如:

blahRealm = com.company.blah.Realm

fooRealm = com.company.foo.Realm

barRealm = com.company.another.Realm

securityManager.realms = $fooRealm, $barRealm,$blahRealm

这样调用的顺序依次是fooRealm,barRealm和blahRealm。

RealmAuthentication(Realm认证)

Realm 实质上就是一个特定安全的DAO。Realm 通常和数据源是一对一的对应关系,如关系数据库,LDAP 目录,文件系统,或其他类似资源。

若Realm 支持一个提交的AuthenticationToken,那么Authenticator 将会调用该Realm 的getAuthenticationInfo(token)方法。这代表了一个与Realm的后备数据源的认证尝试。该方法按以下方法进行:

1. 为主要的识别信息(帐户识别信息)检查token。

2. 基于principal 在数据源中寻找相吻合的帐户数据。

3. 确保token 支持的credentials 匹配那些存储在数据源的。

4. 若credentials 匹配,返回一个封装了Shiro 能够理解的帐户数据格式的AuthenticationInfo 实例。

5. 若credentials 不匹配,则抛出AuthenticationException 异常。

在上述过程中,Realm有一个职责就是匹配提交的credentials 和那些存储在Realm 后备数据存储中的credentials。Shiro 本身拥有CredentialsMatcher 实现,如SimpleCredenticalsMatcher 和HashedCredentialsMatcher,但你也可以根据自己的逻辑自定义一个实现。比如:

[main]

customMatcher = com.company.shiro.realm.CustomCredentialsMatcher

myRealm = com.company.shiro.realm.MyRealm

myRealm.credentialsMatcher = $customMatcher

...

Shiro 中默认使用的是SimpleCredentialsMatcher,SimpleCredentialsMatcher 验证该密码是否与存储在数据库中的密码相同。SimpleCredentialsMatcher不仅仅为字符串执行直接相等比较。它能够处理大多数常用的字节码,像字符串,字符数组,字节数组,文件及输入流。

除此之外Shiro 还提供了HashedCredentialsMatcher,通过单向散列化方式实现一种更安全的方式存储终端用户的credentials。配置方式如下:

[main]

credentialsMatcher = org.apache.shiro.authc.credential.Sha256CredentialsMatcher

# base64 encoding, not hex in this example:

credentialsMatcher.storedCredentialsHexEncoded = false

credentialsMatcher.hashIterations = 1024

# This next property is only needed in Shiro 1.0. Remove it in 1.1 and later:

credentialsMatcher.hashSalted =true

myRealm = com.company……

myRealm.credentialsMatcher = $credentialsMathcer

...


Guess you like

Origin blog.csdn.net/WA_MC/article/details/113483309