Create http session in filter - java

My xhtml web pages are called from an external system using a simple request, I suppose to check if the user name - given from the request - is valid or not, if valid he suppose to get to the home page, other than that he is redirected to the external system. I created a filter to get the request:
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
// skip the resources library
if (!req.getRequestURI().startsWith(req.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER)) {
res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP
// 1.1.
res.setHeader("Pragma", "no-cache"); // HTTP 1.0.
res.setDateHeader("Expires", 0); // Proxies.
}
Object attr = req.getParameter("user");
String language = (String) req.getParameter("language");
if (attr != null && language != null) {
// check user in db
String userAdmin = (String) attr;
ResultStatus result = myDao.findUser(userAdmin);
if (result.getStatus().equals(ResponseStatus.SUCCESS)) {
// User is logged in, so just continue request.
User user = new User();
user.setAccountId(result.getAccount().getAccountId());
chain.doFilter(req, res);
} else {
// User is not logged in, so redirect to index.
res.sendRedirect(req.getContextPath() + "/test.xhtml");
}
} else {
// User is not logged in, so redirect to index.
res.sendRedirect(req.getContextPath() + "/test.xhtml");
}
}
I need to create session for the user in the filter if he is a valid user, so I can get the user object at any back bean.

To set it just do this :
req.getSession().getServletContext().setAttribute(LoginFilter.USER_KEY, user);
chain.doFilter(req, res);
To get it :
FacesContext facesContext = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest) facesContext.getExternalContext().getRequest();
User user = (User) request.getSession().getServletContext().getAttribute(LoginFilter.USER_KEY);

Related

back button goes to confirm form resubmission

I made a logout servlet for logout button, when clicking on logout servlet it successfully going to login page as coded. But when clicking on back button, it asks for form resubmission and after confirming it again going to previous user session.
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
/* PrintWriter out = response.getWriter(); */
HttpSession session = request.getSession();
response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0");
response.setHeader("Cache-control", "no-cache");
response.setHeader("Pragma", "no-cache");
response.setHeader("Expire","0");
response.setDateHeader("Expires",-1);
session.invalidate();
String userr = (String)request.getAttribute("k");
if (userr == null)
response.sendRedirect("Login.html");
}
To anyone, who has a similar issue, here is the solution that worked for me.
Create your login.jsp page with the user input form (method should be POST)
<form action="${pageContext.request.contextPath}/userAuth" method="POST">
...
</form>
Create a filter class and map it to login.jsp. Inside the filter class make a check for null, retrieve session and check if it contains an attribute, which will signal that the user has already logged in (I used User object and mapped it as "user")
#WebFilter("/login.jsp")
public class AuthFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpSession session = ((HttpServletRequest) request).getSession();
if (session.getAttribute("user") != null) {
response.setContentType("text/html;charset=UTF-8");
request.getRequestDispatcher("homepage.jsp").forward(request, response);
}
chain.doFilter(request, response);
}
}
Create servlet class and map it to the form action inside login.jsp. Override doPost and doGet methods: former will contain user credentials processing logic, latter will contain log out logic.
#WebServlet("/userAuth")
public class AuthServlet extends HttpServlet {
/**
* Log in
*/
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
HttpSession session = request.getSession();
String email = request.getParameter("email");
String password = request.getParameter("password");
try {
User user = UserDAO.getUser(email, password);
session.setAttribute("user", user);
response.sendRedirect(request.getContextPath() + "/login.jsp");
} catch (DAOException e) {
e.printStackTrace();
}
}
/**
* Log out
*/
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
request.getSession().invalidate();
response.setContentType("text/html;charset=UTF-8");
response.sendRedirect("login.jsp");
}
}
Create your homepage.jsp and add the logout button which will send GET to the servlet
Logout
Now the logic behind this is as follows:
The servlet doesn't actually redirect to user homepage. All it does is adding that one attribute, that the filter is looking for, and redirecting request back to login.jsp. And login.jsp always gets intercepted by the filter, who redirects to the homepage if that attribute is present.
This way you will solve the problem of keeping the user logged in until the session is on, as well as the problem of user being able to return or refresh page (which will cause form resubmission) after logging out. No additional headers like "no-cache" are needed.

Forwarding a request from one servlet to another using Request dispatcher

