Consider these static methods outside of any servlet. All of them retrieve a hibernate session from a servlet filter.
public static User findUser(HttpServletRequest request) {
Session session = (Session)request.getAttribute("session"); // org.hibernate.Session
User user = (User)session.createQuery("from User u where u.email like :email and u.password like :password").setParameter("email", request.getParameter("email")).setParameter("password", hash(request.getParameter("password"))).uniqueResult();
return user;
}
public static User userExist(HttpServletRequest request) {
Session session = (Session)request.getAttribute("session"); // org.hibernate.Session
User user = (User)session.createQuery("from User u where u.email like :email").setParameter("email", request.getParameter("email")).uniqueResult();
return user;
}
public static User loadUser(HttpServletRequest request) {
Session session = (Session)request.getAttribute("session"); // org.hibernate.Session
User user = session.load(User.class, (long)request.getSession().getAttribute("userid"));
return user;
}
public static boolean existReservations(HttpServletRequest request, boolean checkCurrent) {
Date checkInDate = getDate(request.getParameter("checkInDate"));
Date checkOutDate = getDate(request.getParameter("checkOutDate"));
List<Reservation> res = loadUser(request).getReservations();
for (Reservation r : res) {
if (checkInDate.compareTo(r.getCheckOutDate()) <= 0 && checkOutDate.compareTo(r.getCheckInDate()) >= 0) {
if (checkCurrent && r.getReservationID() != Long.parseLong(request.getParameter("id"))) {
continue;
}
return true;
}
}
return false;
}
I will have to call these methods lots of times so they are in a Utils class. Now, I am absolutely sure that I will always call them if:
I'm in a servlet.
A hibernate session is open
A HTTPSession and a "userid" attribute is available.
In case of reservation methods, a parameter "id" is available
Now I found that doing this made my servlet code shorter. I personally think there are no problems doing this, I'm not modifying any attributes or parameters in HTTPServletRequest. I've seen many question asking if this is possible. But is this bad practice or I'm doing just fine? Are there cases where doing this approach make bad things happen?
Related
I have configured the server.xml file in a Java Spring application to authenticate users when logging in from database tables and roles. I'm wondering how in Java code can I check who's logged in to the application?
I know that in a jsp file I can just use this following syntax to show the name:
${pageContext.request.userPrincipal.name} .
In your Spring MVC Controller, just add the following statement:
String loggedUser = request.getUserPrincipal().getName();
where request is the object of HttpRequest type, made available to you by Spring on demand.
There is very beautiful article for this is given at http://www.baeldung.com/spring-security-track-logged-in-users
You can leverage the HttpSessionBindingListener to update the list of logged in users whenever user information is added to the session or removed from the session based on user logs into the system or logs out from the system.
It will listen to events of type HttpSessionBindingEvent, which are triggered whenever a value is set or removed, or, in other words, bound or unbound, to the HTTP session.
#Component
public class LoggedUser implements HttpSessionBindingListener {
private String username;
private ActiveUserStore activeUserStore;
public LoggedUser(String username, ActiveUserStore activeUserStore) {
this.username = username;
this.activeUserStore = activeUserStore;
}
public LoggedUser() {}
#Override
public void valueBound(HttpSessionBindingEvent event) {
List<String> users = activeUserStore.getUsers();
LoggedUser user = (LoggedUser) event.getValue();
if (!users.contains(user.getUsername())) {
users.add(user.getUsername());
}
}
#Override
public void valueUnbound(HttpSessionBindingEvent event) {
List<String> users = activeUserStore.getUsers();
LoggedUser user = (LoggedUser) event.getValue();
if (users.contains(user.getUsername())) {
users.remove(user.getUsername());
}
}
// standard getter and setter
}
You can go through the whole code here
You can also retrieve the current logged in user from Spring security
Go through this artical
Or through Request also
request.getUserPrincipal().getName();
You can write a method to get current logged in user as you might need this various places like below :
public User getCurrentLoggedInUser() {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
if (auth != null) {
Object principal = auth.getPrincipal();
if (principal instanceof User) {
return ((User) principal);
}
}
}
I need to get list of all the active Session so that I can manage them. Basically I need to manage all the logged in Users in application.
Using HttpServletRequest req I am able to get current session but
need to get all the sessions
Something like this:
public EmployeeTO getEmployeeById(int id, HttpServletRequest req) {
EmployeeTO employeeTO = null;
try{
HttpSession session = req.getSession();
HttpSessionContext httpSessionContext = session.getSessionContext();
}catch(Exception e){
e.printStackTrace();
}
return employeeTO;
}
Am using RESTFul implementation with JASS for Login
I have a screen which shows the list of all active Users. If I check one
User and click close session. I need to terminate that users session.
To do that I need to have sessions somewhere accessible.
Using the HttpServletRequest, you will be able to get only the current request's (user's) session object. But if you want to track all session objects, you can do that by implementing HttpSessionListener as shown below:
public class MyProjectSessionListenerAndInvalidator
implements HttpSessionListener {
private static Map<String,Session> sessions = new HashMap<>();
#Override
public void sessionCreated(HttpSessionEvent event) {
//add your code here,
//this will be invoked whenever there is a new session object created
//Get the newly created session
Session session = event.getSession();
//get userId or unique field from session
sessions.put(userId, session);
}
#Override
public void sessionDestroyed(HttpSessionEvent event) {
//add your code here
//this will be invoked whenever there is a new session object removed
//Get the removed session
Session session = event.getSession();
//get userId or unique field from session
sessions.remove(userId);
}
public R getSessions() {
//add code here
}
public void invalidateSession(String userId) {
//add code here
}
}
N.B.: I recommend to use getSessions() and invalidateSession() carefully.
I need to retrieve users profile from Http Session. Since I need the same profile in couple different methods within the class is there a way that all the method access the same session? So I dont have to put the http request multiple times. Below is the example of session and methods.
In the below methods you will see im putting the http request in both methods since they are both in same class it would help if I dont create seprate sessions.
Http Request:
HttpSession session = request.getSession();
EntRProfile profile = (EntRProfile) session.getAttribute("profile");
Sample methods:
private Integer getClaimCount(HttpServletRequest request, String searchCriteria) throws Exception {
HttpSession session = request.getSession();
EntRProfile profile = (EntRProfile) session.getAttribute("profile");
Integer claimsCount = claimTDAO.getCountOfClaimsWithCurrentStatusNot(profile, "INI", searchCriteria);
request.getSession().setAttribute("claimsPaginationCount", claimsCount);
return claimsCount;
}
2nd Method
#RequestMapping(value = "/claims_history", method = RequestMethod.GET)
public String getClaims(HttpServletRequest request, #RequestParam(value = "claimsSearch", required = false) String searchCriteria, boolean keepOffset) throws Exception {
HttpSession session = request.getSession();
EntRProfile profile = (EntRProfile) session.getAttribute("profile");
request.getSession().setAttribute("claimsList", claimsList);
request.getSession().setAttribute("claimsSearchCriteria", searchCriteria);
Integer count = claimTDAO.getCountOfClaimsWithCurrentStatusNot(profile, "INI");
request.setAttribute("claimsHistoryCount", count);
return "claims_history";
}
You can create a private method in your controller:
private EntRProfile getProfile(HttpServletRequest request) {
HttpSession session = request.getSession();
EntRProfile profile = (EntRProfile) session.getAttribute("profile");
return profile;
}
Then you can get the profile by calling:
EntRProfile profile = getProfile(request);
I need to get current session Id without hitting the session (to give it a chance to expire).
I've used Cookies from Servlet code in order keep the session not-touched and then make the session expires after its timeout time.
I am using the following code:
public static String getSessionId(HttpServletRequest request)
{
String sessionId = "";
String logMsg = "";
if (request != null)
{
String sessionTimeout = PropertiesReader.SESSION_TIMEOUT_SCHEMA;
if (sessionTimeout != null && SessionHelper.SESSION_TIMEOUT_FIXED.equalsIgnoreCase(sessionTimeout))
{
logMsg = "FIXED: Getting SessionId from Cookies with activating the session";
Cookie[] cookies = request.getCookies();
if (cookies != null)
{
for (Cookie cook : cookies)
{
if ("JSESSIONID".equalsIgnoreCase(cook.getName()))
{
sessionId = cook.getValue();
break;
}
}
}
} else
{
logMsg = "PER_USAGE: Getting SessionId from Session";
sessionId = request.getSession(false) != null ? request.getSession(false).getId() : "";
}
}else
{
logMsg = "Request object is null";
}
logger.info(logMsg + ", sessionId=" + sessionId);
return sessionId;
}
One one OC4J app server, it works fine. although on another oc4j server, the code of accessing cookies makes the session keep active and don't timeout!
EDIT:
I really stucked!, I've trying to place afilter to remove the JSESSIONID cookie and remove all cookies from the HttpServletRequest, but when I call getSession(false) on the request passed to the servlet, I got a valid Session!
class CookieRemovalHttpServletRequestWrapper extends HttpServletRequestWrapper
{
public static final String COOKIE_HEADER = "cookie";
public static final String JSESSIONID = "JSESSIONID";
public CookieRemovalHttpServletRequestWrapper(HttpServletRequest request)
{
super(request);
}
#Override
public String getHeader(String name)
{
if (COOKIE_HEADER.equalsIgnoreCase(name))
{
return "";
}
return super.getHeader(name);
}
#Override
public Enumeration getHeaderNames()
{
Enumeration e = super.getHeaderNames();
List l = new ArrayList();
while (e.hasMoreElements())
{
String headerName = (String) e.nextElement();
if (!COOKIE_HEADER.equalsIgnoreCase(headerName))
{
l.add(headerName);
}
}
return Collections.enumeration(l);
}
#Override
public Enumeration getHeaders(String name)
{
if (COOKIE_HEADER.equalsIgnoreCase(name))
{
return new Enumeration()
{
public boolean hasMoreElements()
{
return false;
}
public Object nextElement()
{
return null;
}
};
}
return super.getHeaders(name);
}
#Override
public Cookie[] getCookies()
{
Cookie[] cs = super.getCookies();
List<Cookie> cokRet = new ArrayList<Cookie>(cs.length);
for (Cookie c : cs)
{
if (c.getName().equalsIgnoreCase(JSESSIONID)) continue;
cokRet.add(c);
}
return cokRet.toArray(new Cookie[] {});
}
}
And really think to forget all about Session and just use the session Id as just a unique identifier to the user, and do it myself the hard way.
As to your code, don't do it the hard way, use HttpServletRequest#getRequestedSessionId() and HttpServletRequest#isRequestedSessionIdValid() instead to check the requested session ID and if it is valid.
if (request.getRequestedSessionId() != null && !request.isRequestedSessionIdValid()) {
// The session has been expired (or a hacker supplied a fake cookie).
}
As to your concrete problem:
the code of accessing cookies makes the session keep active and don't timeout!
No, the code doesn't do that. It's the HTTP request itself which does that. It is not true that whenever you don't call getSession() or something, the session timeout won't be postponed. It will be postponed on every single HTTP request fired by the client, regardless of whether you need the session in the code.
To learn about how sessions work, you may find this answer helpful: How do servlets work? Instantiation, sessions, shared variables and multithreading
The session expiring isn't dependent on your code accessing the session, it depends on the user making a request with that session. Every time the user makes a request, the session's timeout will reset itself.
If you want to not have the user's request re-set the timeout (ie. have a fixed-length session), then you will need to do additional things for configuring the session, including possibly using a different filter to handle sessions.
The session is not timeout, that is correct behavior, because request was accepted and session expiration is updated in any case.
I am trying to use a HttpSessionListener to check for a cookie and get the IP address of the request.
However I don't have access to the HttpServletRequest in the listener to pass to STKUserCookie or to get the IP.
public STKUserCookie(HttpServletRequest request)
public void sessionCreated(HttpSessionEvent se) {
HttpSession httpSes = se.getSession();
if ( se.getSession().getAttribute("STKUserSession") == null) {
STKUserCookie userCookie = new STKUserCookie(request); <------- ERROR on this line "request" not available
String userBadge = userCookie.getUserID();
STKUserDAO userDAO = new STKUserDAO();
STKUser user = userDAO.getUser(userBadge);
if (user != null) {
user.setIpAddress(se.getRemoteAddr()); <------- ERROR on this line "getRemoteAddr" not a method of se
userDAO.updateLogin(user);
httpSes.setMaxInactiveInterval(36000); //set to 10 hours
httpSes.setAttribute("STKUserSession", user);
}
}
}
The above used to be a scriptlet that I was including in all my jsp pages and I am trying to refactor it into a listener, rather than a filter since I only want it to be called once per session to reduce overhead. Or should I not worry about the overhead and stick the method into a filter??
Don't worry about the overhead of a no-op filter. It is negligible.