You are viewing a plain text version of this content. The canonical link for it is here.
Posted to user@shiro.apache.org by Mike K <mk...@semanticresearch.com> on 2010/08/23 21:27:47 UTC

Re: Permission checking on client side ?

I am thinking of using similar functionality to give some hints to an AJAX
web client about the users permission state (incomplete information like
login status and admin permissions). Current thought is to  use a cookie or
to find/implement a cookie-based session.
I guess what I am saying is that I am interested in this as well.
-- 
View this message in context: http://shiro-user.582556.n2.nabble.com/Permission-checking-on-client-side-tp5450587p5453883.html
Sent from the Shiro User mailing list archive at Nabble.com.

Re: Permission checking on client side ?

Posted by Kalle Korhonen <ka...@gmail.com>.
There's no 1.1.0 release as of yet - there are automatically posted
1.1.0 snapshots available from http://repository.apache.org/snapshots
(simple if you use Maven but not too difficult to grab the jars from
there manually).

Kalle


On Thu, Sep 16, 2010 at 10:01 AM, Mike K <mk...@semanticresearch.com> wrote:
>
> Thanks, just found the fix in the source as well.
> I did not realize there was a 1.1.0 release (the docs all point to 1.0.0).
> Well I guess posting to the wrong thread worked.
> Thank you.
>
> --
> View this message in context: http://shiro-user.582556.n2.nabble.com/Permission-checking-on-client-side-tp5450587p5539405.html
> Sent from the Shiro User mailing list archive at Nabble.com.
>

Re: Permission checking on client side ?

Posted by Mike K <mk...@semanticresearch.com>.
Thanks, just found the fix in the source as well. 
I did not realize there was a 1.1.0 release (the docs all point to 1.0.0). 
Well I guess posting to the wrong thread worked.
Thank you.

-- 
View this message in context: http://shiro-user.582556.n2.nabble.com/Permission-checking-on-client-side-tp5450587p5539405.html
Sent from the Shiro User mailing list archive at Nabble.com.

Re: Permission checking on client side ?

Posted by Kalle Korhonen <ka...@gmail.com>.
Sorry, should have read this thread before to save time from both of
you guys: https://issues.apache.org/jira/browse/SHIRO-182. Best thing
is to use 1.1.0-SNAPSHOT for now, we should be able to get the release
out after fairly quickly after becoming TLP.

Kalle


On Thu, Sep 16, 2010 at 9:25 AM, Mike K <mk...@semanticresearch.com> wrote:
>
> Les, this is starting too look like a problem with the serialization,
> although it may have been already fixed in your world.
> This seems to be the issue in SimpleSession:
> the bitMask is being set if !expired, but written if expired.
>
> private short getAlteredFieldsBitMask() {
>        int bitMask = 0;
>        bitMask = id != null ? bitMask | ID_BIT_MASK : bitMask;
>        bitMask = startTimestamp != null ? bitMask |
> START_TIMESTAMP_BIT_MASK : bitMask;
>        bitMask = stopTimestamp != null ? bitMask | STOP_TIMESTAMP_BIT_MASK
> : bitMask;
>        bitMask = lastAccessTime != null ? bitMask |
> LAST_ACCESS_TIME_BIT_MASK : bitMask;
>        bitMask = timeout != 0l ? bitMask | TIMEOUT_BIT_MASK : bitMask;
>        bitMask = !expired ? bitMask | EXPIRED_BIT_MASK : bitMask;
>        bitMask = host != null ? bitMask | HOST_BIT_MASK : bitMask;
>        bitMask = !CollectionUtils.isEmpty(attributes) ? bitMask |
> ATTRIBUTES_BIT_MASK : bitMask;
>        return (short) bitMask;
>    }
>  private void writeObject(ObjectOutputStream out) throws IOException {
>        out.defaultWriteObject();
>        short alteredFieldsBitMask = getAlteredFieldsBitMask();
>        out.writeShort(alteredFieldsBitMask);
>        if (id != null) {
>            out.writeObject(id);
>        }
>        if (startTimestamp != null) {
>            out.writeObject(startTimestamp);
>        }
>        if (stopTimestamp != null) {
>            out.writeObject(stopTimestamp);
>        }
>        if (lastAccessTime != null) {
>            out.writeObject(lastAccessTime);
>        }
>        if (timeout != 0l) {
>            out.writeLong(timeout);
>        }
>        if (expired) {
>            out.writeBoolean(expired);
>        }
>        if (host != null) {
>            out.writeUTF(host);
>        }
>        if (!CollectionUtils.isEmpty(attributes)) {
>            out.writeObject(attributes);
>        }
>    }
>
>
>
>
> --
> View this message in context: http://shiro-user.582556.n2.nabble.com/Permission-checking-on-client-side-tp5450587p5539227.html
> Sent from the Shiro User mailing list archive at Nabble.com.
>

