Spring mvc: Change response object in postHandle in HandlerInterceptor - java

I am trying to save the latest time in the cookie. So after every controller call I have intercepting the call using a postHandle of HandlerInterceptor. In that I am updating the value in the cookie. But the values is not updating. Anyone have any idea why it is not working.
The code:
#Override
public void postHandle(HttpServletRequest request,
HttpServletResponse response, Object handler, ModelAndView ex)
throws Exception {
boolean isSet = true;
if (request.getSession().getAttribute("userId") != null){
for (Cookie cookies: request.getCookies()) {
if ("RequestTime".equals(cookies.getName())) {
isSet = false;
cookies.setValue(Long.toString(System.currentTimeMillis()));
response.addCookie(cookies);
}
}
if(isSet){
Cookie cookie = new Cookie("RequestTime", Long.toString(System.currentTimeMillis()));
response.addCookie(cookie);
}
}
}

when you create cookie ,you should set cookie's path, when you want to share this cookie in your project,you should set cookie path as "/" like
if (request.getSession().getAttribute("userId") != null){
Cookie cookie = new Cookie("RequestTime",Long.toString(System.currentTimeMillis()));
cookie.setPath("/")
response.addCookie(cookie); }
the default cookie path is current request URL.
NOTE: if you want to share the cookie from different subdomain, you should also set cookie domain.
cookie.setDomain(".test.com")

Related

Sending cookies using spring-boot

So, I'm trying to send cookies to my frontend and I'm not using spring security. When the user enter their name and click submit button, I want that info to be send to my spring and then I want to return the info of the user and cookie. I implemented the logic like this
#PostMapping("/addUser")
public User addUser(#RequestBody String name, HttpServletRequest request, HttpServletResponse response) {
HttpSession getSession = (HttpSession) request.getAttribute("session");
Cookie cookie = new Cookie("sessionId", getSession.getId());
response.addCookie(cookie);
sessionService.addSession(getSession);
String session = (String) getSession.getId();
System.out.println("Session id is " + session);
User newUser = new User(name, session);
userService.addUser(newUser);
return newUser;
}
to check if cookie is working correctly, I'm using this method
#PostMapping("/noOfUsers")
public int userCount(#RequestBody String sessionId, HttpServletRequest request, HttpServletResponse response) {
System.out.println(request.getSession().getId());
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals("sessionId")) {
System.out.println(cookie.getValue());
}
}
}
return this.userService.noOfUser();
}
I know you people might say "use get mapping" well I want to send my user account too when checking that's why I'm using postmapping where I will be sending my username too.
So, coming back to question. Well, I did try using postman and it worked I got the cookie value as I should have but when working with frontend, it just didn't worked which made me question am I doing it in right way??

Cookie not showing up in request

