Difference between session handling locally and on server with Google App Engine - java

I am using sessions and have enabled sessions in my GAE app
<sessions-enabled>true</sessions-enabled>
<async-session-persistence enabled="true" />
I am using sessions for the purpose of a simple user login. Locally, this works just fine, my session is maintained until I logout and all my pages that are "protected" are viewable with a valid session.
The problem with my live/production server on appspot is that it doesn't work at all. When I login and authenticate, I redirect to another page. This page checks if I have a valid session (using standard HttpSession) and somehow this fails and then redirects me back to the login screen.
Does anyone have any idea why it doesn't work in the GAE production environment but works just fine locally?
Here is the code I use to check validity of current session:
public static boolean isValidSession(HttpServletRequest request) {
return (request.isRequestedSessionIdValid());
}
Update:
I'm creating session ID like this:
public static void createNewSession(HttpServletRequest request, final String username) {
HttpSession session = request.getSession(true);
session.setAttribute("username", username);
}

There is no difference between handling sessions locally and in production as such on Google App Engine. They work the same in both the environment. The only difference that I can think of is that when you create sessions (say at or after Login) locally and you set some attribute in the session say the access level of the user, it will not change even when attribute's value change(say if it is pulled dynamically from some database where it got changed after Login) until you close the tab and Login again, however in production if the attribute changes in the database and then if you refresh the page it will take the new value from the database. Well that's in my experience. Hope it helps.

Related

Disabling Cookies stops Session as well?

I have been building a Web Application, So far I have implemented Login & Registration. User can register and then can login within the web application. Everything is working fine. What I am doing is When user clicks on Login button, a servlet is being invoked where I'm checking if the credentials are correct, If validated then Saving isLoggedIn in HttpSession and redirecting it to Home Page.
LoginServlet.java
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
boolean isValidated = false;
... // Service Layer is invoked here and checks for user validation
// Assume isValidated to be true
if(isValidated){
HttpSession session = request.getSession();
session.setAttribute("isLoggedIn", Boolean.valueOf(true));
...
// redirected to /home
}else{
// redirected to /login?invalid
}
}
HomeController.java
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
HttpSession session = request.getSession();
Boolean isLoggedIn = (Boolean) session.getAttribute("isLoggedIn");
if(isLoggedIn != null && isLoggedIn){
...
// Service Layer is invoked to fetch `Home Page Data`
}else{
// redirected to /login?expired
}
}
All of a sudden I have encountered a strange problem, If i disable cookies for localhost using FireBug I am not able to login anymore. No matter if I enter correct username or password each time I am being redirected to /login?expired.
I don't get it, Cookies are ment to be stored at client side and Session are stored at Server side, then Why session attribute can not be set if Cookies are disabled.
I have tried disabling Cookies for already built Web Application in Spring-MVC which is in production and having same issue there as well.
When cookies are enabled, the session is stored in a cookie under the name JSESSIONID.
If cookies are disabled, the container should rewrite the session id as a GET parameter (i.e. &JSESSIONID=1223456fds at the end of all URLs).
If the URL rewriting isn't on by default, see your container's documentation on how to enable it.
You might want to consider modern frameworks (for example Spring MVC with Thymeleaf) which will automate this for you. Otherwise you need to make sure you're rewriting URLs with response.encodeURL() as Ouney directs in his answer.
A session is to maintain a stateful conversation between server and client.
By default Http is a stateless protocol.
So, to make it a stateful conversation we need to store some values on browser side (cookies) which are sent by the browser to the server with the request.
Without cookies every request is a new request and it becomes a stateless conversation.
That is the reason people use add session information in url's (jsessionId) when cookies are disabled.
To use URL rewriting use response.encodeURL() on your URLs.
with every request and response session id stored on client side as a Cookie is checked by server, if it is present the server update the information and if not a new session is created. so when you disable cookie in you browser, with every request a new session is created as cookie is disabled.
for further information you can refer this link.
click here
When we manage the session using the HttpSession mechanism that time a jsessionid save in the browser's cookies. So when you delete a cookies from the browser or disable cookies that time that jsessionid information is not sent to the server and that time server treat this request from a new session.

