how to differentiate a new log in (new Session) and a session time out - jsf

Could someone let me know how to differentiate a new log in (new Session) and a session time out .
Only on login : user must be authenticated and redirected to a servlet to load user details (on other screnarios user must not be redirected to the servlet)
and on timeout user must be redirected to the timeout page.
To identify a new session (user not logged in):
-- Session attributes cannot be used since the session becomes null on timeout.
-- Setting cookies for session management didnt work.
The cookies are getting removed for the current session
Cookie cookie = new Cookie("activeSession", null);
cookie.setMaxAge(0);
cookie.setPath("/");
cookie.setValue("");
httpServletResponse.addCookie(cookie);
getCookieValue(httpServletRequest , "activeSession"); returns null
public static String getCookieValue(HttpServletRequest request, String name) {
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie != null && name.equals(cookie.getName())) {
return cookie.getValue();
}
}
}
return null;
}
After logout or Timeout (session is invalidated) when user logs in and a new session is created.
The cookies that were removed in the previous sessions reappears with the preset values.
getCookieValue(httpServletRequest , "activeSession") returns a value;
If I use the below approach it works for the 1 st login attempt.
After the first login session has timedout ,the filter redirects to timeout page.
The actual problem arises when user accesses the application in the same window after timeout.
public void doFilter(ServletRequest request, ServletResponse response,FilterChain filterChain) throws IOException,
{ if ((request instanceof HttpServletRequest)
&& (response instanceof HttpServletResponse)) {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
//Check for a new login
if (httpServletRequest.getSession(false) == null && httpServletRequest.getRequestedSessionId()==null)
{
// Create a new session
httpServletRequest.getSession();
//Redirect to servlet on 1 st login to fetch details from DB
httpRequest.getRequestDispatcher("/loginServlet").forward(request,response);
}else{
//validate active or timedout sessions.
boolean isSessionValid = (httpServletRequest.getRequestedSessionId() != null) && !httpServletRequest.isRequestedSessionIdValid();
if(isSessionValid)
{
httpServletResponse.sendRedirect(getTimeoutPage());
}
}
}
filterChain.doFilter(request, response);
}
Therefore the details are not fetched from DB and the page is not loaded correctly.
Browser:IE 8
Server : Weblogic server

Your cookie approach is unnecessary and technically invalid. A max age of 0 makes it to expire immediately when the response is processed. But anyway, you don't need an additional cookie. The HttpSession is by itself already backed by a cookie and the Servlet API already offers methods to check the one and other. Just store the logged-in user as an attribute of the HttpSession (which can in turn be a session scoped JSF managed bean).
The following example should do, assuming that you've stored the logged-in user as a property of a session scoped JSF managed bean with the managed bean name "auth".
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
Authenticator auth = (Authenticator) req.getSession().getAttribute("auth");
if (req.getRequestedSessionId() != null && !req.isRequestedSessionIdValid()) {
res.sendRedirect(req.getContextPath() + "/timeout.xhtml");
} else if (auth == null || !auth.isLoggedIn()) {
res.sendRedirect(req.getContextPath() + "/login.xhtml");
} else {
chain.doFilter(request, response);
}
}

Related

Prevent page access via URL

Good morning everyone!
I have an application that has access control, it is working ok
But the user can write the URL in the browser and access pages that he does not have access to
Could someone help me solve this?
Below is the implementation of Filter
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filter) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpSession session = req.getSession();
if (session.getAttribute("sessionUser") != null
|| req.getRequestURI().endsWith("Login.xhtml")) {
System.out.println("if");
filter.doFilter(request, response);
} else {
System.out.println("else");
HttpServletResponse res = (HttpServletResponse) response;
res.sendRedirect(req.getContextPath()+"/Login.xhtml");
}
}
Before answer i suggest you to use one security framework to control access of pages. something powerfull like spring security.
But in this case you checked only that user session is validated or not but nothing related to page or page name added to session.
You should add all user accessed page (name for example), to session as attributes after successful login and then in this filter, check what page user requested to access?
If session attributes contains that page dofilter called else redirect to access denied page.

JSF, session timeout handling [duplicate]