I'm working with Spring and have 2 controllers, one of them is:
#RequestMapping("/meni/{id}")
public String meni(#PathVariable String id, Model model, HttpServletRequest request, HttpServletResponse response){
cookie = new Cookie("fake_session",id);
cookie.setMaxAge(30*60);
response.addCookie(cookie);
return "meni";
}
Then in the 'meni' static HTML page, I have a post request that goes to:
#PostMapping("/index/{id}")
public void post(#PathVariable String id,#RequestBody TestDTO testDTO, HttpServletResponse response, HttpServletRequest request){
Cookie [] cookies = request.getCookies();
for (int i=0;i<cookies.length;i++){
Cookie cookie = cookies[i];
if (cookie.getName().equals("fake_session")){
System.out.println("Same cookie!");
}
}
However, the if never gets passed. If i go to the get controller twice, it recognizes the cookie, but if i go the post controller, it the if does not get passed. Everything else is running smoothly in the post controller, it does all its other tasks well.
I go to the Post controller by clicking a button that calls a ajax function in my java script that sends a POST request to that URL. Am I suppose to do something with the cookie there maybe ? I always go to the GET controller before going to the post controller so that the cookie gets created.
Try using Spring MVC's #CookieValue(value = "fake_session", defaultValue = "default") to access data set within any HTTP cookie in your post method.

Creating a cookie inside a jax-rs endpoint

I have a jax-rs endpoint. The purpose of the endpoint is to authorize a user. I need to login details inside a cookie. Below I have mentioned the related part of my code.
public Response authorize(#Context HttpServletRequest request) throws URISyntaxException {
if (authnResult.isAuthenticated()) {
//TODO create a cookie to maintain login state
Cookie authCookie = new Cookie(FrameworkConstants.COMMONAUTH_COOKIE, "test");
authCookie.setSecure(true);
authCookie.setHttpOnly(false);
authCookie.setMaxAge(5 * 60);
}
EDIT:
This is my first time when creating cookies. I followed some tutorials. In these tutorials it has added the created cookie to the response. But inside the endpoint I can't access the response. So how can I create the cookie? Please advice me.
Updated code:
public Response authorize(#Context HttpServletRequest request) throws URISyntaxException {
NewCookie cookie = new NewCookie("CookieName","CookieValue");
Response.ResponseBuilder builder = Response.ok("Cool Stuff");
builder.cookie(cookie);
Response response=builder.build();
Cookie[] cookies = request.getCookies();
}
what I need to know is how to access the newly created cookie.
You can create a javax.ws.rs.core.NewCookie. There are a bunch of different constructors, just go through the API docs.
Then you can add cookies through ResponseBuilder#cookie(NewCookie). So for example:
#GET
public Response getCookie() {
NewCookie cookie = new NewCookie("Name", "Value", "path", "domain",
"comment", 300, true, true);
ResponseBuilder builder = Response.ok("Cool Stuff");
builder.cookie(cookie);
return builder.build();
}
UPDATE (with complete example)
#Path("cookie")
public class CookieResource {
#GET
public Response getCookie(#CookieParam("A-Cookie") String cookie) {
Response response = null;
if (cookie == null) {
response = Response.ok("A-Cookie: Cookie #1")
.cookie(new NewCookie("A-Cookie", "Cookie #1"))
.build();
return response;
} else {
String cookieNum = cookie.substring(cookie.indexOf("#") + 1);
int number = Integer.parseInt(cookieNum);
number++;
String updatedCookie = "Cookie #" + number;
response = Response.ok("A-Cookie: " + updatedCookie)
.cookie(new NewCookie("A-Cookie", updatedCookie))
.build();
return response;
}
}
}
After 38 requests, you can see the result. I used a Firefox plugin Firebug. You can see the sent cookie #37, and returned cookie #38
If you need help trying to access the cookie from the client (as suggested in your comment), that may be suitable for another question on SO. Maybe off topic for this discussion, as it will rely on another technology. If this is not what you are looking for, then maybe a better explanation of exactly what you are trying to accomplish would help.

How to add a cookie using doTag method in custom tag?

I have developed a custom tag library in Java which I use in my web application.
I am not sure why but my doTag() is not setting up cookie at all. I have cleared my cache and restarted my computer as well. Here is the code:
public class UserVersionOfSite extends EvenSimplerTagSupport {
private static final Log logger = LogFactory.getLog(UserVersionOfSite.class);
private StringWriter sw = new StringWriter();
#Override
public void doTag() throws IOException, JspException {
getJspBody().invoke(sw); //get the tag body and put it in StringWriter object
//get request object to get cookie value
PageContext ctx = (PageContext)getJspContext();
HttpServletRequest httpServletRequest = (HttpServletRequest) ctx.getRequest();
HttpServletResponse httpServletResponse = (HttpServletResponse) ctx.getResponse();
if(httpServletRequest.getParameterMap().containsKey("show_full_site")) {
logger.debug("show_full_site ");
if(!checkIfCookieExists(httpServletRequest)){
Cookie cookie = new Cookie("SHOW_FULL_SITE",httpServletRequest.getParameter("show_full_site"));
cookie.setMaxAge(86400);
httpServletResponse.addCookie(cookie);
//write the tag output
if(!httpServletRequest.getParameter("show_full_site").equalsIgnoreCase("true")){
//write the response
getJspContext().getOut().println(sw.toString());
}
}else{
String cookieValueString = getCookieValue(httpServletRequest.getCookies(),"SHOW_FULL_SITE","false");
if(!cookieValueString.equalsIgnoreCase("true")){
//write the response
getJspContext().getOut().println(sw.toString());
}
}
}
}
#Override
public String getResult() throws IOException {
return "User version of site";
}
public String getCookieValue(Cookie[] cookies,
String cookieName,
String defaultValue) {
for(int i=0; i<cookies.length; i++) {
Cookie cookie = cookies[i];
if (cookieName.equals(cookie.getName()))
return(cookie.getValue());
}
return(defaultValue);
}
public boolean checkIfCookieExists(HttpServletRequest httpServletRequest){
logger.debug("inside checkIfCookieExists()");
boolean cookiePresent = Arrays.asList(httpServletRequest.getCookies()).contains( "SHOW_FULL_SITE" );
return cookiePresent;
}
}
Even I tried adding the code without using if else statements but still no success. Is there any thing critical I am missing?
Any ideas guys??!!! I have checked the browser's setting as well, but there is nothing there which is blocking a creation of cookie!
I realise the horse has probably bolted by the time I'm posting this but, for the benefit of others stumbling across it, I think the problem may be related to the feature of RequestDispatcher highlighted in this question: unable to add a cookie included in JSP via jsp:include
your following line inside checkIfCookieExists() method is wrong:
Arrays.asList(httpServletRequest.getCookies()).contains( "SHOW_FULL_SITE" );
HttpServletRequest.getCookies() returns Cookie[]. You are wrapping it inside a List and checking for a string "SHOW_FULL_SITE" inside this.
Coming back to your question- how do you know cookie is not being set in the HTTP headers? Try using browser plugins like firebug to see the HTTP response headers coming from server. Also set the path of cookie before adding it to response e.g.
Cookie cookie = new Cookie("SHOW_FULL_SITE",httpServletRequest.getParameter("show_full_site"));
cookie.setMaxAge(86400);
cookie.setPath("/");

JavaEE + Glassfishv3.0.1: Losing session attribute (SessionId is not the same between request)

I have a home.jsf that invoke a login servlet that look into database and query out the user object given the username and password. Then I save that user object into session under attribute name user, like this request.getSession().setAttribute("user", user);
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
boolean remember = "true".equals(request.getParameter("remember"));
//Hashing the password with SHA-256 algorithms
password = hash(password);
HttpSession s = request.getSession(false);
if (s != null) {
logger.log(Level.INFO, "Id: {0}", s.getId());
}
User user = scholarEJB.findUserByUserNamePassword(username, password);
try {
if (user != null) {
request.login(username, password);
request.getSession().setAttribute("user", user);
if (remember) {
String uuid = UUID.randomUUID().toString();
UserCookie uc = new UserCookie(uuid, user.getId());
scholarEJB.persist(uc);
Helper.addCookie(response, Helper.COOKIE_NAME, uuid, Helper.COOKIE_AGE);
}else{
//If the user decide they dont want us to remember them
//anymore, delete any cookie associate with this user off
//the table
scholarEJB.deleteUserCookie(user.getId());
Helper.removeCookie(response, Helper.COOKIE_NAME);
}
response.sendRedirect("CentralFeed.jsf");
}else{
response.sendRedirect("LoginError.jsf");
}
} catch (Exception e) {
response.sendRedirect("LoginError.jsf");
}
Then I have a Filer that map to all my secured page, that will try to retrieve the user object from the session, otherwise, redirect me to home.jsf to login again
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession s = request.getSession(false);
if (s != null) {
logger.log(Level.INFO, "Id Before: {0}", s.getId());
}
User user = (User) request.getSession().getAttribute("user");
s = request.getSession(false);
if (s != null) {
logger.log(Level.INFO, "Id After: {0}", s.getId());
}
if (user == null) {
String uuid = Helper.getCookieValue(request, Helper.COOKIE_NAME);
if (uuid != null) {
user = scholarEJB.findUserByUUID(uuid);
if (user != null) {
request.getSession().setAttribute("user", user); //Login
Helper.addCookie(response, Helper.COOKIE_NAME, uuid, Helper.COOKIE_AGE);
} else {
Helper.removeCookie(response, Helper.COOKIE_NAME);
}
}
}
if (user == null) {
response.sendRedirect("home.jsf");
} else {
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
response.setDateHeader("Expires", 0); // Proxies.
chain.doFilter(req, res);
}
Now as you see here, I manipulate some Cookie as well, but that is only happen when I check remember me. So now I am in CentralFeed.jsf, but then any request that I send from here will bring back to home.jsf to login again. I walk through a debugger, so when I first login, the first time I get into the Filter, i successfully retrieve the user object from session by request.getSession().getAttribute("user");. But after that, when I get back in the filter, I no longer the session attribute user anymore. I set session timeout to be 30 min in my web.xml
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
EDIT
Now when I print out the session Id between request, it is fact different session id, but I have no idea why? please help.
EDIT2
#BalusC: I actually did invalidate the session. Back then, you show me how to force a logout when user log in somewhere else (http://stackoverflow.com/questions/2372311/jsf-how-to-invalidate-an-user-session-when-he-logs-twice-with-the-same-credentia). So inside User entity i have this
#Entity
public class User implements Serializable, HttpSessionBindingListener {
#Transient
private static Map<User, HttpSession> logins = new HashMap<User, HttpSession>();
#Override
public void valueBound(HttpSessionBindingEvent event) {
HttpSession session = logins.remove(this);
if (session != null) {
session.invalidate(); //This is where I invalidate the session
}
logins.put(this, event.getSession());
}
#Override
public void valueUnbound(HttpSessionBindingEvent event) {
logins.remove(this);
}
}
In the valueBound method, I did invalidate the session, when I comment it out, everything work. I walk through the debugger, and here is what happen. When I first log in, the LoginServlet catch it. Then the line request.getSession().setAttribute("user", user); invoke the method valueBound. Then the Filter got called, and the line chain.doFilter(req, res); invoke the valueBound method again, this time, session is not null so it get in the if and session.invalidate. I comment the session.invalidate out and it work. But as u might have guess, I cant force a log out when user login somewhere else. Do you see a obvious solution for this BalusC?
The HTTP session is maintained by the JSESSIONID cookie. Ensure that your Helper.COOKIE_NAME doesn't use the same cookie name, it will then override the session cookie.
If that is not the case, then I don't know. I would use Firebug to debug the HTTP request/response headers. In a first HTTP response on a brand new session you should be seeing the Set-Cookie header with the JSESSIONID cookie with the session ID. In all subsequent requests within the same session, you should be seeing the Cookie header with the JSESSIONID cookie with the session ID.
A new session will be created when the Cookie header is absent or contains a JSESSIONID cookie with a (for the server side) non-existing session ID (because it's been invalidated somehow), or when the server has responded with a new Set-Cookie header with a different session ID. This should help you in nailing down the culprit. Is it the server who generated a new session cookie? Or is it the client who didn't send the session cookie back?
If it was the server, then somewhere in the server side the session has been expired/invalidated. Try putting a breakpoint on HttpSession#invalidate() to nail it further down.
If it was the client (which would be very weird however, since it seems to support cookies fine), then try to encode the redirect URL to include the JSESSIONID.
response.sendRedirect(response.encodeRedirectURL(url));
Try with different clients if necessary to exclude the one and other.
look at the JSessionID param in your request. If it changes that means you are losing your session (browser is telling your Server its another session). Dont know why its happening but propably is something you are doing (open another window, change servlet context and come back, change server in some request... etc.).
Please post more information if you confirm that

Categories

Resources