Hi there,
> 1. What is the ideal way anyone here has done this (i'm sure i'm not the
> first)?
I have not done this, but yes, you would create a Realm and/or filter
as necessary to handle the Facebook Connect protocol. If you (or
someone) does this and wishes to contribute it back to the project,
please create a Jira issue!
> 2. I have some custom "login" logic to check if the user exists and create
> the user if not + some other locked status stuff. I assume this goes in the
> Realm?
You could do it there. I'd probably delegate that logic to a
component that plugs in to your Realm so you keep that logic separate
from the Realm's needs.
Then, once the user is authenticated (or authenticated and then
created), you return the identity you need in the form of a Shiro
AuthenticationInfo.
> 3. What kind of data does Shiro actually save in the Session? We're very
> keen on keeping it as lean as possible and easily serializable using Kryo or
> other performant library (these libraries usually use default constructors
> and reflection).
Very very little. Here are the session usages I can think of off the
top of my head:
1. By default it will store the PrincipalCollection (the collection of
account identities discovered during authentication) after login so
the Subject's identity is available for the remainder of the session.
2. It will use the session to store a request if the request needs to
be redirected and referenced later. For example, if an
unauthenticated user visits an authentication-required page, they
could be redirected to the login page. Before redirect, the request
will be saved in the session so that after successful login, Shiro can
auto-redirect the user back to the same page they originally
requested.
3. During 'runAs' functionality. RunAs is implemented as a stack of
PrincipalCollections that get pushed on or popped off of the stack as
runAs identities are accumulated or released, respectively. That
stack is presently stored in the Subject's session if runAs
functionality is engaged. If runAs is not used, the session is not
touched.
I think that's it. To ensure that sessions are clustered as
efficiently as possible, ensure that the PrincipalCollection returned
from your Realm during authentication is as lean as possible. Most
people store a primitive value that is a 'pointer' to the actual data
- e.g. a user id or username or similar - to ensure the session
remains lean.
> 4. We have some functionality that sends requests that don't contain the
> SessionID (from flash) so we just include the SessionID as a request
> parameter and "inject" the security context using a filter in the request
> thread. Is that possible with Shiro without doing a complete "login"
> process? It should allow Session lookup by id.
Absolutely! Shiro's session support really shines for these types of
'frameworky' issues.
You will need to replicate what the ShiroFilter does for web requests:
when encountering a session ID associated with the request, build a
Subject instance that corresponds to the referenced session and ensure
the Subject is bound to the thread for access at any time during the
thread's execution. This is trivial w/ the Shiro APIs:
SecurityManager shiroSecurityManager = //get from app-specific location
String sessionId = //get from request payload or header
Subject callingSubject = new
Subject.Builder(shiroSecurityManager).sessionId(sessionId).buildSubject();
subject.execute(new Callable() {
public Object call() throws Exception {
//continue the filter chain here
}
});
The execute call will ensure that the Subject instance is bound to the
current thread and then unbound after the method returns. This
guarantees thread 'cleanliness' in thread-pooling environments.
More information on this approach is covered in Shiro's documentation:
http://shiro.apache.org/subject.html
specifically, the "Custom Subject Instances" section.
You'll also find value in seeing how the ShiroFilter does this for web requests:
http://shiro.apache.org/static/current/xref/org/apache/shiro/web/servlet/AbstractShiroFilter.html#260
As well as Shiro's Spring Remoting-specific support (shows a remote
method invocation scenario demonstrating the same flow, but without a
web request):
http://shiro.apache.org/static/current/xref/org/apache/shiro/spring/remoting/SecureRemoteInvocationExecutor.html#78
You'll need to do something identical for the Flex-specific request.
I know people have already done this to support Shiro in the SmartFox
Server for Flash-based mmo games, but I don't know where the code is.
If you can find it, that might help as well. In any event, I'm sure
that code looks like the above two code samples, so they might get you
far enough.
HTH!
Cheers,
--
Les Hazlewood
CTO, Katasoft | http://www.katasoft.com | 888.391.5282
twitter: @lhazlewood | http://twitter.com/lhazlewood
katasoft blog: http://www.katasoft.com/blogs/lhazlewood
personal blog: http://leshazlewood.com