Redirecting HTML page only once - java

I have Spring app that uses JSP. And I need to redirect one page, but only once. It's due the spring security - once the user comes to this page, I need to call redirection to log him out, but to stay on the same page. Is there any way, how to do this only via java, html or js? Or maybe I've asked wrong - there must be some way, how to do this, but I'm not very into frontend technologies, so I'd be glad, if anybody could post some code to show me, how to make this work.. Thanks :)
So the usecase: user types mywebsite.com/login -> I need to call redirect to log him out in the case he's already logged -> the same site shall appear but now without redirection.
PS: I can't redirect the user to another site - it must be the same site with same source code.

If I understand your use case, I would rather log out a user as a part of the login action (i.e. factor out the logging out process, and call it from both the logout action, as well as from the login action).
If that is not feasible (and I can't of a reason why it wouldn't be), I would focus on "redirect if he's logged in" part rather than "redirect only once" part - the former is very easy to check without almost any modification to your code, assuming you're using some kind of sessions to track the logged-in status.
Disclaimer: I know next to nothing about Sprint, these are all very general comments that should work on any classic webapp.

You can use filter .
#Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2) throws IOException, ServletException {
HttpServletRequest test1= (HttpServletRequest) arg0;
test1.getRequestURL()); it gives http://localhost:8081/applicationName/menu/index.action
test1.getRequestURI()); it gives applicationName/menu/index.action
String pathname = test1.getServletPath()); it gives //menu/index.action
if(pathname.equals("//menu/index.action")){
arg2.doFilter(arg0, arg1); // call to urs servlet or frameowrk managed controller method
// in resposne
HttpServletResponse httpResp = (HttpServletResponse) arg1;
RequestDispatcher rd = arg0.getRequestDispatcher("another.jsp"); redirect to another page at response time
rd.forward(arg0, arg1);
}
donot forget to put <dispatcher>FORWARD</dispatcher> in filter mapping in web.xml
If you do not want to use filter you can redirect to another jsp from urs controller method.

Related

capturing relevant user requests using filter/interceptors

I am capturing URLs requested for my website. I need to see what all pages were requested from my website.
To achieve this I created a basic filter, and started logging page requests from there.
Now, this filter catches all the requests specific to a page.
For e.g. abc.com/page1, abc.com/resources/myjs.js, etc.
My problem is that for each page request, subsequent resources(js,css) are requested too. I want to capture only the relevant requests.
Right now, I check for patterns like /resources to ignore such requests, but I am looking for a more clean approach.
Also, will interceptors be more useful here?
I have seen filter patterns as well. But those are not useful, since I would have to create patterns for my filter.
If you want to capture the urls accessed from your website, you can configure spring boot to generate access logs in following way until you don't want more advance information:
server.tomcat.accesslog.directory=/logs/ #absolute directory path for log files\
server.tomcat.accesslog.enabled=false #Enable access log.
server.tomcat.accesslog.pattern=any_pattern # log string format pattern for access logs.
To perform any operation based on any request pattern, you can go ahead with filters.
I'm using filters for such requirements in following way:
public class CustomFilter extends OncePerRequestFilter{
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
String url = request.getRequestURI();
if (url.startsWith("/resources/")) {
//your business logic
}
filterChain.doFilter(request,response);
}
}

how to implement production ready login logout functionality in servlet jsp

My question is simple - how to implement login-logout in servlet jsp?
Following is the use case...
I have a users table in DB with email,username and password
I have a mapped bean object - User in java having email,username,password properties
Simply I want to login by validating email and password BUT
Once I login and then logout, when I click on back button, it should not retain the session.
It should not give any warning BUT simply should ask for login
If I copy-paste restricted resource's link, it should ask for login
What all solutions I've gone through...
Some say to implement tomcat security using roles and bla bla... BUt I think I should not set username, passwords in some tomcat config file. Bcz the details are in DB table
Some ask to implement no-cache, pragma bla bla... but never work
Back button disable is foolish thing
**
What Help I am expecting from you guys ...?
**
Is there any third-party API available to do this?
How things are implemented in production ready applications ?
Should I use JAAS, or any other security process for exactly above mentioned scenario OR WHAT
Please give me some hint or solution how I should proceed implementing production ready login-logout in servlet-jsp
I've searched on internet but end up with simple Login examples or tomcat security roles etc. No one gives the actual solution. ANd please don't say that this question is NOT RELATED TO this FORUM.
Thanks
This happens because browser caches the web pages that are being loaded,you can prevent it by using filters and telling browser not to cache the web pages like below.
doFilter method of Filter
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", 0);
HttpSession session = request.getSession(false);//don't create if session doesn't exist.
if (session==null || session.getAttribute("username") == null) {
RequestDispatcher rd=request.getRequestDispatcher("login");//dispatch it to your desired page i.e login page
rd.forward(request, response);
} else {
chain.doFilter(req, res);
}
}
You should configure this filter inside web.xml or using Annotations for which url-patterns you want to filter.refer documentation for more details.
If you're using Tomcat then a good place to start is Tomcat Standard Realm Implementations.
It's important to remember that normal Java EE security authenticates users and authorises them using roles - even if you only have the one.
Once you have done that you can implement Logout by invoking a servlet which calls HttpServletRequest.logout() and then invalidates the HttpSession:
request.logout();
request.getSession().invalidate();
and then:
response.sendRedirect("some protected page");
which should resolve your back button problem and land back on the login page.

