I am a newbie in Spring, so I am explaining my requirement.
My requirement is to create an web - application in spring, where sign in / log in should be from 1 system. If user gets logged in , in another browser/system the previous should be out of session.
How can I achieve this ? Any document link or any concept that I need to learn will be helpful.
You can use spring-session-redis - it's an API with implementation for managing a user’s session information with Redis.
Application uses command line to execute GET request on same server running on different ports, to explain how the session works. You can build POST, DELETE and other HTTP request.
HttpServletRequest and HttpServletResponse interfaces are implemented by the web-container wrapping your application.
If you are using Spring boot it uses embedded Tomcat instance, if you are deploying your WAR application on Weblogic, they are implemented by Weblogic.
However, the interfaces are the same and depending on your configuration on those containers, they maintain Session objects.
Using this session object, you can add key-value pairs and maintain same set coming from the same user in consequent requests.
#RequestMapping(value = "/hello")
public Object hello(HttpServletRequest request, HttpServletResponse response){request.getSession().setAttribute("key",mySessionObject);}
when you want to retrieve the session object you have just added, just use getAttribute() method with same key.
request.getSession().getAttribute("key")
Related
I'm developing application in Spring Boot and I need jwt authentication there. I decide to use that github project, but when I'm looking at code I don't understand sense of SecurityContextHolder.
Here are 2 classes which are using it:
AuthenticationRestController.java
JwtAuthenticationTokenFilter.java
Can you tell me what is purpose of SecurityContextHolder? I want stateless authentication without session. So I just need generate jwt and next check it before requests.
This git project also has disable session:
...
httpSeccurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
...
I've tried delete code with SecurityContextHolder and applicatin still works fine.
Thanks for answers.
Here is a quote from Learning Spring 5.0:
One major aspect of security is storing the information of the principal currently used by the application. It is held by the security context of the application. SecurityContextHolder is the most important object of the framework as it stores the details about security context in ThreadLocal. It means the security context will be available to the methods that are executed in the same thread. However, in a few circumstances, all the threads in the application may need to use other strategies for using the security context. The framework provides two ways to change the default nature of using ThreadLocal. The developers can either set the system property or they can invoke the static method on SecurityContextHolder.
The reason your application still works after deleting code with SecurityContextHolder is that by using the SessionCreationPolicy.STATELESS creation policy you request Spring Security to not create an HTTP session and not store logged in user’s SecurityContext in the session.
When to use SessionCreationPolicy.STATELESS
to stop creating sessions during the entire lifespan of the application
to stop using sessions during the entire lifespan of the application
While experiencing weird behavior in a web application, I've found that its sessions was being invalidated and recreated everytime HttpSession session = request.getSession(); was being executed. It was occouring specially while application calls a Spring controller built in another servlet.
As shown in the HttpSession javadoc, sessions are ServletContext. So, I ask: Spring controllers are implemented in different servlet scopes? Or just when a controller is implemented in a different servlet? Can we set Spring to maintain a single scope? Thanks!
Edit:
Adding information: I have a tip that the issue is due to I'm importing header and footer into the page. It's 90% certain that are those elements which are being processed in a different session by Spring, but I don't know how to correct this behaviour (yet).
session, request and response objects are not created by spring. Only the Controllers are created by spring and they are singletons by default (spring application context singletons, not JVM singletons).
So I would guess that your problem of session invalidation is happening outside of spring.
We have a task to certify our application in Tomcat7 which is already certified and running in Websphere.
Our application in websphere has JAAS custom login module and it access HttpServletRequest object via callback handlers as shown below and we set user related information in the session object (which is retrieved from request).
javax.security.auth.callback.Callback callbacks[] = new javax.security.auth.callback.Callback[3];
callbacks[0] = new javax.security.auth.callback.NameCallback(
"Username: ");
callbacks[1] = new javax.security.auth.callback.PasswordCallback(
"Password: ", false);
callbacks[2] = new com.ibm.wsspi.security.auth.callback.WSServletRequestCallback(
"HttpServletRequest: ");
The problem here is that, as you see, the above code is specific to websphere. So, we want to write another custom login module specific to Tomcat. Excuse me, this is designed by someone else.
Now the queustion is how can I access HttpServletRequest/HttpSession object in Jaas login module in Tomcat?
Note: I have tried to use ThreadLocal to pass the user information instead HttpServeletRequest but it appears that it is not advised since threads are reused from Thread Pool in Tomcat and there could be a potential problems (memory leak, user information shared etc) in case if we don't clear the ThreadLocal properly.
In Jboss, it can be get through:
HttpServletRequest request = (HttpServletRequest) PolicyContext
.getContext("javax.servlet.http.HttpServletRequest");
But PolicyContext is in JACC and Tomcat does not support JACC yet. It might be supported in Tomcat 9, but low on Tomcat's priority.
You should not have to obtain the HttpServletRequest in the LoginModule. The LoginModule is the JAAS version of an identity store, which is a database/repository for users, their credentials and optionally groups or roles.
In Tomcat a LoginModule is not the prime identity store type. A Realm is, but Tomcat provides a bridge so you can use a LoginModule anyway. But as you have discovered the usage of JAAS in Java EE is not standard. Servers either don't use JAAS at all, or they use it differently from any other server.
What you're looking for is the authentication mechanism, which is the thing responsible for interacting with the request, response and session. Tomcat has two interfaces for that, one is Tomcat specific, the other is a Java EE standard.
The Authenticator see https://tomcat.apache.org/tomcat-9.0-doc/api/org/apache/catalina/authenticator/package-summary.html
The ServerAuthModule see https://tomcat.apache.org/tomcat-9.0-doc/config/jaspic.html and http://docs.oracle.com/javaee/7/api/javax/security/auth/message/module/ServerAuthModule.html
I'm creating a restful web service using Resteasy. One thing I need to do is to secure the service using a standard HTTP auth request. The tricky part is that the service is multi-tenant and needs to use one of the path parameters to determine the security realm.
There are a lot of articles typical of this link which describe setting up a single-tenant service. What I can't find is what to configure, and what interfaces to implement to describe my own security which is based on a path parameter + the username in the HTTP authentication method.
I envision that prior to calling any of the application logic, tomcat/resteasy would call a SecurityProvider (or whatever) interface with the HttpServletRequest and have me either throw a 401 or return a SecurityContext that gets passed to the JAX-RS handlers. In that routine, I would inspect the path parameters, and make a determination based on parameter+username+password given in the Basic/Digest/Form.
Is there any such beast?
I thought I'd update this since there's bee little activity on this question.
It looks like there's no baked in feature to do what I envisioned, so instead I extended the RestEasy servlet and added the security checks in my override before passing control back to the stock RestEasy servlet.
Seems to work well.
I have a webapp on one Glassfish server (front-end) and an EJB 3.1 app (back-end) on another Glassfish server. The webapp communicates with the EJB 3.1 via remote invocation.
I would like to pass context data (user data i.e.) without having to define it as an input parameter of each business operation.
I have one idea, but not sure it will work: use a ThreadLocal to store data, but the ThreadLocal will only be available on one server (meaning JVM) => use the InvocationContext object and create interceptor to add user data to the ContextData Map.
What do you think about it? Any other ideas are more than welcome! ;-)
UPDATE
After first answer, I googled it a little bit and found the annotation #CallerPrincipal.
How can I set this object before the remote invocation?
The container will already handle this so you don't have to code it yourself.
In your EJB, you can access the EJBContext, which has a getCallerPrincipal() method which will give you the callers identity.