P.S. Also, if you authenticate a Subject every time you use it (e.g.
like in REST calls, where you may authenticate every REST request),
you don't need sessions, since Subject state is re-created on every
authentication.  You can turn off sessions entirely.

This is all covered in the documentation:
http://shiro.apache.org/session-management.html#SessionManagement-SessionsandSubjectState

HTH,

--
Les Hazlewood | @lhazlewood
CTO, Stormpath | http://stormpath.com | @goStormpath | 888.391.5282

On Wed, May 15, 2013 at 9:38 AM, Les Hazlewood <[email protected]> wrote:
> 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.
>>
>>

Reply via email to