Hi
I am currently playing with Guice and @SessionScoped. To give it more sense, I decided to build a (very simple) authentication process.
Below, I will explain each step I have done. Then I will ask you some questions.
[1] I have create an Identity class which represents a person (guest or user) :
@SessionScoped
public class Identity implements Serializable
{
private String uid;
private String name;
public boolean isAuthenticate()
{
return uid != null;
}
public void logout()
{
this.uid = null;
}
/*Setters-Getters*/
}
[2] Next, I created an Authentication class that log-in user:
public class Authentication
{
@Override
public Identity authenticate(String login, String password)
{
/*some code*/
Identity identity = new Identity();
identity.setUid(user.getId());
return identity;
}
}
[3] Then, in my Servlet, I log-in the user :
@RequestScoped
public class LoginAction
{
@Inject
Injector injector;
protected void login(HttpServletRequest req, HttpServletResponse resp)
{
Identity identity = injector.getInstance(Identity.class);
Authentication auth = new Authentication();
identity = auth.authenticate("login","password");
}
}
[4] Finally, I create a Filter that show me if user is authenticated :
@Singleton
public class SecurityFilter implements Filter
{
@Inject
private Injector injector;
@Override
public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain)
{
Identity identity = injector.getInstance(Identity.class);
if(identity.isAuthenticate())
{
System.err.println("USER");
}
else
{
System.err.println("GUEST");
}
chain.doFilter(request, response);
}
}
Well, this code is not working. My Identity's uid is always "null".
Let's go for questions :
a - First of all, Why did my code not works ?
b - Is @SessionScoped equivalent to set the object in HttpSession ?
c - How to invalidate the Identity object (only it) in (http)session ?
d - Generally, In which case did we have to use @SessionScoped?
Thanks you for reading,
Waiting your answers.
[a] You're assigning a new instance of Identity
to a local variable in LoginAction
, not replacing the instance managed by Guice. You could solve the problem by populating the uid
and name
fields on the existing Identity
instance managed by Guice.
For example, instead of
identity = auth.authenticate("login","password");
you could say:
Identity identity = injector.getInstance(Identity.class);
Authentication auth = new Authentication();
Identity authenticated = auth.authenticate("login","password");
identity.setUid(authenticated.getUid());
identity.setName(authenticated.getName());
There are cleaner ways to do it, but you get the idea.
[b]/[d] That's correct: @SessionScoped
is equivalent to setting a variable in the HttpSession
, and this is the kind of situation that you would use it. You'll need it for objects that need to be unique across sessions, but need to be available for every request.
[c] I'm not quite sure what you mean, but if you're wanting to redirect to different places in the app depending on whether the user is logged in, your filter design is a common way to do that.
Some improvements that you could make:
SessionScoped
service that manages the session's user's Identity
, and make sure it's synchronized on the Identity
instance. That way you won't have concurrency troubles if a user makes two requests in quick succession.Provider
s instead of injecting the Injector
(examples here) to decouple your classes from Guice.