I was trying to create a cookie in one servlet , add it to response() and forwarded it to another servlet using DisaptcherServlet and tried to retrive the cookie using request.getCookies(). But this always coming out to be null.
//Servlet one
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String userName = request.getParameter("username");
String password = request.getParameter("password");
Cookie cookie = new Cookie("name", "value");
cookie.setMaxAge(30);
response.addCookie(cookie);
if(userName.equals("username") && password.equals("*****")){
RequestDispatcher requestDispatcher = request.getRequestDispatcher("/Welcome");
requestDispatcher.forward(request, response);
}
else{
System.out.println("invalid credentials");
}
}
//welcome servlet
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie [] cookie = request.getCookies();
if(cookie != null){
System.out.println("sucess");
}
else{
System.out.println("cookieis null");
}
}
When you forward a request you are basically saying "no I don't want to process this request give it to this other resource instead". This means the forwarded request uses the same request and response as the original request.
In your example servlet one sets a cookie on the response, which welcome servlet cannot access because there is no API on the response object to get cookies. If you want this pattern servlet one should set a parameter on the request object which welcome servlet can then get from the request object.

get same session object in jsp and Servlet Filter?

I am setting an attribute to the session object in jsp page as shown below:
String remoteAddr = request.getRemoteAddr();
session.setAttribute("remoteAddr",remoteAddr);
Then, I am trying to retrieve that session attribute in the servlet filter:
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String remoteIP = httpServletRequest.getSession(false).getAttribute("remoteAddr");
}
But I am getting a null value for the session object here. What is the correct way to get same session object here?
The method HttpServletRequest.html#getSession(boolean) may return null
If create is false and the request has no valid HttpSession, this method returns null.
A Filter may be invoked before a resource is requested or after it is requested depending on when you perform chain.doFilter(request, response);
In your case it seem that you query the session before the jsp is executed, i.e. doing something like this:
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String remoteIP = (String) httpServletRequest.getSession(false).getAttribute("remoteAddr");
// pass the request along the filter chain
chain.doFilter(request, response);
Changing it to
// pass the request along the filter chain
chain.doFilter(request, response);
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String remoteIP = (String) httpServletRequest.getSession(false).getAttribute("remoteAddr");
Will get it to work, but I doubt this is what you intend to do, since you probably want to check the remote IP and decide whether to allow access or deny it to the requested resource, in which case you may want to do something like this:
String remoteIP= request.getRemoteAddr();
if(remoteIP.matches("some pattern")) {
((HttpServletResponse)response).setStatus(HttpServletResponse.SC_FORBIDDEN);
} else {
// pass the request along the filter chain
chain.doFilter(request, response);
}

how to make a filter to avoid accessing a page if not logged?

So I´m writing an interceptor so when a user tryies to access a page without being logged he gets send back to the login
The thing is that my filter is that the condition that checks if a user is logged is always true and whats worst; it also intercept resources (css, images, js)
So how should I change my filter so it works??
Here is my code:
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
try {
// check whether session variable is set
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
boolean estaLoggeado = false;
if (req.getSession().getAttribute("estaLoggeado") != null) {
estaLoggeado = new Boolean("" + req.getSession().getAttribute("estaLoggeado"));
}
// allow user to proccede if url is login.xhtml or user logged in or user is accessing any page in //public folder
String reqURI = req.getRequestURI();
System.out.println(reqURI);
System.out.println("index: " + reqURI.indexOf("/index.xhtml"));
System.out.println("pages: " + reqURI.indexOf("/pages/"));
System.out.println("resources: " + reqURI.contains("javax.faces.resource"));
System.out.println("log: " + estaLoggeado);
if ((reqURI.indexOf("/index.xhtml") >= 0 || reqURI.indexOf("/pages/") >= 0 || reqURI.contains("javax.faces.resource"))) {
System.out.println("Si");
chain.doFilter(request, response);
} else { // user didn't log in but asking for a page that is not allowed so take user to login page
System.out.println("No");
res.sendRedirect(req.getContextPath() + "/pages/index.xhtml"); // Anonymous user. Redirect to login page
}
} catch(Throwable t) {
System.out.println(t.getMessage());
}
} //doFilter
Thanks in advance!!
You forgot to check estaLoggeado in the if() block. In other words, you're never actually checking if the user is logged in. You're merely printing to stdout whether the user is logged in.
All in all, this filter's logic is rather clumsy. Those contains() checks on the URI are very poor (note that indexOf(part) >= 0 is effectively exactly the same as contains(part)). What if the part is in the beginning, middle or the ending of an URL? You should be performing exact/starts/ends matching.
Here's a rewrite:
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession(false);
String loginURL = request.getContextPath() + "/pages/index.xhtml";
boolean loggedIn = (session != null) && (session.getAttribute("estaLoggeado") != null);
boolean loginRequest = request.getRequestURI().equals(loginURL);
boolean resourceRequest = request.getRequestURI().startsWith(request.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER + "/");
if (loggedIn || loginRequest || resourceRequest)) {
chain.doFilter(request, response); // So, just continue request.
}
else {
response.sendRedirect(loginURL); // So, redirect to login page.
}
}
(as a side note: I recommend to replace estaLoggeado by user (or usuario if you really need to make your code unreadable to non-English people) so that it represents the whole user instead of just an useless "flag")
Note that this doesn't cover ajax requests. The redirect would fail with no visual feedback when the session is expired during submitting a JSF ajax form. For a more extended filter, head to this answer: Authorization redirect on session expiration does not work on submitting a JSF form, page stays the same.

