Shiro-About Realm

Source: Internet
Author: User
Tags deprecated

Realm was also mentioned before in authentication and authorization.

Whether it's authentication or permission validation, regardless of the way the data exists, we need to access some data and convert it to a format that Shiro can recognize.

Typically a data source corresponds to a realm. Therefore, implementing a realm will use the API associated with that data source.

Typically, a data source holds data related to both identity-related data and permissions. Thus, a realm implementation class can perform both authentication and authorization operations.

Realm can be simply understood as DAO.

(Although idea generated the type Hirarchy diagram is beautiful, but too big ... Or use it back to eclipse..)

If you use the. ini configuration, we can define N realms in the [main] section, but we can use explicit (explicit) and implicit (implicit) methods to specify realm for SecurityManager (a bit of the meaning of the IOC container).

Display designation is a common way to define realm and then assign realm to SecurityManager in the order you want.

fooRealm = com.company.foo.RealmbarRealm = com.company.another.RealmbazRealm = com.company.baz.RealmsecurityManager.realms = $fooRealm, $barRealm, $bazRealm


The display of the specified method is relatively clear, and even if you do not change the realm definition, we can still allow validation and authorization to be performed in the order that we assign to SecurityManager.

If for some reason (perhaps there are too many defined realms?) Do not want to specify for Securitymanager.realms, we can also use implicit mode.

In other words, changing the above configuration to the following form is implicit:

blahRealm = com.company.blah.RealmfooRealm = com.company.foo.RealmbarRealm = com.company.another.Realm

Implicit is actually not specified, only defined (define), Shiro will search all realms in the configuration and assign them one by one to SecurityManager.

When using implicit mode, if you change the definition of realm a little bit, Shiro may surprise us.

In the article introducing authentication, the workflow of the Shiro framework is described when a validation request appears.

Here is a specific record of realm's work (although the Securiymanager validation begins, but the work of fetching data from the data source and comparing it is done by realm).