Re: Permission checking on client side ?

Posted by Mike K <mk...@semanticresearch.com>.
Les, this is starting too look like a problem with the serialization,
although it may have been already fixed in your world.
This seems to be the issue in SimpleSession:
the bitMask is being set if !expired, but written if expired.

private short getAlteredFieldsBitMask() {
        int bitMask = 0;
        bitMask = id != null ? bitMask | ID_BIT_MASK : bitMask;
        bitMask = startTimestamp != null ? bitMask |
START_TIMESTAMP_BIT_MASK : bitMask;
        bitMask = stopTimestamp != null ? bitMask | STOP_TIMESTAMP_BIT_MASK
: bitMask;
        bitMask = lastAccessTime != null ? bitMask |
LAST_ACCESS_TIME_BIT_MASK : bitMask;
        bitMask = timeout != 0l ? bitMask | TIMEOUT_BIT_MASK : bitMask;
        bitMask = !expired ? bitMask | EXPIRED_BIT_MASK : bitMask;
        bitMask = host != null ? bitMask | HOST_BIT_MASK : bitMask;
        bitMask = !CollectionUtils.isEmpty(attributes) ? bitMask |
ATTRIBUTES_BIT_MASK : bitMask;
        return (short) bitMask;
    }
 private void writeObject(ObjectOutputStream out) throws IOException {
        out.defaultWriteObject();
        short alteredFieldsBitMask = getAlteredFieldsBitMask();
        out.writeShort(alteredFieldsBitMask);
        if (id != null) {
            out.writeObject(id);
        }
        if (startTimestamp != null) {
            out.writeObject(startTimestamp);
        }
        if (stopTimestamp != null) {
            out.writeObject(stopTimestamp);
        }
        if (lastAccessTime != null) {
            out.writeObject(lastAccessTime);
        }
        if (timeout != 0l) {
            out.writeLong(timeout);
        }
        if (expired) {
            out.writeBoolean(expired);
        }
        if (host != null) {
            out.writeUTF(host);
        }
        if (!CollectionUtils.isEmpty(attributes)) {
            out.writeObject(attributes);
        }
    }




-- 
View this message in context: http://shiro-user.582556.n2.nabble.com/Permission-checking-on-client-side-tp5450587p5539227.html
Sent from the Shiro User mailing list archive at Nabble.com.

Re: Permission checking on client side ?

Posted by Mike K <mk...@semanticresearch.com>.
Thanks Les, this is exactly what I was looking for.

On Aug 24, 2010, at 10:48 AM, Les Hazlewood-2 [via Shiro User] wrote:

