Have you thought about using Shiro's "RunAs" feature?

On Tue, Dec 3, 2019 at 3:41 AM Richard Adams <[email protected]>
wrote:

> Where are your permission checks located?  Can you move to check into the
> request instead of checking late in the batch process?
>
> Not really - a user's content is a series of documents which can contain
> links to other documents; also documents belonging to other people that
> have been shared; these linked  /shared documents(that require permission
> checks) are only identified during the traversal of user's content during
> the export process.
> It's possible we could do some initial scan to check permissions in the
> request thread, and then switch off permission checking in the background
> thread, but this initial scan is still likely to take some time and doesn't
> solve the issue for really large exports where this would probably still be
> too slow.
>
> Thanks Richard
>
> On 3 Dec 2019, at 00:22, Brian Demers <[email protected]> wrote:
>
> Where are your permission checks located?  Can you move to check into the
> request instead of checking late in the batch process?
>
> On Mon, Dec 2, 2019 at 5:57 PM Richard Adams <[email protected]>
> wrote:
>
>> Thanks
>>
>> On 02 December 2019 at 21:49 Brian Demers <[email protected]>
>> wrote:
>>
>> A couple of things stick out:
>>
>> 1.) You shouldn't need to call `subject.login()` directly.  This is
>> almost always handled by some framework for you (like the Shiro Servlet
>> Filter).  The same can be said for `.logout()` though to a lesser extent.
>>
>> This just seems a good entry point to encapsulate authenticating the
>> token - we have an ApiTokenRealm to authenticate the token and by using
>> this approach we can reuse  getAuthorizationInfo() method that we use for
>> username-password logins. Also if authentication fails we want to throw a
>> 401 status rather than redirect to a login page for the web UI which the
>> ShiroServlet filter does
>>
>> 2.) As for the "logout" issue, I think this is a misuse of logout.
>>
>> If you truly don't have any session/state, then the "logout" doesn't
>> _really_ have anything to clean up (like a session cache, or container
>> related session)
>> You _shouldn't_ be logging a user out if you expect the subject to remain
>> active (as you still need the context of the given subject).  My guess
>> (based on minimal data) is that you are forcing a logout, because you are
>> also managing the "login"?
>>
>> You are probably right, as much as anything it seems symmetrical, if we
>> are logging users in, to log them out again after the response is generated
>>
>>
>> Things get a little tricky when you with async tasks though, and the best
>> solution might depend on what you do when the processing is done.  Are you
>> emailing the user some results?  Does the user poll an endpoint until the
>> job is finished?
>>
>> In the web application, the user can continue using the application while
>> the background job is running. When the job is finished, it notifies the
>> user either by email, in-app messaging or slack depending on preferences.
>> For API invocations, the client gets a jobId which they can use to query
>> for progress - we implement a thin wrapper around Spring Batch which does
>> the bulk of the job management.
>> Our application is a specialist content management system for scientific
>> researchers. The background job is an export task which iterates over
>> user's content (typically 10s to 10_000s of items) and generates HTML, PDF
>> or XML exports. The end result is a download link. For each candidate item
>> to export we do a permissions lookup to see if the user has permission to
>> read that item (hence the need for Shiro's permissions lookups).
>> From what you are saying it sounds like we can just not call logout() for
>> the API calls. But how to handle a user logging out of web application
>> while background process is running?  They may have a valid reason to
>> logout(e.g. they are working on a shared computer and they have to leave it
>> unattended) but would not want their background jobs to be
>> stopped/cancelled. Is their some way to clone a Shiro subject and bind it
>> to another thread?
>> Thanks
>> Richard
>>
>> If the user does need to logout (and I can see some valid use cases for
>> this anyway, for example, If the job runs for 3 hours and the result is
>> emailed to the user) then there is no reason for a subject to be kept
>> alive.
>> There are a few ways to work around this, but can you give us some
>> details on your async task? And why you are calling login/logout? (Maybe
>> because you don't have a custom Filter?
>> https://shiro.apache.org/web.html#Web-DefaultFilters)
>>
>> NOTE: Shiro 1.5 will contain support for Bearer tokens headers
>> <https://github.com/apache/shiro/blob/master/web/src/main/java/org/apache/shiro/web/filter/authc/BearerHttpAuthenticationFilter.java>
>> which may make your life easier too.
>>
>>
>> On Thu, Nov 28, 2019 at 7:38 AM otter606 < [email protected]>
>> wrote:
>>
>> Hello
>>  We have happily been using Shiro for some years now for our Spring MVC
>> web
>> application authentication and authorisation using standard Shiro filters
>> to
>> login and logout users.
>> Recently we implemented an asynchronous 'export' feature where a request
>> launches a background thread to perform a possibly long running ( a few
>> minutes) task. The request returns a job ID that the client app can use
>> to
>> interrogate progress.  We bind the Subject to the Callable using
>> <code>task
>> = subject.associateWith(task);</code> and it all works fine, as in the
>> web
>> application the user generally remains logged in while the export is
>> happening.
>>
>> We now expose this export feature through an API. Here is where we get a
>> problem, maybe we are not using Shiro correctly here.
>>  - We have implemented a Realm that checks for access token validity
>>  - we have set noSessionCreation to be active as the API requests are
>> supposed to be stateless
>> - if all ok we call SecurityUtils.getSubject().login so that there is an
>> authenticated principal to do permissions checks on access to resources
>> that
>> are going to be exported.
>> - When the API call is finished, in a filter we call
>> SecurityUtils.getSubject().logout() before returning the response. This
>> has
>> the effect of setting the principalsCollection to null, so all subsequent
>> permission lookups fail for the Subject. This means that permission
>> lookups
>> performed by the background thread now fail.
>>
>> Does anyone have any suggestions for how to keep a subject usable in a
>> background thread after logout() has been called? There seem to be
>> several
>> options:
>>
>> - not call logout() at the end of each API request. Would this be bad
>> practice? Would there be some accumulation of Subject or Http Session
>> instances over time and 000s of API requests?
>> - stop using Shiro for API permissions lookups - we would prefer to use
>> the
>> same permissions mechanism for all clients, so this option is not
>> attractive
>> - Use reflection to set the PrincipalCollection back into the Subject
>> after
>> calling logout - this seems a bit hacky and potentially fragile
>>
>> Any advice or examples of using Shiro to secure APIs would be greatly
>> appreciated, thanks Richard
>>
>>
>>
>> --
>> Sent from: http://shiro-user.582556.n2.nabble.com/
>>
>>
>>
>>
>
>

Reply via email to