You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@shiro.apache.org by Schloool <ko...@max-schlosser.de> on 2021/04/21 14:07:41 UTC

Manual shiro configuration - No realms have been configured!

Hey folks!
While setting up a custom shiro-environment I came across a problem
outsourcing the realm initialization. Using environment variables the user
may choose a custom auth-method, such as LDAP, Database, etc.
Therefore, the corresponding shiro.ini does *not* set a specific realm
instance:


[main]
authc.loginUrl = /login
vaadin = org.vaadin.shiro.VaadinNavigationRolesAuthorizationFilter
vaadin.loginUrl = /login
authSetup = com.project.auth.AuthSetup

[urls]
/ = anon, vaadin
/login = anon, vaadin
/stations = authc, vaadin[admin]
/organizations = authc, vaadin[admin]
/station-types = authc, vaadin[admin]
/projects = authc, vaadin[admin]


However, as you can see, an instance of my class AuthSetup is initialized.
This class resolves the auth method the user wants and therefore
instantiates the custom realm. In my example, the Realm I use is a class
setting up a DefaultLdapRealm:


    @Override
    public Realm initRealm() {
        JndiLdapContextFactory contextFactory = new
JndiLdapContextFactory();

        contextFactory.setUrl(environmentResolver.getUrl());
        contextFactory.setSystemUsername("cn=read-only-admin, dc=example,
dc=com");
        contextFactory.setSystemPassword("admin");

        DefaultLdapRealm realm = new DefaultLdapRealm();
        realm.setUserDnTemplate(environmentResolver.getUserDnTemplate());
        realm.setContextFactory(contextFactory);
        return realm;
    }


The data insertes by the environment-vars are the LDAP-URL
(ldap://ldap.forumsys.com:389) and the user DN-Template
(uid={0},dc=example,dc=com). All of these data are read out correctly as I
can tell from the debug messages I am printing to my logs.
Finally, the realm created in the given method, is passed using this method
called by initializing my AuthSetup:


    private void processAuthMethod(AuthMethodChoice authMethodChoice) {
        AuthMethodFactory authMethodFactory = new AuthMethodFactory();

        AuthMethod authMethod =
authMethodFactory.getAuthMethod(authMethodChoice);
        initAuthEnvironmentResolver(authMethod);

        Realm realm = authMethod.initRealm();
        SecurityManager securityManager = new DefaultSecurityManager(realm);
        SecurityUtils.setSecurityManager(securityManager);
        System.out.println(format("Auth SecurityManager instance initialized
with custom Realm %s.", realm.getClass().getSimpleName()));
    }


As you can tell by the last lines of code in this method, I try to pass in
the loaded Realm using a DefaultSecurityManager. Also, the success message
gets printed successfully ("Auth SecurityManager instance initialized with
custom Realm DefaultLdapRealm."). Moreover, the DefaultSecurityManager seems
to be set correctly using the method, as SecurityUtils.getSecurityManager()
returns an DefaultSecurityManager instance again.
--------------------------------------

So far so good. The problem occurs when logging in using the default shiro
login()-Method. Whenever logging in, the following exception comes up:


WARN org.apache.shiro.authc.AbstractAuthenticator - Authentication failed
for token submission [org.apache.shiro.authc.UsernamePasswordToken -
ExampleUser, rememberMe=false].  Possible unexpected error? (Typical or
expected login exceptions should extend from AuthenticationException).
java.lang.IllegalStateException: Configuration error:  No realms have been
configured!  One or more realms must be present to execute an authentication
attempt.


Can anybody explain why no realm seems to be set although everything
descripted above gets executed correctly? Also, I am willing to provide more
information regarding my background system when needed.
I am thankful for every advice you can give.




--
Sent from: http://shiro-user.582556.n2.nabble.com/

Re: Manual shiro configuration - No realms have been configured!

Posted by Schloool <ko...@max-schlosser.de>.
Hey Benjamin,

Thank you a lot. Defining subclasses with custom filter-functions really did
the job!
Thanks for helping out. :)



--
Sent from: http://shiro-user.582556.n2.nabble.com/

Re: Manual shiro configuration - No realms have been configured!

Posted by Benjamin Marwell <bm...@apache.org>.
Hi Schlool,

authenticating (enabling log-in) and authorizing (getting
roles/permissions) are two different things.
This means, you implemented an AuthenticatingRealm, which will enable
your users to log-in.
Now you need to implement an AuthorizingRealm, which queries the
source for their roles, groups, permissions etc.

Consider this default:
securityManager.authorizer = org.apache.shiro.authz.ModularRealmAuthorizer # [2]

If you look at the implementation [2], it is still querying all realms.

This is documented in the Authorizer documentation [1].

[1] https://shiro.apache.org/authorization.html#modularrealmauthorizer
[2] https://github.com/apache/shiro/blob/9e68eb488644f4a8ee72c4ec736d257a66e5cc5d/core/src/main/java/org/apache/shiro/authz/ModularRealmAuthorizer.java

Am Mo., 26. Apr. 2021 um 09:16 Uhr schrieb Schloool <ko...@max-schlosser.de>:
>
> Thanks for your answer Benjamin!
> I was able to set up a custom Authenticator which selects a Realm depending
> on a given name.
> However, using this Authenticator results in issues whenever using
>
>   SecurityUtils.GetSubject().checkRole("admin");
>
> as seemingly all loaded Realms try to check the role. However, only the
> fitting Realm should be used.
> Is there any easy way to achieve this result?
>
>
>
> --
> Sent from: http://shiro-user.582556.n2.nabble.com/

Re: Manual shiro configuration - No realms have been configured!

Posted by Schloool <ko...@max-schlosser.de>.
Thanks for your answer Benjamin!
I was able to set up a custom Authenticator which selects a Realm depending
on a given name.
However, using this Authenticator results in issues whenever using

  SecurityUtils.GetSubject().checkRole("admin");

as seemingly all loaded Realms try to check the role. However, only the
fitting Realm should be used.
Is there any easy way to achieve this result?



--
Sent from: http://shiro-user.582556.n2.nabble.com/

Re: Manual shiro configuration - No realms have been configured!

Posted by Benjamin Marwell <bm...@apache.org>.
Hello Schlool,

in that case you would still be able to write your own Authenticator.
Just define as much Realms as you wish and then write your own
Authenticator which selects the Realm based on the name.

As a template you could use the ModularRealmAuthenticator[1].
Instead of iterating through the realms and trying to authenticate
with each, just check the name first and only authenticate if it
matches.

To install your custom authenticator, just put this into your ini file:

[main]
authenticator = com.foo.bar.CustomAuthenticator

blahRealm = com.company.blah.Realm
blahRealm.name = LDAP
fooRealm = com.company.foo.Realm
fooRealm.name = CONFIG
barRealm = com.company.another.Realm
barRealm.name = DATABASE
; the next line is optional
securityManager.realms = $fooRealm, $barRealm, $blahRealm

We have some examples here:
https://shiro.apache.org/authentication.html#Authentication-RealmAuthentication


[1]: https://github.com/apache/shiro/blob/9e68eb488644f4a8ee72c4ec736d257a66e5cc5d/core/src/main/java/org/apache/shiro/authc/pam/ModularRealmAuthenticator.java

- Ben

Am Mi., 21. Apr. 2021 um 22:45 Uhr schrieb Schloool <ko...@max-schlosser.de>:
>
> Thanks for your answer.
> Wouldn't using a custom ini with interpolation mean setting up multiple
> "pre-set" ini-files (e.g. for LDAP, Database, ...) so the fitting
> ini-configuration gets loaded depending on a user's choice?
>
> As an example, when the user wants to use LDAP, he would set up an
> environment such as AUTH_METHOD=LDAP. My setup would recognize this choice
> and would load the shiro-ldap.ini, which may read out env-vars using string
> interpolations for the URL and the DN-template, so the correct realm
> instance gets loaded using this special ini-file?
>
>
>
> --
> Sent from: http://shiro-user.582556.n2.nabble.com/

Re: Manual shiro configuration - No realms have been configured!

Posted by Schloool <ko...@max-schlosser.de>.
Thanks for your answer.
Wouldn't using a custom ini with interpolation mean setting up multiple
"pre-set" ini-files (e.g. for LDAP, Database, ...) so the fitting
ini-configuration gets loaded depending on a user's choice?

As an example, when the user wants to use LDAP, he would set up an
environment such as AUTH_METHOD=LDAP. My setup would recognize this choice
and would load the shiro-ldap.ini, which may read out env-vars using string
interpolations for the URL and the DN-template, so the correct realm
instance gets loaded using this special ini-file?



--
Sent from: http://shiro-user.582556.n2.nabble.com/

Re: Manual shiro configuration - No realms have been configured!

Posted by Brian Demers <br...@gmail.com>.
Shiro's Servlet Filter has a SecurityManager instance, which is configured
from your INI file. Shiro also supports a "static" security manager for
dealing with requests in your application that are NOT bound to a request
thread (queues, thread pools, scheduled tasks, etc).  Setting the "static"
security manager does NOT affect web requests.

My guess is you can simplify this configuration by just interpolating the
INI configuration (filtering in env vars and system properties)
https://stormpath.com/blog/string-interpolation-apache-shiro



On Wed, Apr 21, 2021 at 10:07 AM Schloool <ko...@max-schlosser.de> wrote:

> Hey folks!
> While setting up a custom shiro-environment I came across a problem
> outsourcing the realm initialization. Using environment variables the user
> may choose a custom auth-method, such as LDAP, Database, etc.
> Therefore, the corresponding shiro.ini does *not* set a specific realm
> instance:
>
>
> [main]
> authc.loginUrl = /login
> vaadin = org.vaadin.shiro.VaadinNavigationRolesAuthorizationFilter
> vaadin.loginUrl = /login
> authSetup = com.project.auth.AuthSetup
>
> [urls]
> / = anon, vaadin
> /login = anon, vaadin
> /stations = authc, vaadin[admin]
> /organizations = authc, vaadin[admin]
> /station-types = authc, vaadin[admin]
> /projects = authc, vaadin[admin]
>
>
> However, as you can see, an instance of my class AuthSetup is initialized.
> This class resolves the auth method the user wants and therefore
> instantiates the custom realm. In my example, the Realm I use is a class
> setting up a DefaultLdapRealm:
>
>
>     @Override
>     public Realm initRealm() {
>         JndiLdapContextFactory contextFactory = new
> JndiLdapContextFactory();
>
>         contextFactory.setUrl(environmentResolver.getUrl());
>         contextFactory.setSystemUsername("cn=read-only-admin, dc=example,
> dc=com");
>         contextFactory.setSystemPassword("admin");
>
>         DefaultLdapRealm realm = new DefaultLdapRealm();
>         realm.setUserDnTemplate(environmentResolver.getUserDnTemplate());
>         realm.setContextFactory(contextFactory);
>         return realm;
>     }
>
>
> The data insertes by the environment-vars are the LDAP-URL
> (ldap://ldap.forumsys.com:389) and the user DN-Template
> (uid={0},dc=example,dc=com). All of these data are read out correctly as I
> can tell from the debug messages I am printing to my logs.
> Finally, the realm created in the given method, is passed using this method
> called by initializing my AuthSetup:
>
>
>     private void processAuthMethod(AuthMethodChoice authMethodChoice) {
>         AuthMethodFactory authMethodFactory = new AuthMethodFactory();
>
>         AuthMethod authMethod =
> authMethodFactory.getAuthMethod(authMethodChoice);
>         initAuthEnvironmentResolver(authMethod);
>
>         Realm realm = authMethod.initRealm();
>         SecurityManager securityManager = new
> DefaultSecurityManager(realm);
>         SecurityUtils.setSecurityManager(securityManager);
>         System.out.println(format("Auth SecurityManager instance
> initialized
> with custom Realm %s.", realm.getClass().getSimpleName()));
>     }
>
>
> As you can tell by the last lines of code in this method, I try to pass in
> the loaded Realm using a DefaultSecurityManager. Also, the success message
> gets printed successfully ("Auth SecurityManager instance initialized with
> custom Realm DefaultLdapRealm."). Moreover, the DefaultSecurityManager
> seems
> to be set correctly using the method, as SecurityUtils.getSecurityManager()
> returns an DefaultSecurityManager instance again.
> --------------------------------------
>
> So far so good. The problem occurs when logging in using the default shiro
> login()-Method. Whenever logging in, the following exception comes up:
>
>
> WARN org.apache.shiro.authc.AbstractAuthenticator - Authentication failed
> for token submission [org.apache.shiro.authc.UsernamePasswordToken -
> ExampleUser, rememberMe=false].  Possible unexpected error? (Typical or
> expected login exceptions should extend from AuthenticationException).
> java.lang.IllegalStateException: Configuration error:  No realms have been
> configured!  One or more realms must be present to execute an
> authentication
> attempt.
>
>
> Can anybody explain why no realm seems to be set although everything
> descripted above gets executed correctly? Also, I am willing to provide
> more
> information regarding my background system when needed.
> I am thankful for every advice you can give.
>
>
>
>
> --
> Sent from: http://shiro-user.582556.n2.nabble.com/
>