Session handling in a Struts application - java

I am facing an issue in handling an object in session.
I store an object in the session like this. Assume object is the name of the object. I do this in my action class:
if(object!=null)
{
session.settAttribute("objectName",object);
return mapping.findForward("success");
}
else
{
return mapping.findForward("failure");
}
I map both success and failure to the same jsp page. I check like
if(session.getAttribute("objectName")!=null)
{
object= (SomeObjectClass)session.getAttribute("objectName");
}
if(object!=null)
{
//Do this
}
else
{
//Do that
}
Now here comes my problem. There is no problem when I set the object in first time in the session. I get a problem when I call this action class from two different browsers at the same time I go to else part for one case and if part for one case. I believe this is because session is not thread safe. Is there any solution?

You mention that you're trying to see the same information between two browsers... if the information you're trying to share is "global" (i.e. it should be the same for ALL users of the application, you should store the information in the application scope, not the session scope. (see http://java.sun.com/developer/onlineTraining/JSPIntro/contents.html#JSPIntro5 for explanation of scopes). For example:
ServletContext servletContext = getServlet().getServletContext(); //"application scope"
SomeObjectClass object = (SomeObjectClass) servletContext.getAttribute("objectName");
if(object !=null){
//Do this
} else {
//Do that
}
If you have accounts and a login mechanism and you're wanting the same login to see the same information in two different browsers, then you have a different issue. In that case the information will need to be stored in a "database" (not necessarily a rdbms, could be the application scope!, depending on your needs for persistence) and the information would need to be retrieved in the action class using the user information that could be stored in the session, cookie, etc.
//get the user info from the session, cookies, whatever
UserInfoObject userInfo = getUserInfo(request);
//get the object from the data store using the user info
SomeObjectClass object = getObjectForUser(userinfo);
if(object !=null){
//Do this
} else {
//Do that
}

When you access action/page from different browser you create a new session. In modern browsers you can share session between tabs or views. The only way to share session with more browsers is to use jSessionid param in URLs.

Related

Is there a way to enable #Filter globally while taking logged in User ID as a parameter?

I'm new to #Filter and I have understood that it takes in parameters when compared to #Where.
I have a use case where I need to filter the results for every end point based on the logged in User.
While searching for how to enable filtering globally, I came across a solution where AOP is used to intercept Session creation and to enable the filter which seems to be working fine.
The problem here is that I need to have the User ID sent in as the parameter while enabling the filter. How do I do it or is there any other alternative for this particular scenario?
#Aspect
#Component
public class EnableFilterAspect {
#AfterReturning(pointcut = "bean(entityManagerFactory) && execution(* createEntityManager(..))",
returning = "retVal")
public void getSessionAfter(JoinPoint joinPoint, Object retVal) {
if (retVal != null && EntityManager.class.isInstance(retVal)) {
Session session = ((EntityManager) retVal).unwrap(Session.class);
session.enableFilter("authorize").setParameter("userId", **USER_ID**);
}
}
}
You will have to store the user id in a thread local variable and use that in the aspect. Not sure what the filter does, but maybe multi-tenancy is more in line with what you want to achieve. The solution doesn't change much though, you will have to somehow publish the user id through a thread local variable.

Vaadin UI - cannot use static fields for every client

I'm creating a web app.
I have a MyUI that extends UI.
public class MyUI extends UI {
public static Authentication AUTH;
#Override
protected void init(VaadinRequest vaadinRequest) {
AUTH = new Authentication();
updateContent();
}
//other methods
}
In Authentication() I have the user logged. When I do the logout, that user is set to null.
I noticed that when I access to the server from two device, so when I should have two connection to the server, when someone do the logout, the other one is logged out too.
In Authentication class there is this method:
public void doLogout() {
System.out.println("User: " + this.user.getMail() + " has logged out.");
this.user = null;
}
I get error in user.getMail() because the user is already set to null, when I try to do the logout from the other account.
Is com.vaadin.ui.UI unique? How can I handle different connections in Vaadin?
Java, in general
Basic Java here, nothing to do with Vaadin…
The keyword static means one value per class, otherwise known as a “class variable”, more generally known as a “global variable”. Not object-oriented. Generally speaking, you should minimize your use of static.
Omitting that keyword means “one value per instance of this class”, an instance variable also known as member variables. This is object-oriented.
I suggest you learn more of the basics of Java before embarking on a Vaadin project. And learn the basics of how Java Servlet technology works, perhaps reading the Head First book on Servlet published by O’Reilly (now outdated, but basics are the same). You also need to learn about advanced topics such as threading and concurrency issues as a Servlet environment such as Vaadin is inherently multi-threaded. Eventually, read the book Java Concurrency In Practice by Goetz.
Vaadin specifically
To store values per user of a Vaadin app, use session attributes. This is a key-value store where you insert and retrieve a value by specifying a key, the name of the "attribute". The session is automatically instantiated for you when the user first connects, as part of the Java Servlet technology.
Alternatively, you can store values per user on that UI class as instance variables. Each Vaadin user starts with a UI instance when first connecting. But beware: you can open multiple web browser tabs/windows in a Vaadin 8 app, each having their own UI instance. So to share data between those multiple UI objects, use the session attributes.
Note that while every Vaadin app has at least one UI subclass defined, you can define additional UI subclasses as well, for those additional browser tabs/windows mentioned above to show different content.
Maybe instead of static variable you should use here session attribute (updated to be more generic):
UI.getCurrent().getSession().setAttribute("AUTH", AUTH);
Authentication auth2 = UI.getCurrent().getSession().getAttribute("AUTH");
So use VaadinSession to store session specific data.

Making a variable accessible in all Play 2.0 project views

It is sometimes desirable to share context variables with all views, such as the current user or navigational state. Looking through the documentation, I haven't been able to find a way to share such global context variables accessible to the template engine in all views.
Is this provided by the framework, or am I better off explicitly passing these variables to all views, perhaps by writing a wrapper method called in all controllers whose views need these global variables?
You can use for that Session and Flash scopes
public static Result index() {
// session is good for storing session data such as for an example logged user's info
session("username", "John Doe");
// flash is available only for next request (in this case for view rendering process)
flash("navId", "mainPage");
return ok(index.render("ellou' World"));
}
index.scala.html
#(message: String)
#main(message) {
#if(flash.get("navId")=="mainPage"){<h1>Great! You're on main page again</h1>}
<div>You're logged as #session.get("username")</div>
}
of course for data which are individual for each page (like sample navId) you can also pass it to the view, where you can declare required type other than String.

