setting cookie to null not working in java - java

i want to remove cookie with domain name and context path as "/" which is running in my cloud server.
i have below code for clearing cookie in cloud server
Cookie cookie = new Cookie(cookieName, null);// cookieName = TEST_COOKIE
String cookiePath = request.getContextPath();
cookie.setPath(cookiePath); // path = "/"
cookie.setDomain("mydomain.com");
cookie.setMaxAge(0);
response.addCookie(cookie);
if i notice the cookie in my browser i have below details
cookie name = "TEST_COOKIE" value = "MUZJd3NuNDhy" domain = "mydomain.com" path = "/"
where in my localhost, above code works fine, without setting domain name. even i tried with empty domain name which is not working. dont know how to proceed with this, direction is much appreciated.
EDIT -
below code without domain in localhost is working fine with context path as /MyApp.
Cookie cookie = new Cookie(cookieName, null);
String cookiePath = request.getContextPath();
cookie.setPath(cookiePath); // path = "/"
cookie.setMaxAge(0);
response.addCookie(cookie);
when i removed contextPath "/MyApp", it stopped working in localhost too, where in my cloud server my context path is "/" .

After lot of debugging, i found the request.getContextPath was returning empty string instead of "/" in my remote server, and in jave doc
* Returns the portion of the request URI that indicates the context
* of the request. The context path always comes first in a request
* URI. The path starts with a "/" character but does not end with a "/"
* character. For servlets in the default (root) context, this method
* returns "". The container does not decode this string.
since i am having root context , the method return empty string instead of "/", i have fixed it by below code and it is working now.
if (cookiePath.isEmpty()) {
cookie.setPath("/");
} else {
cookie.setPath(cookiePath);
}