> > All I am trying to do is store the Shiro session data in a server-side 
> > secret encrypted cookie.  This would be a session cookie no different in 
> > scope or replayability then the JSESSION cookie. 
> 
> Ahhh - ok, that makes things easier to understand.  Thanks for clarifying. 
> 
> I've never tried this before, but there are some things that I can think of: 
> 
> 1.  You'll need to be using Shiro's native sessions instead of the 
> servlet container's sessions - servlet containers don't support this 
> AFIK. 
> 
> 2.  Create and provide your own SessionDAO implementation to the 
> SessionManager, e.g. in shiro.ini: 
> 
> sessionDAO = com.company.my.CookieSessionDAO 
> securityManager.sessionManager.sessionDAO = $sessionDAO 
> 
> The trick with this is that the SessionDAO has no 'knowledge' of a 
> request/response pair.  You'll probably need to acquire the request 
> from a ThreadLocal somewhere so you have access to it and its cookies. 
> 
> I'd recommend subclassing the abstract CachingSessionDAO 
> implementation and implement the remaining methods for retrieving and 
> storing the Session based on cookies, using the thread-bound 
> request/response pair.  But I recommend the CachingSessionDAO not 
> because you'll use an enterprise cache - but because every time the 
> SessionManager requests a session, it hits the DAO.  This call might 
> occur anywhere from 1 or 2 times up to 30 or 40 times per request - 
> however many times the session is accessed or manipulated during a 
> request. 
> 
> This implies that your CacheManager implementation should be 
> ThreadLocal based - so every read operation acquires the thread-bound 
> Session instance instead of you having to decrypt/deserialize every 
> time read is called or encrypt/serialize every time save/update is 
> called (these calls occur frequently in a single request). 
> 
> Finally, ensure that all ThreadLocals that you bind (request, 
> response, any thread-cached Session) are all cleared from the thread 
> at the end of the request, even if there is an exception.  I'd 
> probably do this in a servlet filter that executed _before_ the 
> ShiroFilter, just in case. 
> 
> Does all of this make sense?  It is a lot to cover and the approach is 
> a little unorthodox since this use case was never designed for, but it 
> should all still work fine, and without much coding (A thread-clearing 
> ServletFilter, a ThreadLocal-based CacheManager and one SessionDAO 
> subclass). 
> 
> Les 
> 
> 
> View message @ http://shiro-user.582556.n2.nabble.com/Permission-checking-on-client-side-tp5450587p5457995.html 
> To unsubscribe from Permission checking on client side ?, click here.
> 


-- 
View this message in context: http://shiro-user.582556.n2.nabble.com/Permission-checking-on-client-side-tp5450587p5458141.html
Sent from the Shiro User mailing list archive at Nabble.com.

Re: Permission checking on client side ?

Posted by Les Hazlewood <lh...@apache.org>.
> All I am trying to do is store the Shiro session data in a server-side
> secret encrypted cookie.  This would be a session cookie no different in
> scope or replayability then the JSESSION cookie.

Ahhh - ok, that makes things easier to understand.  Thanks for clarifying.

I've never tried this before, but there are some things that I can think of:

1.  You'll need to be using Shiro's native sessions instead of the
servlet container's sessions - servlet containers don't support this
AFIK.

2.  Create and provide your own SessionDAO implementation to the
SessionManager, e.g. in shiro.ini:

sessionDAO = com.company.my.CookieSessionDAO
securityManager.sessionManager.sessionDAO = $sessionDAO

The trick with this is that the SessionDAO has no 'knowledge' of a
request/response pair.  You'll probably need to acquire the request
from a ThreadLocal somewhere so you have access to it and its cookies.

I'd recommend subclassing the abstract CachingSessionDAO
implementation and implement the remaining methods for retrieving and
storing the Session based on cookies, using the thread-bound
request/response pair.  But I recommend the CachingSessionDAO not
because you'll use an enterprise cache - but because every time the
SessionManager requests a session, it hits the DAO.  This call might
occur anywhere from 1 or 2 times up to 30 or 40 times per request -
however many times the session is accessed or manipulated during a
request.

This implies that your CacheManager implementation should be
ThreadLocal based - so every read operation acquires the thread-bound
Session instance instead of you having to decrypt/deserialize every
time read is called or encrypt/serialize every time save/update is
called (these calls occur frequently in a single request).

Finally, ensure that all ThreadLocals that you bind (request,
response, any thread-cached Session) are all cleared from the thread
at the end of the request, even if there is an exception.  I'd
probably do this in a servlet filter that executed _before_ the
ShiroFilter, just in case.

Does all of this make sense?  It is a lot to cover and the approach is
a little unorthodox since this use case was never designed for, but it
should all still work fine, and without much coding (A thread-clearing
ServletFilter, a ThreadLocal-based CacheManager and one SessionDAO
subclass).

Les

Re: Permission checking on client side ?

