Access to sessionid from RealmBase object - java

Is it possible to access to session id from RealmBase.athenticate method? I need it from my custom realm class in order to store into a database additional info associated to the session and retrieve it during the following requests. I'm using Tomcat 8. Thank you!

No.
Authentication does not require the use of a session, so it's not baked into the API. Authentication is also supposed to be separated from session management, so again it's not baked-into the API.
You might still be able to do this, but it requires some trickery.
Write a Valve that uses a ThreadLocal containing a Request object.
Register the Valve before the AuthenticationValve in the valve chain.
In that Valve, stuff the user's request into the ThreadLocal, then call down the chain.
In your custom Realm, fetch the object from the ThreadLocal.
Always remember to remove the request from the ThreadLocal after the call chain comes back... even if an exception is thrown.

Related

Restore auth using SecurityContext or Authentication instance in multi threaded environment

I have an AuthenticationServerInterceptor for grpc-java, that authenticates any request. However, the request processing itself is split into multiple threads.
For the sake of simplicity lets assume, that there are 3 parts (that are potentially executed by different threads):
Establishing the request and doing the authentication
[1..* times] Processing the parts of the request
Closing the request
What should I pass to the other places in order to allow me to restore the authenticated context in the later cases? (All three parts belong to a single request and they share a grpc-context)
The Authentication instance
The SecurityContext instance
If I pass along the Authentication instance, then I ensure that for each part of the request the original authentication is restored. However, any additional information that might be stored in the (custom) security context will be lost.
If I pass along the SecurityContext instance, then I ensure that for each part of the request the additional information and an authentication are passed along, but the developer must be careful with modifying that context.
Unfortunately I couldn't find any information about which to pass along in the docs.
I cannot just decide on either of those, because the authentication process is part of a library and it doesn't know anything about whether there might be additional details in the context and what the developer might do when processing the request parts.
Here is my current implementation, that is tested to be working+thread safe:
https://github.com/yidongnan/grpc-spring-boot-starter/blob/2ee90f16ee4295370ee47c40829805ff1a9f4f51/grpc-server-spring-boot-autoconfigure/src/main/java/net/devh/boot/grpc/server/security/interceptors/DefaultAuthenticatingServerInterceptor.java#L59
TLDR: Is spring-security's SecurityContext more thread-scoped or more request-scoped?
The problem is that the default option in Spring Security is thread Local, meaning that if your request create new threads, these new ones will be created with an empty Security context. You can set it to mode Inheritable Thread Local with the following code:
#Bean
public MethodInvokingFactoryBean methodInvokingFactoryBean() {
MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
methodInvokingFactoryBean.setTargetClass(SecurityContextHolder.class);
methodInvokingFactoryBean.setTargetMethod("setStrategyName");
methodInvokingFactoryBean.setArguments(new String[]{SecurityContextHolder.MODE_INHERITABLETHREADLOCAL});
return methodInvokingFactoryBean;
}

Apache Shiro : Filter vs Realm, which one to use?

Use case : HTTP context, I need to restrict access to urls given a certain session attribute state
Extending the is* methods of AccessControlFilter in a custom filter works, but it looks sorta ugly : I have no Realm.
AFAIK Realms are used for things like LDAP, JDBC, INI backends. Whenever my "realm" is in fact web-bound, i.e the HttpSession itself is the realm.
Is my custom filter the proper way to secure, given that I have the information I need in the HttpSession
If not, how would you bind a Realm to web based context ? Like HttpSession or even HttpServletRequest
You should use a Realm to bind you User [Subject], even if you are just passing in some object from your filter (i.e. a info pulled from the session or http header)
The Realm is the object that will Authenticate and Authorize. Generally speaking there are two types of filters: Filters that build tokens that get passed to a realm (e.g. Form auth, Basic auth, etc) and filters that require some sort of authorization (which assert one or more roles and/or permission)

How do you cache data only for the duration of the http request using apache shiro in a servlet container?