Webfilter only manages to login user in 2nd response (remember me)

I've been playing around with code inspired from one of balusC's answers. Basicly its a webfilter that tries to login the user if there is a remember me cookie.
The login happens so that it first fetches the MyUser entity from the userService-EJB and places it in the MUserSessionBean which is a #SessionScoped jsf-ManagedBean
Problem is that in the first response, the user appear as not logged in.
But in the logs i can see it is being logged in and if I just request a page refresh in the browser, the response will show a logged in user.
I've tried to place a redirect in som various places after the login happens, but the page-layout breaks when i tried that..
How can i successfully display a logged-in user in first response?
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,
ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
MUserSessionBean mUserSessionBean = (MUserSessionBean) request.getSession(true)
.getAttribute("mUserSessionBean");
if (mUserSessionBean != null && mUserSessionBean.getCurrentUser() == null) {
String uuid = CookieUtil.getCookieValue(request, CookieUtil.COOKIE_NAME);
if (uuid != null) {
MyUser user = userService.findUserByUUID(uuid);
if (user != null) {
mUserSessionBean.setCurrentUser(user);
CookieUtil.addCookie(response, CookieUtil.COOKIE_NAME, uuid, CookieUtil.COOKIE_AGE);
} else {
CookieUtil.removeCookie(response, CookieUtil.COOKIE_NAME);
}
}
}
// pass the request along the filter chain
chain.doFilter(req, res);
}
From what I can see, you're not actually logging the user in on the first go around. All you're doing so far is simply setting a value in a session created without the container actually authenticating the user.
The remember-me feature requires you to authenticate against the realm on behalf of the user, using the credentials you pulled up with the remember-me token. You haven't done that. Even on the page refreshes where it appears the user has logged in, technically that's not true. It only appears as logged in because
if (mUserSessionBean != null && mUserSessionBean.getCurrentUser() == null)
resolves to true after the page has been requested the first time and skips all checking. Subsequent requests pass through simply because you forcefully placed an instance of MyUser in the session. In reality, the user is not logged in and this is probably responsible for the page breaks that occur elsewhere within your application.
You need to truly authenticate the user against the realm for peace to reign :)
if (uuid != null) {
MyUser user = userService.findUserByUUID(uuid);
if (user != null) {
request.login(user.username,user.password); //Authenticate!!!!
mUserSessionBean.setCurrentUser(user);
CookieUtil.addCookie(response, CookieUtil.COOKIE_NAME, uuid, CookieUtil.COOKIE_AGE);
} else {
CookieUtil.removeCookie(response, CookieUtil.COOKIE_NAME);
}
}
I did a quick-fix that solved the problem. Instead of storing the user-entity in a SessionScoped ManagedBean, I stored it directly in the session. So the filter method looks like this:
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,
ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
MyUser user = (MyUser) request.getSession(true).getAttribute("user");
if (user == null) {
String uuid = CookieUtil.getCookieValue(request, CookieUtil.COOKIE_NAME);
if (uuid != null) {
user = ub.findUserByUUID(uuid);
if (user != null) {
request.getSession().setAttribute("user", user);
CookieUtil.addCookie(response, CookieUtil.COOKIE_NAME, uuid, CookieUtil.COOKIE_AGE);
} else {
CookieUtil.removeCookie(response, CookieUtil.COOKIE_NAME);
}
}
}
// pass the request along the filter chain
chain.doFilter(req, res);
}
The advantage is the filter doesnt have to wait for ManagedBean to be constructed. Then the SessionScoped-Bean peak into the session and fetch the entity the filter might have put there.
#ManagedBean
#SessionScoped
public class MUserSessionBean {
private MyUser currentUser;
#PostConstruct
public void init() {
if (currentUser == null) {
ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
currentUser = (MyUser) context.getSessionMap().get("user");
}
}
...
}
I will look into to servlet-managed-authentication or what it may be called as Kollossus sugested, but the immediate problem is gone atleast.

Categories

Resources