Posted by Mike K <mk...@semanticresearch.com>.
Thank you Les, 
I have, very carefully, looked read the Subject API document per you
suggestion. I don't disagree with your argument at all. I think we are just
thinking in different ways. 
I am not trying to do something akin to token login - trading credentials
for a token and using the token in the form of a cookie to perform logins.
All I am trying to do is store the Shiro session data in a server-side
secret encrypted cookie.  This would be a session cookie no different in
scope or replayability then the JSESSION cookie. Now, I agree that there is
some performance penalty to encrypt, decrypt this data and there are two
ways of mitigating it:
1. As you suggest use a clustered cache.
2. Keep a local session (current scenario) and replace with the crypto
session cookie if it is newer.

I prefer 2 for our implementation since it keeps configuration simpler -
which in our case is important. 

I think another issue here is that I have inadvertently hijacked this
thread. I started out about signaling state to the client, and evolved (or
devolved depending on your opinion) into the conversation about session
state management.

Still, now that, hopefully, explained my thinking, I would appreciate advice
on where would be the best place to plug in.

Thank you,

Mike.
-- 
View this message in context: http://shiro-user.582556.n2.nabble.com/Permission-checking-on-client-side-tp5450587p5457627.html
Sent from the Shiro User mailing list archive at Nabble.com.

Re: Permission checking on client side ?

Posted by Les Hazlewood <lh...@apache.org>.
Well, it is a little more of a security risk than the session id: once
a session stops or is expired, nothing can be done under that id
anymore - any replay attempts beyond that time would fail.

Another difference is that the decryption operation on the
authentication cookie would incur a somewhat undesirable performance
hit on on every request.

The final difference that I can think of is the most important one
IMO:  if you automatically log-in a user via a saved authentication
cookie, you're essentially acting on the end-user's behalf, implicitly
trusting who they are: your software has no way of knowing if the end
user has actually _proven_ their identity, for example, if a user gets
up and walks away and someone else uses their computer (or via replay
attacks).

Also see the Shiro's Subject API, particularly the isAuthenticated()
and isRemembered() JavaDoc for a better explanation of why the
distinction is important for most applications:

http://incubator.apache.org/shiro/static/current/apidocs/org/apache/shiro/subject/Subject.html

It is also important to note that Shiro can perform authorization
checks (roles/permissions, etc) for a remembered (unauthenticated
user) - its just that the isAuthenticated() check is even more strict
and should typically be used to protect things like user account
information, financial data, etc.

Cheers,

Les

On Mon, Aug 23, 2010 at 6:30 PM, Mike K <mk...@semanticresearch.com> wrote:
>
> All good points.  But isn't keeping this data on the client in an encrypted
> form just as safe as a session id? Given strong encryption, the only
> vulnerability I can see would be a replay attack, to which session is also
> vulnerable.
> --
> View this message in context: http://shiro-user.582556.n2.nabble.com/Permission-checking-on-client-side-tp5450587p5455037.html
> Sent from the Shiro User mailing list archive at Nabble.com.
>

Re: Permission checking on client side ?

Posted by Mike K <mk...@semanticresearch.com>.
All good points.  But isn't keeping this data on the client in an encrypted
form just as safe as a session id? Given strong encryption, the only
vulnerability I can see would be a replay attack, to which session is also
vulnerable.
-- 
View this message in context: http://shiro-user.582556.n2.nabble.com/Permission-checking-on-client-side-tp5450587p5455037.html
Sent from the Shiro User mailing list archive at Nabble.com.

Re: Permission checking on client side ?

Posted by Les Hazlewood <lh...@apache.org>.
Other than the session ID cookie, Shiro currently only stores
remembered principals as a cookie (i.e. the 'rememberMe' cookie) - and
by default they are serialized and encrypted.

Neither the authentication state (isAuthenticated(), etc) nor the
principals/credentials used to authenticate is stored in a cookie.
Doing so would constitute a serious security risk, providing attackers
the ability to simulate authenticated users - a very bad thing.

As such, we're left with one of two approaches: either authenticate
with every request (somewhat common in REST environments, for
example), or store the authentication state on the server somehow
(e.g. in the session).

Other than really nasty and complicated solutions involving
cryptographic nonces, I'm not aware of a way to store authentication
state in client-side cookies without opening a serious security hole.
If anyone has any ideas, I'm all ears!

As an aside:

Note that the worry about a 100% server stateless architecture is
often mitigated by relying on an enterprise clustered cache to
maintain state in production environments (e.g. Memcache, TerraCotta,
Coherence, etc).  A request can go to any machine because the state is
accessible in the enterprise cache from any application instance.
These caches are extremely fast too - global mission-critical
financial trading systems use them, so odds are very high they are
fast enough for your application as well.