how to log a user out programmatically using spring security

i am using spring security v3.1.4. what i want to achieve is to have an admin be able to log out a regular user (invalidate his session). a user can only log in once at any given time, but if he forgets to log out, then when he attempts to log in from another location, he won't be able to log in. so he'll put in a ticket to the admin, and the admin will invalidate all his previously logged in sessions (hopefully there's just one).
in my web.xml i have the following defined.
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
in my spring security xml i have the following defined.
<session-management invalid-session-url="/home">
<concurrency-control max-sessions="1" error-if-maximum-exceeded="true" session-registry-ref="sessionRegistry"/>
</session-management>
<beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl"/>
i then have a rest-like controller to perform the logging out.
#Controller
#RequestMapping("/api/admin")
public class RestAdminController {
static final Set<SimpleGrantedAuthority> AUTHS = new HashSet<>();
static {
AUTHS.add(new SimpleGrantedAuthority("ROLE_USER"));
}
#Autowired
private SessionRegistry sessionRegistry;
#RequestMapping("/user/logout");
public #ResponseBody String logout(#RequestBody Account account) {
User user = new User(account.getUsername(), "", AUTHS);
List<SessionInformation> infos = sessionRegistry.getAllSessions(u, false);
for(SessionInformation info : infos) {
info.expireNow(); //expire the session
sessionRegistry.removeSessionInformation(info.getSessionId()); //remove session
}
return "ok";
}
}
this code "kinda" works when i test it from the same computer. let's say we have a user, USER_A, and an administrator, ADMIN_A.
USER_A uses chrome to log into the APP.
USER_A uses firefox to log into the APP. he is denied because a user can only have 1 login session at a time.
ADMIN_A goes in, and calls the rest-like service (code above) to "kick" out all of USER_A's session.
USER_A can now use firefox to log into the APP.
however, USER_A is now logged in twice, once in chrome and once in firefox.
refreshing the (spring security protected) pages for USER_A in chrome (first log in) doesn't force him to be redirected (to the login page).
refreshing the protected pages for USER_A in firefox (second login) also doesn't force him to be redirected.
any idea on approaches on how to completely invalidate/destroy USER_A's first/previous login sessions such that if he tries to access protected pages spring security will know, "hey this guy's session is invalid or expired, send him to the login page" ?
any help is appreciated. thanks.
It looks like you've almost got it, but I think the problem is that you are removing the information prematurely from the SessionRegistry. The ConcurrentSessionFilter performs a check on the current session when a user makes a request, and at this point, it logs out an expired session and invalidates it. Since you have already removed the information for that session, it won't find it and will do nothing.
Try removing the line:
sessionRegistry.removeSessionInformation(info.getSessionId());
All you need is modify equals() and hashCode(). Your code will run later on. This could be helpful: http://blog.trifork.com/2014/02/28/session-timeout-and-concurrent-session-control-with-spring-security-and-spring-mvc/

How to retrieve user name from CAS in Apache Wicket

I am working on a research project for a university, and I must build a portal-like web application where they see analysis information about their academic performances.
My web application is built using the Apache Wicket framework.
I need to use the university's CAS authentication server and use its login page to validate the user credentials. However, I also want to retrieve the name the user entered as username, as I need it for storage in session variables and use for the duration of the session.
I saw that CAS has a client for Apache Wicket, but I can't see how I can retrieve the username.
Any help would be appreciated,
Jeremie
Looking at the code for the client here https://wiki.jasig.org/display/CASC/Apache+Wicket+CAS+Client it looks like the getUser() method in CasAuthenticatedWebPage may be what you want.
/**
* #return the authenticated principal name
*/
public String getUser() {
Session session = getSession();
Serializable value = session.getAttribute(SSO_USER_NAME);
return value + BLANK_STRING;
}

Allow only one session per user