Java Play! 2 - Authentication does not make sense

This is a follow up from Java Play! 2 - User management with cookies
from the zentask example
public class Secured extends Security.Authenticator {
#Override
public String getUsername(Context ctx) {
return ctx.session().get("email");
}
#Override
public Result onUnauthorized(Context ctx) {
return redirect(routes.Application.login());
}
// Access rights
public static boolean isMemberOf(Long project) {
return Project.isMember(
project,
Context.current().request().username()
);
}
public static boolean isOwnerOf(Long task) {
return Task.isOwner(
task,
Context.current().request().username()
);
}
}
For me this doesn't really makes sense.
User gets the following cookie. for example "email=test#test.com"
If I go to a "secured" page , zentask only checks if email is not null. How can this be secure?
The reason of sessions are to get load off the db. But with this approach he has to constantly check if the user has the rights to on a secured page.
For me it doesn't really makes sense. Why is there a function getUsername? And why is the return type a string?
I want to do somthing like this:
User logs in and gets a cookie which looks somthing like this "value=randomString"
Safe the user OBJECT in the cache for example Cache.set(randomstring,userObject);
Now if the visitor comes back I check if his randomstring is in my cache, if yes check if the User object in the cash has the rights to be on the secured page.
I was able to achieve this, just without the #Security.Authenticated() annotation.
Is it possible to achieve this with this annotation?
It is just a sample, nothing else. You don't need to store a email in the cookie. You can for an example save some hash to identify logged user, or do some other matching.
Samples are as simple as possible, changing it to more sophisticated scenarios lays on the developers side.
BTW of course all Play's cookies are signed and I really doubt if you'll be able to manually change it.

Play framework 2 - isAuthenticated in Java

In my action i'd like to render different views (or maybe only display some other divs) depending on whether a user is authenticated or not.
Should i do something like this:
public static Result index() {
if (Context.current().request().username().equals("")) {
// user is NOT authenticated
return ok(welcome.render());
} else {
// user is authenticated
return ok(dashboard.render());
}
}
And how about checking if a user is authenticated in a view?
I know I can use the #Security.Authenticated(Secured.class) annotation, but how do things conditional?
Depends on what you're trying to achieve. If you only need to decide whether a user is logged in or not, you can use something like you wrote, in your controller classes, eg:
public static boolean loggedIn() {
return (session().get("userId") != null);
}
then in the static controller methods check whether the user is logged in:
if (!loggedIn()) {
return redirect(routes.Application.login());
}
Notice the use of the session() by which you can access the secure session cookie's map, and from there you can get the user id. If you want to implement more complex logic, eg. different actions for different user groups, then it's a different story.
Either use some maps in a cache with the authenticated user id-s and you validate the userId in the session, whether it's in the map, or alternatively you can use some property of the user (eg. a set of userRoles) and set what is visible accordingly. These are the most sensible ways I'm aware of.
(here's how you can use the session() of controller:
Controller,Session)

Categories

Resources