In fact, this is one of the best ways to use Shiro - if you have a
cluster, and you need clustered sessions, you can turn on Shiro's
native session support and plug in a distributed Cache into Shiro's
configuration.  This is great because servlet containers all support
different ways to cluster sessions - a real pain if you need to deploy
to Tomcat or Jetty or Websphere, or any other container  With Shiro,
without changing your code or configuration, you have portable Session
clustering regardless of deployment environment.

HTH,

Les

On Mon, Aug 23, 2010 at 5:11 PM, Mike K <mk...@semanticresearch.com> wrote:
>
> Yes, I see that, but I would like to store all of the data that Shiro uses in
> a session (which not much) in a cookie, so that there is no server-side
> state reliance at all.
> --
> View this message in context: http://shiro-user.582556.n2.nabble.com/Permission-checking-on-client-side-tp5450587p5454837.html
> Sent from the Shiro User mailing list archive at Nabble.com.
>

Re: Permission checking on client side ?

Posted by Mike K <mk...@semanticresearch.com>.
Yes, I see that, but I would like to store all of the data that Shiro uses in
a session (which not much) in a cookie, so that there is no server-side
state reliance at all.
-- 
View this message in context: http://shiro-user.582556.n2.nabble.com/Permission-checking-on-client-side-tp5450587p5454837.html
Sent from the Shiro User mailing list archive at Nabble.com.

Re: Permission checking on client side ?

Posted by Les Hazlewood <lh...@apache.org>.
Shiro already uses the default JSESSIONID cookie to automatically
associate a user with a request.  As long as you use the
IniShiroFilter (or any subclass of AbstractShiroFilter, depending on
your configuration mechanism), you don't need to do anything else.

Does that help?

Les

On Mon, Aug 23, 2010 at 2:48 PM, Mike K <mk...@semanticresearch.com> wrote:
>
> Les, any thoughts on the best way to have Shiro get/store session in a
> cookie.
> --
> View this message in context: http://shiro-user.582556.n2.nabble.com/Permission-checking-on-client-side-tp5450587p5454437.html
> Sent from the Shiro User mailing list archive at Nabble.com.
>

Re: Permission checking on client side ?

Posted by Mike K <mk...@semanticresearch.com>.
Les, any thoughts on the best way to have Shiro get/store session in a
cookie.
-- 
View this message in context: http://shiro-user.582556.n2.nabble.com/Permission-checking-on-client-side-tp5450587p5454437.html
Sent from the Shiro User mailing list archive at Nabble.com.

Re: Permission checking on client side ?

Posted by Les Hazlewood <lh...@apache.org>.
There is currently no JavaScript client-side component to Shiro,
although this has been discussed on more than a few occasions (e.g. a
JavaScript mechanism, ActionScript for Flex, etc).

The 'poor man's solution' for this is to have a SecurityService
exposed to the client tier that acts as a simple passthrough to
Shiro's Subject.* calls.  As long as the session id cookie accompanies
the request, Shiro's AbstractShiroFilter implementations (e.g.
IniShiroFilter) will automatically associate the inbound request with
the corresponding Subject to ensure the SecurityService works as
expected.

This solution aside, one of my desires is to see the community
contribute client-side libraries to pair with Shiro's server-side
support - JavaScript, ActionScript, C#, etc.  Hopefully someone will
dig in to this!  In the meantime, the SecurityService 'wrapper' has
served me well enough in the past, even if it isn't the ideal.

HTH,

Les

On Mon, Aug 23, 2010 at 12:27 PM, Mike K <mk...@semanticresearch.com> wrote:
>
> I am thinking of using similar functionality to give some hints to an AJAX
> web client about the users permission state (incomplete information like
> login status and admin permissions). Current thought is to  use a cookie or
> to find/implement a cookie-based session.
> I guess what I am saying is that I am interested in this as well.
> --
> View this message in context: http://shiro-user.582556.n2.nabble.com/Permission-checking-on-client-side-tp5450587p5453883.html
> Sent from the Shiro User mailing list archive at Nabble.com.
>