This question already has answers here:
Authorization redirect on session expiration does not work on submitting a JSF form, page stays the same
(2 answers)
Closed 4 years ago.
I have configured my session timeout in the server and have added a filter to handle session timeout. But when I am trying to redirect it back to the login page its not working. I searched the net but not getting anything solid. I am using jsf.. my code
public class SessionTimeoutFilter implements Filter {
private String timeoutPage = "login.seam";
public void init(FilterConfig filterConfig) throws ServletException {
}
public void doFilter(ServletRequest request,
ServletResponse response, FilterChain filterChain) throws IOException,ServletException {
if ((request instanceof HttpServletRequest)
&& (response instanceof HttpServletResponse))
{
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
if (isSessionControlRequiredForThisResource(httpServletRequest)) {
if (isSessionInvalid(httpServletRequest))
{
String timeoutUrl = httpServletRequest.getContextPath()
+ "/" + getTimeoutPage();
System.out.println("Session is invalid! redirecting to timeoutpage : " + timeoutUrl);
httpServletResponse.sendRedirect(timeoutUrl);
return;
}
}
}
filterChain.doFilter(request, response);
}
Can anyone tell me what am i doing wrong... why is sendredirect not responding
Maybe this solution will be proper for your needs:
How to redirect to index page if session time out happened in jsf application
if you need perform some action on session timeout you can also create #Destory annotated method on session statefull bean.

JSF page style missing when using login filter

I am using following filter to control access to all pages in JSF 2.0 using GlassFish as application server. The problem is that with this code although filter works fine and user are redirected to log.xhtml if they try to acess anyother page directly but the login.xhtml does not look good (no colored image displayed and while page shape changed) as it should be. However if i remove the sendRedirect statement and replace it with chain.doFilter statement, then the page displays in the same way as it should be looking nice and good however filtering does not work obviously. How can I fix this problem?
LoggingFilter.java
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
HttpServletRequest req = (HttpServletRequest) request;
LoginBean auth = (LoginBean) req.getSession().getAttribute("loginBean");
if ((auth != null && auth.isLoggedIn()) || req.getRequestURI().endsWith("/login.xhtml")) {
// User is logged in, so just continue request.
HttpServletResponse httpResponse = (HttpServletResponse)response;
httpResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
httpResponse.setHeader("Pragma", "no-cache"); // HTTP 1.0.
httpResponse.setDateHeader("Expires", 0); // Proxies.
chain.doFilter(request, response);
} else {
// User is not logged in, so redirect to index.
HttpServletResponse res = (HttpServletResponse) response;
res.sendRedirect(req.getContextPath() + "/faces/login.xhtml");
//FacesContext.getCurrentInstance().getExternalContext().dispatch("/login.xhtml");
//chain.doFilter(request, response);
}
}
This filter also redirects all requests on CSS/JS/image files to the login page. The browser end up getting a response containing some HTML code representing the login page instead of the concrete CSS/JS/image content it requested for and hence the browser fails applying the necessary look'n'feel.
Provided that you're 100% utilizing JSF resource management (<h:outputStylesheet>, etc) and thus they are all covered by /javax.faces.resource/* URIs, rewrite your filter as follows:
#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);
LoginBean auth = (session != null) ? session.getAttribute("loginBean") : null;
String loginURL = request.getContextPath() + "/faces/login.xhtml";
boolean loggedIn = auth != null && auth.isLoggedIn();
boolean loginRequest = request.getRequestURI().equals(loginURL);
boolean resourceRequest = request.getRequestURI().startsWith(request.getContextPath() + "/faces" + ResourceHandler.RESOURCE_IDENTIFIER);
if (loggedIn || loginRequest || resourceRequest)) {
if (!resourceRequest) {
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(request, response);
} else {
response.sendRedirect(loginURL);
}
}
Note that no-cache headers should not be set on resource requests, otherwise you defeat the benefit of the browser cache on CSS/JS/image files.

How to restrict access if user is not logged in