We have a web-application developed using struts2, spring & hibernate.
The application needs a functionality that one user can login from only one browser.
Say if user x, is logged in on pc-1 browser ff, then he cannot be logged in from any other place.
I tried it by implemention session map and store the sessions in global map, but this fails when user logs off and tries to login again.
Even it fails critically if the user does not logs off and session time-outs, but the map is not cleared.
Any better idea to implement this functionality.
We do not want to obstruct the user to login but do not want users to exploit the application by allowing him to share the creditionals and allow multiple users with same login to happen.
Since you are already using Spring, I would recommend you to integrate your application with Spring Security.
Spring security lets you define maximum sessions allowed per user concurrently.
<session-management>
<concurrency-control max-sessions="1" />
</session-management>
If set when user having valid session tries to login again it will inform user that maximum concurrent access is set to 1.
Read more at the reference documentation of Spring Security: v3.2.x, v4.2.x or v5.1.x.
If spring security is not an option for you then:
Use a SessionInterceptor which will check for session validity, if session is valid it will check if user is already logged in to the application (for this you will have to maintain session somewhere for eg database for every successful login), if valid login is found, redirect user again to login page with custom message, or logout already valid session and then redirect him to login again. If you logout earlier session it would mean any successive action in that browser session will have to deal with invalid session.
If case you are also using Servlet in your application then Interceptor wont work for you, in this case you should use a Filter and follow the same steps as detailed above for Interceptor.
The best solution is to log-off user from other session when he logs in in new session. It is often that user would not logoff when closing browser and restricting him from logging in other window would be the pitfall.
Automaticly closing any previous user sessions is good, because in normal usage, it is no problem, but when sharing login and password, no two persons can work simultanously with your application.
At the login give the user a generated ID/cookie (sessionid suffices) stored with the user data. If a user does a request to the server with an old ID/cookie, say that he logged in elsewhere.
The other way round, forbidding the new login attempt, has its drawbacks - as you've experienced.
Create a map.
At the time of logging check that user id is present into that map or not.
If its not exist then put user id into map, at the time of logout remove that user id.
To be honest I would revisit the reasons why you have to restrict a user to a single login. Whilst preventing them from logging in from two different browsers is easy enough - any of the suggestions provided would work - with the Spring Security option being the easiest to implement if you can - they all break down when your user opens a second tab in the same browser. That is considered to be part of the same session.
Maintain user stack in servlet context,as it will be one for web container.perform a check before user getting logged in, if user name found in servlet context redirect him to login page.
All you should do is add a field in database userprofile table saying: alreadyLogin.
If user logins, make it Y. If user logs out, make it N. Now every time when user tries to login from new location, check this value and prevent login if Value is Y.
As many said, you can have a Map<String, User> (static Map or better an attribute in ServletContext) of (sessionId, user) of active users.
When a user tries to login, first check the existence in theMap.values(), and if it is okay add it to theMap.
Instead of removing from theMap on logout, implement a javax.servlet.http.HttpSessionListener, and on sessionDestroyed method, remove the item from it (the parameter of the method gives you the sessionId). This way if a user closes the browser, after session timeout period, it will be removed automatically.
On logout, invalidate the session, so it will be destroyed, and again this listener get executed.
Don't forget adding the listener to your web.xml.

Can't get the session in java servlet

I am using servlets for the first time but I made a lot of progress. My servlets are working well. So I decided to put an authentication mechanism, which creates a session, if users give the right password and id's. But sessions are totally new for me. So I don't quite follow the logic but I have started to understand.
As I mentioned before one of my servlets is dedicated for logging in. If password is correct a session is created (I don't store any object/data in sessions) and client (remoteUser) is notified that the password is accepted and session is created. What client does is to reach any other servlet in the same application. Other servlets get the session to check if it is created and valid (not timed out). For that purpose in those other servlets I get the session with:
HttpSession session = req.getSession(false); //false because this is not the place to create a session. sessions should only be created in the login servlet.
But this returns a null. So I have tried:
HttpSession session = req.getSession();
And checked with session.isNew(); and I it was a new session. So the session I have created in login servlet can't be called with req.getSession(); in another servlet.
PS: When session is created in login servlet: session.setMaxInactiveInterval(300); //5 minutes
Thanks a lot for any response!
When using Google App Engine, you have to specifically enable session support. See http://code.google.com/appengine/docs/java/config/appconfig.html#Enabling_Sessions.

Categories

Resources