I'm using ServletRequestListener to attach to new requests, get a ServletRequest object and extract cookies from it.
I've noticed that only HTTPServletRequest has cookies but I haven't found a connection between those two objects.
Is it okay to use
HttpServletRequest request = ((HttpServletRequest) FacesContext.getCurrentInstance()
.getExternalContext().getRequest());
to retrieve the request while in a RequestInitialized method? (I do want to run on every request)
FYI - This is all done in a JSF 1.2 Application
This is not correct. The FacesContext isn't available in a ServletRequestListener per se. The getCurrentInstance() might return null, leading to NPE's.
If you're running the webapp on a HTTP webserver (and thus not some Portlet webserver for example), you could just cast the ServletRequest to HttpServletRequest.
public void requestInitialized(ServletRequestEvent event) {
HttpServletRequest request = (HttpServletRequest) event.getServletRequest();
// ...
}
Note that a more common practice is to use a Filter for this since you can map this on a fixed URL pattern like *.jsf or even on specific servlets so that it runs only when the FacesServlet runs. You might for example want to skip cookie checks on static resources like CSS/JS/images.
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
HttpServletRequest request = (HttpServletRequest) req;
// ...
chain.doFilter(req, res);
}
When you happens to be already inside the JSF context (in a managed bean, phaselistener or whatever), you could just use ExternalContext#getRequestCookieMap() to get the cookies.
Map<String, Object> cookies = externalContext.getRequestCookieMap();
// ...
When running JSF on top of Servlet API, the map value is of type javax.servlet.http.Cookie.
Cookie cookie = (Cookie) cookies.get("name");
Yes, you can do that. In Web scenarios, this will always be ok. If you want to be sure, you could do a check for the type first. (Good practice anyway):
if (FacesContext.getCurrentInstance().getExternalContext().getRequest() instanceof HttpServletRequest) {
...
By the way: Why do you have to use FacesContext? From where are you calling this code?
Related
I have a simple blog webpage with a lot of links. They are all using GetMapping. Therefore whenever I have a bot try to access those pages using POST I get an error saying
Request method 'Post' not supported.
I understand that this is caused because I use #GetMapping, and if I switch to #RequestMapping then everything will be fine. However I do not want to allow anyone to access my blog with POST. The only page that should be POST is /contact/message except that page everything should be accessed through GET.
So I have two questions:
How do I enforce people to use GET only.
How do I catch attempts to use POST and redirect them to /error?
Sidenote: I do not use spring security, there is no logging in or anything that is hidden behind an account. Also most of my mappings are using regex. Do not know if this info is of any help or not.
#GetMapping(value = {
"", "{page:^[1-9][0-9]*$}", "{section:^\\d*[a-zA-Z][a-zA-Z0-9]*[^.]+$}",
"{section:^\\d*[a-zA-Z][a-zA-Z0-9]*[^.]+$}/{page:^[1-9][0-9]*$}"})
You can add a filter in your application:
public class Tfil implements Filter {
#Override
public void doFilter(ServletRequest servletRequest,
ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
if (!"GET".equals(req.getMethod())) {
//redirect or error page
HttpServletResponse res = (HttpServletResponse) servletResponse;
//here redirect
res.sendRedirect("redirect url");
//or return 404 code
res.setStatus(404);
}
filterChain.doFilter(servletRequest,servletResponse);
}
}
I am actually pretty new to the Java EE specifications since I am kind of young. I never learned this things at school and I am facing a weird behaviour with the doFilter method.
Consider the following filter :
#WebFilter(filterName = "URLFilter", value = "/test")
public class URLFilter implements Filter {
public void destroy() {}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletResponse response = (HttpServletResponse) resp;
if (response.getStatus() == HttpServletResponse.SC_NOT_FOUND)
response.sendRedirect("/");
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {}
}
There is no servlet or page present in /test and in my browser, the status is obviously a 404 not found error when accessing the URL and so should be the value returned to me by the getStatus() method which isn't. (actually having a 200 status code)
Why is my filter not redirecting me to / as requested ? Do I misunderstand the use of Filters in general ?
UPDATE:
My question was about redirecting the client (using the sendRedirect()) when a page is not found. I did not understand the filter part because I didn't know that resp and req are actually filled with the new data when chain.doFilter() is called. (which I actually found strange since the doFilter is calling the next Filter chained by the COR pattern)
I've made a class inheriting the HttpServletResponseWrapper, implemented it, passed it to the Filter and it's working fine now.
Your filter is invoked before trying to access the actual resource (servlet, page, file, whatever) located at /test. So the response status can't be 404 yet at this time.
Then your filter invokes chain.doFilter(), thus telling the container to actually serve the resource at /test. Since there is no such resource, you get a 404.
I need to change the serverName of the ServletRequest object in my Grails controller. I'm having trouble figuring out how to do this since the serverName is a read-only property.
The most correct thing to do is probably to set up a clever filter or redirect which "fixes" your request URL before your servlet even gets involved. I know nothing about how to do that; you should ask on serverfault.com if you want to do that.
In java, you can fake it by creating your own subclass of HttpServletRequestWrapper which provides setServerName() and overrides getServerName() while delegating all other methods to the superclass. You can then provide a filter which creates an instance of your request and sends that one down the chain.
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
YourHttpServletRequest yourRequest =
new YourHttpServletRequest(request, newServerName);
chain.doFilter(yourRequest, response);
}
If I understand this correctly, CORS filter might help
I've used http://software.dzhuvinov.com/cors-filter.html in my previous project.
But you can also lookup on github for example https://github.com/eBay/cors-filter
I'm having a JavaEE Website running on a cloud-platform.
Now I want to use two types of authentications:
Is from an SSO-System, which is well integrated in the platfrom and works very nicely.
Is the problematic part: I want to authorize a user from 1) for the time of a session, and give him access to a more restricted resource.
Some details
I get the user and his data from 1).
The user first has to ask for permission to 2), which can be denyed or granted. A user gets authorization from a service, which is outside of the scope of his servlet.
For this purpose I pass a User-POJO (with the session of this user as a member) to a service.
If the service grants the rights to this user, it will set an attribute to the user session:
userSession.setAttribute("auth", "granted");
To restrict access to that resource I use a Filter:
#WebFilter("/supersecret/*")
public class NiceFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
HttpSession session = req.getSession();
// check
if (session.getAttribute("auth") != "granted")
// redirect to login
else
chain.doFilter(req, res);
}
//...
While this is currently working, I feel that my solution is very sloppy.
Altering the user-session outside the scope of a servlet seems to be bad practice.
Adding an attribute to the session for security-purposes is probably not a good idea?
I'd rather want to use standard JavaEE-mechanisms, but most of them are already used for auth-method 1), like declaring login-config in the web.xml.
Any ideas for a more robust solution to this problem?
Thanks in advance :)
I have a HashMap of custom objects being passed to a JSP using RequestDispatcher and I am able to access the object and its properties using JSTL.
However the code fails in case the parameter is sent using response.sendRedirect() .
I am not sure what the reason is and how to make it work?
The response.sendRedirect() basically instructs the client (the webbrowser) to send a new request on the given URL. You'll also see this being reflected by a change in the browser address bar.
A new request does of course not contain the attribtues of the previous (or any other) request. That would otherwise have broken the whole concept of "request scope".
To preprocess a GET request, you need to do the job in doGet() method of a servlet and then redirect to the URL of that servlet instead.
E.g.
response.sendRedirect(request.getContextPath() + "/foo");
and
#WebServlet("/foo")
public class FooServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Map<String, Foo> foos = fooService.map();
request.setAttribute("foos", foos);
request.getRequestDispatcher("/WEB-INF/foo.jsp").forward(request, response);
}
}
Note that this problem is in no way related to having a hashmap of custom objects in the request scope.
See also:
Our servlets wiki page
You can not share a request attribute in response.sendRedirect as it creates a new request.
But, if you want that HashMap, in response.sendRedirect, you can put that in session like
request.getSession().setAttribute("myMap", [HashMap object]);
and can share between the servlet and JSP. This works in both RequestDispatcher and sendRedirect.