Shiro does not create threads for permission checks. What you're
seeing is a side-effect of non-standard Shiro usage.
It is expected that you (or a config mechanism like shiro.ini or
Spring or Guice, etc) create one and only one SecurityManager instance
for your entire application. Additionally, DelegatingSubject is an
internal implementation class in Shiro - it shouldn't be used directly
by application code (it only might ever be used by non-Shiro
developers if they are writing framework-integration code for Shiro -
not for standard app use cases). If you need to create ad-hoc Subject
instances, you should use the Subject.Builder to create ad-hoc Subject
instances, passing in the SecurityManager as a constructor argument.
In any event, here is what you are seeing:
1. Shiro's default SecurityManager implementation has an internal
SessionManager.
2. This SessionManager, if sessions are used, will create a session
validation thread (to ensure that orphaned sessions can be cleaned
properly).
3. If you authenticate a user, Shiro's default storage mechanism for
authenticate state is the session. Because of #2, this will start a
session validation thread.
So by #2 and #3, if you create a SecurityManager for every
authentication, therefore, you'll create a session validation thread
for each authentication! (Thanks to Tamás for the hint). So again,
permission checks don't create threads at all - what you're seeing is
an unrelated issue due to creating a new SecurityManager every time.
Here's what I'd do in your scenario:
- Create one and only one SecurityManager. Set it on
SecurityUtils.setSecurityManager if you have to to ensure it is
re-used (although this is not recommended - you would ideally use
something like dependency injection or a configuration mechanism of
your choice that manages application singletons without using static
memory).
- Don't create DelegatingSubject instances. Use the Subject.Builder
if you have to create ad-hoc Subject instances.
For example, (very similar to Christian's example):
Subject subject = new
Subject.Builder(SecurityUtils.getSecurityManager()).buildSubject();
subject.login(usernamePasswordToken);
if (subject.isPermitted(whatever)) {
do something
}
Because you built the subject manually (and didn't use
SecurityUtils.getSubject()), the built subject is _not_ bound to the
current thread, so other calls to SecurityUtils.getSubject() will not
return the same Subject. If you manually create Subject instances in
Shiro, you are responsible for ensuring thread association if you wish
to use SecurityUtils.getSubject() in other parts of your code.
HTH,
--
Les Hazlewood | @lhazlewood
CTO, Stormpath | http://stormpath.com | @goStormpath | 888.391.5282
On Wed, May 15, 2013 at 7:47 AM, Tamás Cservenák <[email protected]> wrote:
> Session validating thread....?
>
> but by looking at the code, um, very strange use of Shiro.. :)
>
>
> On Wed, May 15, 2013 at 4:14 PM, ApacheNinja <[email protected]> wrote:
>>
>> Hello,
>>
>> Yes, we are using the latest release of Shiro. We are primarily using
>> Shiro to check user permissions. We are not using it to log in to our
>> application. We are creating our Subject using the following method:
>>
>> protected void setAuthorizerSubject(UsersDVO user){
>> DefaultSecurityManager securityManager = new
>> DefaultSecurityManager();
>> securityManager.setRealm(realm);
>> securityManager.setAuthenticator(new MockAuthenticator());
>> SecurityUtils.setSecurityManager(securityManager );
>> Subject currentUser = new DelegatingSubject(securityManager);
>> if(!currentUser.isAuthenticated()){
>> UsernamePasswordToken token = new
>> UsernamePasswordToken(user.getUserName(), "");
>> try{
>> currentUser.login(token);
>> } catch (AuthenticationException ex){
>> Log.exception(ex);
>> }
>> }
>> this.subject = currentUser;
>> }
>>
>> This is created once when the user logs in. In our application it is
>> possible to log in as a general administrator first, then log in again as
>> a
>> more specific user. So this may be called twice. We then use the Subject
>> object to call the isPermitted() object, which checks to see if the user
>> has
>> access to different portions of our application. In our Realm object we
>> have set setAuthorizationCachingEnabled(false) (I don't think this makes a
>> difference but I thought I would include this information anyway).
>> Looking
>> at the stack trace when calling isPermitted(), I see that it goes through
>> the Shiro API and then it then calls our implementation
>> doGetAuthorizationInfo() :
>>
>> @Override
>> protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection
>> principalCollection) {
>> SimpleAuthorizationInfo info = null;
>> if( user != null ) {
>> info = new SimpleAuthorizationInfo();
>> List<Role> roles =
>> roleManager.getRolesForUser(user.getUserID());
>> List<EPermission> permissions =
>> permissionManager.getPermissionsForUser(user.getUserID());
>> for(Role role : roles) {
>> info.addRole(role.getName());
>> }
>> for(EPermission permission : permissions){
>> info.addStringPermission(permission.getName());
>> }
>> }
>>
>> return info;
>> }
>>
>> Somewhere in there a new thread is being generated but I don't know where.
>>
>>
>>
>> --
>> View this message in context:
>> http://shiro-user.582556.n2.nabble.com/Too-many-threads-created-when-calling-isPermitted-tp7578725p7578734.html
>> Sent from the Shiro User mailing list archive at Nabble.com.
>
>