How do I forward to another URL from a Jetty handler?

Somewhere in our chain of servlet filters there is a filter which forwards the request to the sign-in page when a 401 error is sent, as a usability tweak.
I'm trying to convert this to a Jetty handler because someone wants all web applications to be authenticated by the same logic instead of every webapp having to implement their own authentication.
(The main reason we're using a filter approach in the first place is that nobody was able to get Jetty's container-level authentication to work at all - we have the ability to choose Windows auth or built-in auth and want to be able to switch between these at runtime and were never able to figure out how to make that work with Jetty.)
Out in the Jetty handler, there is some logic like this:
private void handleErrorBetter(HttpServletRequest servletRequest,
HttpServletResponse servletResponse)
throws ServletException, IOException {
if (isPageRequest(servletRequest)) {
ServletContext rootContext = servletRequest.getServletContext().getContext("/");
RequestDispatcher dispatcher = rootContext.getRequestDispatcher("/sign_in");
dispatcher.forward(servletRequest, servletResponse);
} else {
// ...
}
}
servletRequest.getServletContext() appears to correctly return the context for /. Interestingly it appears to do this even if I make a request for a different webapp, but according to the Javadoc I have to use getContext("/") to be sure that I get the root context, so I'm doing that.
Getting the dispatcher succeeds too.
Then I call forward() and this always returns a 404 response to the client.
If I go to /sign_in directly from a web browser, the form loads.
There are only two contexts on the server: the root context /, and a /sample/ context which I'm using to test the second webapp. So I know that /sign_in will be in the root context, but why does forward() give a 404 when forwarding to it?
It turned out to be a bug.
https://bugs.eclipse.org/bugs/show_bug.cgi?id=386359

Forward request from a filter

I need to forward my request (to a jsp but I don't think it's matter) from an http.Filter
if the URI of the original request pass some validation that my filter runs.
I found this page that faced similar task
Still I need to figure the following:
How can I get ServletContext in doFilter() method (in order to call forward API) getServletContext() is not recignized
Do I have to call chain.doFilter() before the forward, after the forward or not at all?
In addition do I have to call chain.doFilter() if my validation passed or only if it fails (because in this case I won't continue to forward my page)?
This question actually continue this thread,
to be more obvious, the code could be something like:
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
if (request instanceof HttpServletRequest) {
HttpServletRequest httpServletRequest = ((HttpServletRequest)request);
String requestURI = httpServletRequest.getRequestURI();
String contextPath = httpServletRequest.getContextPath();
if (<this is my implementation of the validation of this filter>){
getServletContext().getRequestDispatcher(
"MySpecific.jsp").forward(request,response);
}
}
chain.doFilter(request,response);
}
How can I get ServletContext in doFilter() method?
httpServletRequest.getSession().getServletContext();
Do I have to call chain.doFilter() before the forward, after the forward or not at all? In addition do I have to call chain.doFilter() if my validation passed or only if it fails (because in this case I won't continue to forward my page)?
I would say that if you forwarded the request, you should not call chain.doFilter() - the forwarded request will get filtered according to its own filter configuration. If your validation failed though, it depends on what the semantics of your web app are - if the original page is some sort of general error/login/welcome screen, you may want to continue to that when the validation failed. It is hard to say without knowing more of the context.
To get the ServletContext, you've got 2 options:
Store off the FilterConfig during the initialization and call FilterConfig.getServletContext()
call HttpServletRequest.getSession().getServletContext()
I don't think you necessarily need the ServletContext to get the RequestDispatcher as you could just call HttpServletRequest.getRequestDispatcher().
In relation to FilterChain.doFilter() call, if you're forwarding, I would think you wouldn't make the call, as once you forward, I assume you don't want any of the standard behavior to take place.
If you don't forward (you don't fall into your if block), then I'd call the FilterChain.doFilter() method, however that assumes there is a target on the other end to be invoked.

JSF redirect on page load

Short question: Is it possible to do a redirection, say when a user isn't logged in, when a page is rendered?
For that you should use a Filter.
E.g.
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
if (((HttpServletRequest) request).getSession().getAttribute("user") == null) {
((HttpServletResponse) response).sendRedirect("error.jsf"); // Not logged in, so redirect to error page.
} else {
chain.doFilter(request, response); // Logged in, so just continue.
}
}
Here I assume that the User is been placed in the session scope as you would normally expect. It can be a session scoped JSF managed bean with the name user.
A navigation rule is not applicable as there's no means of a "bean action" during a normal GET request. Also doing a redirect when the managed bean is about to be constructed ain't gong to work, because when a managed bean is to be constructed during a normal GET request, the response has already started to render and that's a point of no return (it would only produce IllegalStateException: response already committed). A PhaseListener is cumbersome and overwhelming as you actually don't need to listen on any of the JSF phases. You just want to listen on "plain" HTTP requests and the presence of a certain object in the session scope. For that a Filter is perfect.
Yes:
if(!isLoggedIn) {
FacesContext.getCurrentInstance().getExternalContext().redirect(url);
}
You can use a PhaseListener to specify when you want to do redirection.
In a PhaseListener try:
FacesContext ctx = FacesContext.getCurrentContext();
ctx.getApplication().getNavigationHandler()
.handleNavigation(ctx, null, "yourOutcome");

Categories

Resources