You cannot set a Cookie as null but you can delete it (i.e. : when you'll try to get it next time, it will return null).
Just change your first line with :
Cookie cookie = new Cookie(cookieName, "");
String cookiePath = request.getContextPath();
cookie.setPath(cookiePath); // path = "/"
cookie.setDomain("mydomain.com");
cookie.setMaxAge(0);
response.addCookie(cookie);

Related

Can't Remove cookie from response using LegacyCookieProcessor and redirect to same originating URL

I have to remove Cookies from the Response and redirect back to the same requesting URL. I recently upgraded to tomcat 9 and started using LegacyCookieProcessor to avoid invalid domain error. But for some reason i am unable to remove the cookie and redirect to same URL with subsequent call having no cookie in the request.
below is the code i am using to remove the cookie:
public static void removeCookie(String name, HttpServletRequest req, HttpServletResponse res) {
boolean isSecure = req.isSecure();
String domain = getDomain(req);
String path = "/";
String cookieName = getTicketCookiePrefix() + name;
addCookie(req, res, cookieName, "", 0, path, domain, isSecure);
Cookie[] cookies = req.getCookies();
if (cookies != null) {
Cookie[] var8 = cookies;
int var9 = cookies.length;
for(int var10 = 0; var10 < var9; ++var10) {
Cookie cookie = var8[var10];
if (cookie.getName().equals(cookieName)) {
cookie.setValue("");
}
}
}
}
public static void addCookie(HttpServletRequest request, HttpServletResponse response, String name, String value, int cookielife, String path, String domain, boolean secure) {
Cookie ck = createCookie(name, encodeCookieValue(value));
if (path != null) {
ck.setPath(path);
}
if (domain != null) {
ck.setDomain(domain);
}
ck.setMaxAge(cookielife);
ck.setSecure(secure);
response.addCookie(ck);
}
Please Let me know we need to do anything differently with legacy cookie processor to remove cookie.
Problem Statement: User-agent (IE) is unable to process (remove) cookie using 'Set-Cookie' header
Relevant diff between Tomcat 8 & 9:
Tomcat 8
LegacyCookieProcessor is default cookie processor
there is significance of Tomcat VM param FWD_SLASH_IS_SEPARATOR
strict compliance with RFC2109
Tomcat 9
Rfc6265CookieProcessor is default cookie processor
there is no significance of tomcat VM param FWD_SLASH_IS_SEPARATOR
Relevant diff between cookie processors:
The legacy cookie parsing algorithm supported only limited global configuration via several system properties. Those system properties are still supported, but are going to be deprecated in favor of this new configuration element.
ref: tomcat-8.0, tomcat-8.5
LegacyCookieProcessor
implements a strict interpretation of the cookie specifications if
STRICT_SERVLET_COMPLIANCE is true, RFC2109 is enforced
Rfc6265CookieProcessor
interoperable, but does not allow domain stating with dot (.)
Combination used: Tomcat9 + LegacyCookieProcessor
If STRICT_SERVLET_COMPLIANCE is set to true, then implicit value of FWD_SLASH_IS_SEPARATOR is also set to true
And '/' (forward slash) character will be treated as a separator
"some browsers will fail to process a cookie if the path attribute is quoted as is required by a strict adherence to the specifications"
usually we run Tomcat with the following:
org.apache.catalina. STRICT_SERVLET_COMPLIANCE=true, org.apache.tomcat.util.http.ServerCookie.FWD_SLASH_IS_SEPARATOR=false
Hence, in order to change this behaviour, make use of forwardSlashIsSeparator attribute in LegacyCookieProcessor, instead of FWD_SLASH_IS_SEPARATOR in Tomcat 9
Solution:
Replace VM param FWD_SLASH_IS_SEPARATOR with LegacyCookieProcessor.forwardSlashIsSeparator attribute under context.xml/CookieProcessor
<CookieProcessor className="org.apache.tomcat.util.http.LegacyCookieProcessor" forwardSlashIsSeparator="false"/>
Ref:
RFC2109 - https://www.ietf.org/rfc/rfc2109.txt
RFC6265 - https://www.ietf.org/rfc/rfc6265.txt

Setting cookie in JSP and retrieving from non servlet class

I have a situation where i need to set cookie in JSP and i need to get those cookie in normal java class.
The JSP:
CookieManager manager = new CookieManager();
CookieHandler.setDefault(manager);
CookieStore cookieJar = manager.getCookieStore();
// create cookie
HttpCookie cookie = new HttpCookie("UserName", "John Doe");
// add cookie to CookieStore for a
// particular URL
URL url = new URL("http://localhost:8080");
url.openConnection().connect();
cookieJar.add(url.toURI(), cookie);
System.out.println("Added cookie using cookie handler");
%>
Below is the Java class [not a servlet class] and this class is running in the server and this is invoked not after the JSP call but somewhere in the application only if any event occurs. below is the code where i wrote to capture cookies.
URL url = new URL("http://localhost:8080");
URLConnection conn = url.openConnection();
conn.getContent();
CookieManager cm = new CookieManager();
CookieHandler.setDefault(cm);
cm.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
CookieStore cs = cm.getCookieStore();
List <HttpCookie> cookies = cs.getCookies();
for (HttpCookie cookie: cookies) {
System.out.println("CookieHandler retrieved cookie: " + cookie);
}
would this scenario works if i want to retrieve the cookies in non servlet class?
The output of the above code will return empty list.
However if i write a servet class with request.getCookie("UserName") I will see the cookie value.
Here i need to understand how would i get the cookie value without using request object.
Because request object is not always passed in multiple invocation of java class. And i am not using session.
please let me know if you have any better approach.
Thanks-
Instead Use the getHeaderFields() method from the connection Object to get the full list of Name-Value pairs representing the header fields of the specific connection
Cookie information(if present)should be under the “Set-Cookie” header field.
Map<String, List<String>> headerFields = conn.getHeaderFields();
Set<String> headerFieldsSet = headerFields.keySet();
Iterator<String> hearerFieldsIter = headerFieldsSet.iterator();
Then iterate over the Set and check if the cookie is present. If it is present print it out.
while (hearerFieldsIter.hasNext()) {
String headerFieldKey = hearerFieldsIter.next();
if ("Set-Cookie".equalsIgnoreCase(headerFieldKey)) {
List<String> headerFieldValue = headerFields.get(headerFieldKey);
for (String headerValue : headerFieldValue) {
System.out.println("Cookie Found...");
String[] fields = headerValue.split(";\s*");
String cookieValue = fields[0];
System.out.println("cookieValue:" + cookieValue);
}
}
}
Y0u can refer this examle

How to get only part of URL from HttpServletRequest?

From the following URL I need to get (http://localhost:9090/dts) alone.
That is I need to remove (documents/savedoc) (OR)
need to get only - (http://localhost:9090/dts)
http://localhost:9090/dts/documents/savedoc
Is there any method available in request to get the above?
I tried the following and got the result. But still trying.
System.out.println("URL****************"+request.getRequestURL().toString());
System.out.println("URI****************"+request.getRequestURI().toString());
System.out.println("ContextPath****************"+request.getContextPath().toString());
URL****************http://localhost:9090/dts/documents/savedoc
URI****************/dts/documents/savedoc
ContextPath****************/dts
Can anyone please help me in fixing this?
You say you want to get exactly:
http://localhost:9090/dts
In your case, the above string consist of:
scheme: http
server host name: localhost
server port: 9090
context path: dts
(More info about the elements of a request path can be found in the official Oracle Java EE Tutorial: Getting Information from Requests)
##First variant:###
String scheme = request.getScheme();
String serverName = request.getServerName();
int serverPort = request.getServerPort();
String contextPath = request.getContextPath(); // includes leading forward slash
String resultPath = scheme + "://" + serverName + ":" + serverPort + contextPath;
System.out.println("Result path: " + resultPath);
##Second variant:##
String scheme = request.getScheme();
String host = request.getHeader("Host"); // includes server name and server port
String contextPath = request.getContextPath(); // includes leading forward slash
String resultPath = scheme + "://" + host + contextPath;
System.out.println("Result path: " + resultPath);
Both variants will give you what you wanted: http://localhost:9090/dts
Of course there are others variants, like others already wrote ...
It's just in your original question you asked about how to get http://localhost:9090/dts, i.e. you want your path to include scheme.
In case you still doesn't need a scheme, the quick way is:
String resultPath = request.getHeader("Host") + request.getContextPath();
And you'll get (in your case): localhost:9090/dts
AFAIK for this there is no API provided method, need to customization.
String serverName = request.getServerName();
int portNumber = request.getServerPort();
String contextPath = request.getContextPath();
// try this
System.out.println(serverName + ":" +portNumber + contextPath );
Just remove URI from URL and then append context path to it. No need to fiddle with loose schemes and ports which is only more tedious when you're dealing with default port 80 which don't need to appear in URL at all.
StringBuffer url = request.getRequestURL();
String uri = request.getRequestURI();
String ctx = request.getContextPath();
String base = url.substring(0, url.length() - uri.length() + ctx.length());
// ...
See also:
Browser can't access/find relative resources like CSS, images and links when calling a Servlet which forwards to a JSP (for the JSP/JSTL variant of composing the base URL)
In my understanding, you need the domain part and Context path only. Based on this understanding, You can use this method to get the required string.
String domain = request.getRequestURL().toString();
String cpath = request.getContextPath().toString();
String tString = domain.subString(0, domain.indexOf(cpath));
tString = tString + cpath;
For those who want to get, in their endpoint, the URL of the front page which targeted the endpoint. You can use this:
request.getHeader("referer")
Usually I have a method like this:
public String getAbsoluteContextPath() throws MalformedURLException {
ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
HttpServletRequest request = (HttpServletRequest) context.getRequest();
URL url = new URL(request.getRequestURL().toString());
return url.getProtocol() + "://" + url.getAuthority() + context.getRequestContextPath();
}
This method will return what you want, with the port number only if it exists in the current request. In your case it will return: http://localhost:9090/dts

Get url parameters after # in java

I am trying to get the access_token from facebook. First I redirect to facebook using an url as the following
https://graph.facebook.com/oauth/authorize?type=user_agent&client_id=7316713919&redirect_uri=http://whomakescoffee.com:8080/app/welcome.jsf&scope=publish_stream
Then I have a listener that gets the url.
FacesContext fc = FacesContext.getCurrentInstance();
HttpServletRequest request =
(HttpServletRequest) fc.getExternalContext().getRequest();
String url = request.getRequestURL().toString();
if (url.contains("access_token")) {
int indexOfEqualsSign = url.indexOf("=");
int indexOfAndSign = url.indexOf("&");
accessToken = url.substring(indexOfEqualsSign + 1, indexOfAndSign);
handleFacebookLogin(accessToken, fc);
}
But it never gets inside the if..
How do I retrieve the parameter when it comes after a # instead of a usual parameter after ?.
The url looks something like
http://benbiddington.wordpress.com/#access_token=
116122545078207|
2.1vGZASUSFMHeMVgQ_9P60Q__.3600.1272535200-500880518|
QXlU1XfJR1mMagHLPtaMjJzFZp4
The URL is incorrectly encoded. It's XML-escaped instead of URL-encoded. The # is a reserved character in URL's which represents the client-side fragment which is never sent back to the server side.
The URL should more look like this:
https://graph.facebook.com/oauth/authorize?type=user_agent&client_id=7316713919&redirect_uri=http%3a%2f%2fwhomakescoffee.com%3a8080%2fapp%2fwelcome.jsf%26scope%3dpublish_stream
You can use java.net.URLEncoder for this.

How can you get the original REQUEST_URI from within a Struts 2 Action reached via an apache ErrorDocument redirection?

How can you access the REQUEST_URI from within a Struts 2 Action? In perl/php/ruby it is readily available via ENV["REQUEST_URI"] and the like. In java it seems that the PageContext.getErrorData().getRequestURI() is what I'm looking for, but sadly, the PageContext does not appear to be defined within the action, either because the ErrorDocument redirection makes the request not look like an error, or because it is defined later.
A particular example
Given an apache fronted (mod_jk/ajp) struts 2 app on tomcat reached via the ErrorDocument 404 configuration in apache. With the following details:
-- Original request url (which triggers the 404) --
http://server/totally/bogus/path
-- http.conf --
ErrorDocument 404 /struts2app/lookup.action
-- struts action --
public String bogusUrlLookup() {
HttpServletRequest request = ServletActionContext.getRequest();
// contains /lookup.action as does request.getRequestURI();
String url = RequestUtils.getServletPath(request);
// PageContext is null, so I cannot reach ErrorData from it.
log.info("pageContext="+ServletActionContext.getPageContext());
// Not in the ENV
// Map env = System.getenv();
// Not in the ATTRIBUTES
// request.getAttributeNames()
// Not in HEADER
// request.getHeaderNames()
return ERROR;
}
Again all I need is the string "/totally/bogus/path", but in the above action the only url string that I can find is "/struts2app/lookup.action". I'm tied to the ErrorDocument because the totally/bogus/path is not likely to be within the namespace of my application because apache serves other non-tomcat resources.
request.getAttribute("javax.servlet.forward.request_uri")
baseUri = (String)request.getAttribute("struts.request_uri");
Use:
JkEnvVar REDIRECT_URL ""
in your httpd.conf file. Then use request.getAttribute("REDIRECT_URL"); to get the variable in your jsp/servlets.
If you don't wanna miss the query string part, this is better:
final String referrer = (String) request.getAttribute(RequestDispatcher.FORWARD_REQUEST_URI);
if(referrer != null) {
final String query = (String) request.getAttribute(RequestDispatcher.FORWARD_QUERY_STRING);
if(query != null && query.length() > 0) {
url = referrer+ "?" + query;
}
else {
url = referrer;
}
// do something
}

Categories