Take Modularrealmauthenticator as an example:

   Protected AuthenticationInfo domultirealmauthentication (collection<realm> Realms, Authenticationtoken token) {        Authenticationstrategy strategy = Getauthenticationstrategy ();        AuthenticationInfo aggregate = strategy.beforeallattempts (realms, token);        if (log.istraceenabled ()) {Log.trace ("iterating through {} Realms for PAM authentication", realms.size ());            } for (Realm Realm:realms) {aggregate = Strategy.beforeattempt (realm, token, aggregate); if (Realm.supports (token)) {Log.trace ("attempting to authenticate token [{}] using realm [{}]", token                , realm);                AuthenticationInfo info = null;                Throwable t = null;                try {info = realm.getauthenticationinfo (token);                    } catch (Throwable throwable) {t = Throwable; if (log.isdebugenabled ()) {String msg = "Realm" + Realm + "] threw an exception during a Multi-realm authentication attempt:";                    Log.debug (msg, t);            }} aggregate = Strategy.afterattempt (realm, token, info, aggregate, t);  } else {log.debug ("Realm [{}] does not support token {}.            Skipping realm, realm, token);        }} aggregate = Strategy.afterallattempts (token, aggregate);    return aggregate; }

Before realm begins to deal with the logic of validation, authenticator will invoke the realm's supports method to verify that the current realm supports the obtained authenticationtoken.

In general, realm checks for token types, such as checking for the same type in Authenticatingrealm.

public boolean supports(AuthenticationToken token) {    return token != null && getAuthenticationTokenClass().isAssignableFrom(token.getClass());}

In addition, Authenticatingrealm's constructor type defaults to

authenticationTokenClass = UsernamePasswordToken.class;


If the current realm supports the submitted Token,authenticator, the Getauthenticationinfo method is called.

Take Authenticatingrealm as an example (note is final):

public final AuthenticationInfo getAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {    AuthenticationInfo info = getCachedAuthenticationInfo(token);    if (info == null) {        //otherwise not cached, perform the lookup:        info = doGetAuthenticationInfo(token);        log.debug("Looked up AuthenticationInfo [{}] from doGetAuthenticationInfo", info);        if (token != null && info != null) {            cacheAuthenticationInfoIfPossible(token, info);        }    } else {        log.debug("Using cached authentication info [{}] to perform credentials matching.", info);    }    if (info != null) {        assertCredentialsMatch(token, info);    } else {        log.debug("No AuthenticationInfo found for submitted AuthenticationToken [{}].  Returning null.", token);    }    return info;}

If the authentication information can be obtained from the cache, the next step is to check if the password matches, i.e. Assertcredentialsmatch (token, info).

If no validation information exists in the cache, the following methods are called.

protected abstract AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException;

Here we do not consider the situation of caching, consider what dogetauthenticationinfo should do.

Some people (like me) do this directly in the method and verify that the Simpleauthenticationinfo instance is returned when the validation is passed, and the corresponding validation exception is thrown when the failure occurs.

But there is a assertcredentialsmatch, dogetauthenticationinfo this is not intended to use, this way of use will make credentialmatcher lose meaning.

Refer to the implementation of Jdbcrealm, just according to the identity (user name) to query and return the Simpleauthenticationinfo instance.

Then let Assertcredentialsmatch compare tokens and authenticationinfo.

protected void assertCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) throws AuthenticationException {    CredentialsMatcher cm = getCredentialsMatcher();    if (cm != null) {        if (!cm.doCredentialsMatch(token, info)) {            //not successful - throw an exception to indicate this:            String msg = "Submitted credentials for token [" + token + "] did not match the expected credentials.";            throw new IncorrectCredentialsException(msg);        }    } else {        throw new AuthenticationException("A CredentialsMatcher must be configured in order to verify " +                "credentials during authentication.  If you do not wish for credentials to be examined, you " +                "can configure an " + AllowAllCredentialsMatcher.class.getName() + " instance.");    }}

Now that we mention Credentialmatcher, let's see what he means. First, the default credentialmatcher of Authenticatingrealm is ...

public AuthenticatingRealm() {    this(null, new SimpleCredentialsMatcher());}


If we just do the password character comparison, we can not make such an interface (string comparison of pluggable + customizable?)

Before talking about authentication, said, Authenticationtoken principal and credential can be any type, just take it directly compare whether it is not only compared with the password character so simple.

Simplecredentialsmatcher is used to compare whether the two credential are the same.

Its Docredentialsmatch method returns the return value of its Equals method.

protected boolean equals(Object tokenCredentials, Object accountCredentials) {    if (log.isDebugEnabled()) {        log.debug("Performing credentials equality check for tokenCredentials of type [" +                tokenCredentials.getClass().getName() + " and accountCredentials of type [" +                accountCredentials.getClass().getName() + "]");    }    if (isByteSource(tokenCredentials) && isByteSource(accountCredentials)) {        if (log.isDebugEnabled()) {            log.debug("Both credentials arguments can be easily converted to byte arrays.  Performing " +                    "array equals comparison");        }        byte[] tokenBytes = toBytes(tokenCredentials);        byte[] accountBytes = toBytes(accountCredentials);        return Arrays.equals(tokenBytes, accountBytes);    } else {        return accountCredentials.equals(tokenCredentials);    }}

Of course, the implementation class is not just simplecredentialsmatcher ...

Simplecredentialsmatcher also followed Hashedcredentialsmatcher, and then down on all deprecated.

Speaking of Hashedcredentialsmatcher, he just added a salt to the password to improve security.

Where the hashsalted attribute is largely not considered, since the salt from Shiro 1.1 is the Non-null value returned by the Getcredentialsalt () method of Saltedauthenticationinfo.

public HashedCredentialsMatcher() {    this.hashAlgorithm = null;    this.hashSalted = false;    this.hashIterations = 1;    this.storedCredentialsHexEncoded = true; //false means Base64-encoded}

Speaking of salting will have to say Saltedauthenticationinfo, the interface inherits AuthenticationInfo, that is, in addition to principal and credential, he also has a credentialssalt.

public interface SaltedAuthenticationInfo extends AuthenticationInfo {    /**     * Returns the salt used to salt the account‘s credentials or {@code null} if no salt was used.     *     * @return the salt used to salt the account‘s credentials or {@code null} if no salt was used.     */    ByteSource getCredentialsSalt();}

Hashedcredentialsmatcher has a default salt, which is to use his principal as a salt, and later this method is deprecated.

Since 1.1, Shiro prevents the salt from being taken from the user's logon information and should be obtained from the data source.

@Deprecatedprotected Object getSalt(AuthenticationToken token) {    return token.getPrincipal();}

This series of methods and properties will completely disappear from Shiro 2.0.

Shiro-About Realm

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.