My project has a template main.xhtml and three views login.xhtml, dashboard.xhtml, new.xhtml. Once I login in login.xhtml, the LoginBean will validate and if successful, then it will take to dashboard.xhtml. If user need to create an new record he click the new button which takes to new.xhtml.
But the problem is, if dashboard.xhtml is requested directly from browser, then it is working without login. Do I need to check every view that the user is logged in? How can I achieve this?
It sounds like as if you're homegrowing authentication. In that case, you need to also homegrow access restriction. That is normally to be done using a servlet filter.
Assuming that you're logging in as follows in a #RequestScoped bean,
public String login() {
User user = userService.find(username, password);
FacesContext context = FacesContext.getCurrentInstance();
if (user != null) {
context.getExternalContext().getSessionMap().put("user", user);
return "dashboard.xhtml?faces-redirect=true";
} else {
context.addMessage(null, new FacesMessage("Unknown login, try again."));
return null;
}
}
Then you can check for the logged-in user in a #WebFilter("/*") filter as follows:
#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);
User user = (session != null) ? session.getAttribute("user") : null;
String loginURL = request.getContextPath() + "/login.xhtml";
boolean loginRequest = request.getRequestURI().startsWith(loginURL);
boolean resourceRequest = request.getRequestURI().startsWith(request.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER);
if (user != null || loginRequest || resourceRequest)) {
chain.doFilter(request, response);
} else {
response.sendRedirect(loginURL);
}
}
Note thus that this would continue the request when the user is logged in, or when the login page itself is requested directly, or when a JSF resource (CSS/JS/image) is been requested.
If you were using container managed authentication, then the filter would have been unnecessary. See also How to handle authentication/authorization with users in a database?

How to use HttpServletRequest#login() programmatic login with SHA-256 configured security realm

i have read there, i am using glassfish 3.1.1 security realm configured with sha-256 digest algorithm. is there any tutorial about this ? maybe i am blethering, i am trying to login with this code:
public void login() throws NoSuchAlgorithmException {
FacesContext context = FacesContext.getCurrentInstance();
HttpServletRequest request = (HttpServletRequest)context.getExternalContext().getRequest();
EntityManager em = emf.createEntityManager();
boolean committed = false;
try {
FacesMessage msg = null;
EntityTransaction entr = em.getTransaction();
entr.begin();
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(password.getBytes());
byte byteData[] = md.digest();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < byteData.length; i++) {
sb.append(Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1));
}
password = sb.toString();
Query query = em.createQuery("SELECT COUNT(u) FROM EntityUser u WHERE u.userName = :userName AND u.password = :password")
.setParameter("userName", userName).setParameter("password", password);
long result = (long)query.getSingleResult();
if (result == 1) {
request.login(userName, password);
msg = new FacesMessage();
msg.setSeverity(FacesMessage.SEVERITY_INFO);
msg.setSummary("You are logged in");
}
entr.commit();
committed = true;
} catch (ServletException e) {
context.addMessage(null, new FacesMessage("wrong username or password"));
}
finally {
if (!committed) entr.rollback();
}
} finally {
em.close();
}
}
result variable returns 1, but request.login(userName, password); method in if condition always throws servletexception.
Can you post the exception stacktrace? That way it would be easier to understand the source of the exception. But judging from your currently supplied code, you should supply in
request.login(userName, password);
the password as the plain-text password and not the hashed password.
Interface HttpServletRequest
ServletException - if the configured login mechanism does not support username password
authentication, or if a non-null caller identity had already been established (prior to
the call to login), or if validation of the provided username and password fails.
There can be a lot of reasons that login fails. You've just checked if appropriate user and password are in table. Glassfish makes two queries - in authenticate process - to two tables. One to table specified as userTable, and second to groupTable which are determined in security realm definition. Check if web.xml and glassfish-web.xml are correct too.
the questioned problem is whole about method
request.login(userName, password);
Author made everything right, even his own authentication way of working with users database, but request.login needs for authentication realm be set up, to be used by this method. And you have your own, you dont need separate request.login authentication. For the case you need it - thats how you do it jdbc-realm-setup-with-glassfish-v3
So, after you get the result=1, you set up your context.getExternalContext().getSessionMap().put("user", u);
and send redirection context.getExternalContext().redirect(context.getExternalContext().getRequestContextPath() + "какой-то модуль.xhtml");
and use webfilter to block access to /Pages/*.xhtml without logging in.
#WebFilter("/Pages/*")
public class LoggingFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest)request;
HttpServletResponse res = (HttpServletResponse)response;
User user = (User) req.getSession().getAttribute("user");
if(user != null){
chain.doFilter(request,response);
}
else res.sendRedirect(req.getContextPath()+"/запрос_учетных_данных.xhtml");
}
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void destroy() {
}
}

Resources