More specifically, I find that I'm implementing a custom AuthorizingRealm, which declares template methods doGetAuthenticationInfo() and doGetAuthorizationInfo() for returning AuthenticationInfo and AuthorizationInfo objects, respectively.
However, when I retrieve the data for the AuthenticationInfo (a JPA entity) in doGetAuthenticationInfo(), I find that I already have the necessary AuthorizationInfo. Alas, there's no apparantly good way to hang onto this data, so I have to throw it out only to perform another JPA lookup when the authorization filter ultimately gets its turn in the filter chain.
Behold:
public class CustomRealm extends AuthorizingRealm {
#Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
UsernamePasswordToken userPassToken = (UsernamePasswordToken) token;
String username = userPassToken.getUsername()
User user; // Contains username, password, and roles
// Perform JPA lookup by username...
return constructSimpleAuthenticationInfoFromUser(user);
}
#Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
// Look up user again? :(
...
}
}
I've considered a number of possibilities:
Use realm caching. The application will run in a distributed environment so there could be any arbitrary number of JVMs running. The default realm cache manager implementations don't solve all of the inherent problems and setting up an enterprise implementations seems out of scope for this project.
Use the subject's session. There is no server-side state and I'd like to keep it that way if possible. Perhaps you can force the session to behave like request scope, but I wouldn't know how to do so and that risks being obfuscated.
Implement my own Subject. There appears to typically be one Subject instance per request, but it's unclear how to bootstrap this and I would risk losing a lot of potential functionality.
Use the Shiro ThreadContext object. I could attach the data to the ThreadContext as a threadlocal property. Servlet containers generally follow a thread-per-request model, and the Subject instance itself seems to chill out here, awaiting its inevitable garbage collection. Shiro also appears to build up and tear down the context automatically. However, there's not much documentation on this and the source code is hard for me to follow.
Finally, the default WebSecurityManager keeps singleton instances of the CustomRealm around, one per JVM it seems. Simply setting some local instance property is not thread-safe.
This seems like a common data retrieval option and a typical deployment scenario. So, what am I missing?
Thanks!
I would go with option 4 - Using ThreadLocal object as your requirement clearly says that the object lifetime must be of http request.
Have a look at this discussion: When and how should I use a ThreadLocal variable?
ThreadLocal doc: http://docs.oracle.com/javase/6/docs/api/java/lang/ThreadLocal.html

JAX-WS Separate Instance For Separate User

Is there a way to run separate instances for each connection -or let's say user-, like rmi, via JAX-WS?
HTTP is stateless, therefore each request is on its own. The instance of the service is just one, and that's good.
If you want to store session information (i.e. separate data for each client) you have a couple of options that let you identify each subsequent request as belonging to the same user:
create your own solution - let the client pass a token that identifies his session, and load that session from an in-memory or db-persisted Map<String, ...>.
use OAuth

Intercept calls to HttpSession in Tomcat 6

What's the recommended approach to intercepting session.getAttribute() and session.setAttribute()? This is in a Spring based application so something AOP-based would be great. I'd like to avoid having to override core Tomcat classes if possible.
Update: I want to store the actual serialized attributes in a web service.
I am not familiar with AOP or Spring (or Tomcat). :) But I am familliar with Java
The way I do it is set up a filter, and replace the request variable with my own object
request = new MyRequest(request);
Then override getSession() and getSession(boolean) to return an instance of MySession
the javax.servlet.HttpServletRequest and javax.servlet.HttpSession classes are Java EE standard and not Tomcat specific.
You could implement your own session org.apache.catalina.Manager and swap it into Tomcat's configuration, although the interface looks rather lengthy - so perhaps look at extending ManagerBase or StandardManager first.
As an alternative, register a HttpSessionAttributeListener to be notified whenever a session attribute is added/removed/updated. This won't change the default storage mechanism - the session data will still be kept in-memory as well - but it would let you persist the data with an alternative mechanism as well.

Categories

Resources