Bypass login filter for 1 time when user chose continue as guest - jsf

I have a booking page with URL /booking/Create.jsf. I have a filter for URL pattern /booking/* so the user is asked to login on the page /login/signin.jsf before being taken to Create.jsf. But I have a button "Continue as guest" so that user that is not registered can create a booking on Create.jsf page without log-in. How can I make that happen. Any help will be appreciated. My filter looks like
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
UserLoginController loginController = (UserLoginController) req.getSession().getAttribute("userLoginController");
if(loginController != null && loginController.isLoggedIn()){
chain.doFilter(request, response);
}
else{
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
httpServletResponse.sendRedirect(req.getContextPath() + "/login/signin.jsf");
}
}

The page create.jsf is considered in the end as public page. So, in order to enable the filter for other pages concerning "booking", just create a new subfolder named for example "user" inside which you should put others pages of "booking", the new url pattern of the filter will be as a result: /booking/user/*. This way, the other stuff of booking remains safe and the page /booking/create.jsf will be easily available for the users and guests because it's not covered by the filter.

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 SessionScoped only allow to connect from one account to a web page

I am developing a JSF application where 3 kind of users(1, 2,3) can login using an id and when they login the access to different 3 menus(Menuuser1, Menuuser2, Menuuser2) depending on what kind of users they are. Each time an user logins I store its id in an attibute in a sessionscope attribute.
I want that if an user of type 1 logins and he open another tab in the browser he is redirected to the menuuser1 and cannot login from the same computer as an user of type 2.
How could I do that?
You can perform authentication in filter , you can check the role of the user in filter class, if given role is user1, it will forward the request to the Menuuser1 else if it's the user2 then forward to Menuuser2 and so on ...
Example
public class ControlRole implements Filter{
public void init(FilterConfig arg0) throws ServletException {}
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpSession session = request.getSession(false);
User user = (session != null) ? session.getAttribute("user") : null;
if(user.getRole().getName().equals("user1")){
chain.doFilter(req, resp);//sends request to next resource
}
else if(user.getRole().getName().equals("user2")){
// ......
}
else{
oresponse.sendRedirect(request.getContextPath() + "/login");
}
And for "If an user with rol1 logins from its computer, he will not be able to login from the same computer as an user with rol2 while he is loged as user with rol1" this is automatically done by the sessionScope

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.

Homegrown authentication filter does not show the welcome page

So I've come accross quite a numbre of questions similar to mine, and I was starting to get it until I realised I don't, in short, here's the story :
In an authentification bean, success of authentification should result in accessing some web resources, failure should "filter" access and redirect to current login page.
Now, in that authentification bean, I added this line in case of success :
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(authentificationBean1.AUTH_STATE, "true") ;
AUTH_STATE is defined in the bean as :
public static final String AUTH_STATE = "";
In case of failure, I do the following :
FacesContext.getCurrentInstance().getExternalContext().getSessionMap().put(authentificationBean1.AUTH_STATE, null) ;
Now in the filter (one that is applied to every file except of authentification page), my doFilter method looks like this :
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
if (((HttpServletRequest) request).getSession().getAttribute(authentificationBean1.AUTH_STATE) == null) {
((HttpServletResponse) response).sendRedirect("authentification.xhtml");
}
if(((HttpServletRequest) request).getSession().getAttribute(authentificationBean1.AUTH_STATE) != null) {
((HttpServletResponse) response).sendRedirect("accueil.xhtml");
}
}
My idea was that if authentification went well, the authentificationBean1.AUTH_STATE session attribut will be set to something not null, thus in the filter test I'll be able to redirect to a welcom page (accueil.xhtml) ; if that attribut is null, we'll stay in the authentification page.
Tasting the whole thing : the filter seems to work but too much, by that I mean even when authentification test must succeed it doesn't allow me to pass to the welcome page. It was actually working fine without the filter, it looks like I missed something about using filters with JSF or filters as it.
P.S : didn't apply chain.doFilter because I do not have another filter to call, but suspecting something there.
Thanks for your indications.
EDIT :
<filter>
<filter-name>RestrictionFilter</filter-name>
<filter-class>beans.RestrictionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>RestrictionFilter</filter-name>
<url-pattern>/faces/accueil.xhtml</url-pattern>
</filter-mapping>
Your filter is running in an infinite loop, redirecting to itself everytime. It is never continuing the request to the servlet. It seems that you're misunderstood how HTTP works. With response.sendRedirect() you're basically firing a brand new HTTP request. This brand new HTTP request will invoke the filter again. So, when your filter matches the condition in order to redirect to accueil.xhtml, it will keep redirecting to that page in an infinite loop and never continue to the servlet in order to process the request.
Further you also misunderstood the meaning of chain.doFilter(). It does not explicitly advance to the next filter. It just continues the request as if there was no filter. Whether there's another filter next in the chain or not is completely irrelevant. If there's no filter, then it will just end up in the target servlet (which is the FacesServlet in your case, who's responsible for processing the JSF page).
Basically, the flow should be as follows:
If the user is not logged in, then:
If the currently requested page is not authentification.xhtml, then redirect to it.
Or if the currently requested page is already authentification.xhtml, then continue request.
Or if the user is logged in, then continue the request regardless of the requested page.
In other words, this should do it:
#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() + "/authentification.xhtml";
boolean loggedIn = session != null && session.getAttribute(authentificationBean1.AUTH_STATE) != null;
boolean loginRequest = request.getRequestURI().startsWith(loginURL);
boolean resourceRequest = request.getRequestURI().startsWith(request.getContextPath() + ResourceHandler.RESOURCE_IDENTIFIER);
if (loggedIn || loginRequest || resourceRequest)) {
chain.doFilter(request, response);
} else {
response.sendRedirect(loginURL);
}
}
Note that I also added a check on JSF resources (the CSS/JS/image files included via <h:outputStylesheet|outputScript|graphicImage>), otherwise they would also be blocked when the login page is presented. Also note that this filter can be mapped on /* and not on only a single page.

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?

Resources