JSF PhaseListener viewId always one behind - jsf

Im trying to prevent users to access special pages with a phaselistener. for that reason im trying to figure out on which page they try to access.
but my problem is, i only get the page they where before. not the actual page.
public void afterPhase(PhaseEvent event)
{
FacesContext fc = event.getFacesContext();
System.out.println("test1" + fc.getViewRoot().getViewId());
}
and same here
public void afterPhase(PhaseEvent event)
{
FacesContext fc = event.getFacesContext();
HttpServletRequest request = (HttpServletRequest) fc.getExternalContext().getRequest();
String uri = request.getRequestURI();
System.out.println("uri: " + uri);
}
why is that, and how do i get the pagename the user is trying to access? Not that one that they required one step before, or better the page they are coming from.

It is one step behind because that is the way sequence of HTTP POST request behaves. When you are navigating in JSF application via command buttons each request goes as a post request.
Since you are protecting some resources make sure they are accessed via HTTP GET than you will get exact view id, this can be achieved as
User directly hits the url from address bar of browser.
After a post of jsf app redirect it to the resource instead of simple JSF navigation. POST-REDIRECT-GET pattern falls into this have a look here.
If you are showing some messages after each POST, you might need Flash map for that, which is new feature in JSF2, if you are on JSF1.x hard luck, you can implement flash if you want to.
To conclude catch the view ids on HTTP GET request.
Hope this helps...

Related

How do I limit a user from accesing sertain pages in JSF? [duplicate]

This question already has answers here:
How implement a login filter in JSF?
(2 answers)
Closed 2 years ago.
Like the title says, how do I limit users from accessing certain pages in JSF? I have two different kinds of pages that I want to limit access to. The first one is pages that need parameters to load, would it be possible to redirect if a user tries to redirect access that page without any parameters? The second one is pages that only certain users should have access to. In my app you have the ability to create and edit competitions, however, I only want the host of the event to be able to access the edit page for that event - which at the moment anyone can access if they know the right parameters. Is there something in JSF that lets me do this?
General page access
Have a look at #WebFilter and its doFilter method. Inside you can check if your user is logged in retrieving your session scoped bean from the HttpSession.
#WebFilter(filterName = "UserAuthenticationFilter", urlPatterns =
{
"/sites/user/account.xhtml"
} , dispatcherTypes =
{
DispatcherType.FORWARD, DispatcherType.REQUEST, DispatcherType.ERROR
})
public class UserAuthenticationFilter extends HttpFilter
{
#Override
public void doProductionFilter(final HttpServletRequest request, final HttpServletResponse response, final HttpSession session, final FilterChain chain) throws IOException, ServletException
{
final UserBean userBean = session.getAttribute("userBean");
// check if logged in and redirect to login page if not
if (userBean.isLoggedIn()
chain.doFilter(request, response);
else
response.sendRedirect(request.getContextPath() + "/login.xhtml");
}
}
Specific page access
Check your request param either in your #PostConstruct or better in your viewAction or initPreRenderView methods since in the later two you have access to your injected view parameters.
If user does not has sufficient rights to access the data redirect or/and show faces message or do something else.

Injecting a session-scoped bean in JSF2

I'm having some difficulty interacting with a Session-scoped managed bean after a user programmatically logs into my web application.
BACKGROUND:
I have a [javax.enterprise.context.]Session-scoped bean named "SessionHelper" where I place a lot of information gathered from the user as he/she uses the application. In my logon page (which is NOT SessionScoped), Here's a sample of what I'm doing:
#Inject SessionHelper theHelper;
....
FacesContext theContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = theContext.getExternalContext();
HttpServletRequest theRequest = (HttpServletRequest) externalContext.getRequest();
....
theRequest.login(username, password);
....
theSession.method(dostuff);
After this section of code is executed, my application redirects into a protected directory and allows the user (based on roles) to perform their job functions.
When I attempt to "#Inject SessionHelper" into any of my protected resources, my understanding is that I should get the specific SessionScoped instance of SessionHelper that has the data set right after the call to login. This should be available to me for as long as the session (for that specific user) is valid. Unfortunately, the instance I'm getting has none of my "theSession.method(dostuff)" in it.
Am I fundamentally misunderstanding the scope here?
The only thing I could potentially see is that the initial #Inject into my login page is not carried over after the session has been created. If this is the case, is there a way to force a re-injection after the session is created?
As always, thank you very much for your help!!

Writing plain HTML in a JSF based web application

I have this use case in a JSF application.
Supposed in a JSF web application, I have a button that calls an external service that returns a complete HTML response then how can I show that HTML response to my users browsers?
The sequence of events are like this.
In user browser, my application is displayed. A button is there that user can click.
Clicking the button will call an external service. The external service will return information about a certain HTML tags. The HTML is complete with both head/body and with javascript. Currently the service can be implemented thru REST service or a plain DB call then
How can I display that HTML tag in my user browser?
Is this possible to write non-JSF output in a JSF web application?
Just to add, I think my problem is how to write an HTML in my backing bean and write it back to the users browser.
Just write it outright to the HTTP response body whereafter you instruct JSF that the response is manually completed. The principle is not much different from How to provide a file download from a JSF backing bean?, except that you need to set content disposition to inline (which is already the default anyway).
public void writeHtmlResponse() throws IOException {
FacesContext fc = FacesContext.getCurrentInstance();
ExternalContext ec = fc.getExternalContext();
ec.setResponseContentType("text/html;charset=UTF-8");
ec.setResponseCharacterEncoding("UTF-8");
ec.getResponseOutputStream().write(html.getBytes("UTF-8"));
fc.responseComplete(); // Important! Otherwise JSF will attempt to render the response which obviously will fail since it's already written with a file and closed.
}

JSF 2 redirect to HTTPS

I've seen these posts: Issues with JSF navigation rules using redirect on HTTPS, and JSF 2 and Post/Redirect/Get?, but haven't been able to get what I want to do to work. I'm trying to redirect to an https page in my app using ConfigurableNavigationHandler. Here's my handleNavigation:
public void handleNavigation(FacesContext context, String from, String outcome) {
System.out.println("outcome: " + outcome);
if (outcome.startsWith("manageEmail")) {
outcome = "https://localhost:8081/appmonitor/faces/manageEmail.xhtml";
}
System.out.println("outcome: " + outcome);
parent.handleNavigation(context, from, newOutcome);
}
When I click on the link which redirects to "manageEmail", I see that outcome starts as "manageEmail", and changes to my https address, but it doesn't actually redirect there. I suspect it's trying to navigate to http://localhost:8080/appmonitor/faces/https://localhost:8081/appmonitor/faces/manageEmail.xhtml. If this is what is in fact happening, is there any way to override this behavior?
Have you tried accessing the external response and give back a redirect command?
HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
response.sendRedirect(outcome);

JSF 2.0; MyFaces; Form submit only with POST

i've got a security question and i don't know, how to do this in JSF.
In PHP i can react on a form submit that is defined as POST, that i only want values via POST so there is no way to get an value via GET from the same name of the field.
Example:
fieldname in form: username
in my PHP site i can get the value via $_POST["username"] but not with $_GET["username"], because i don't implement the GET way, only POST.
So, now i want this in my JSF site too.
The problem is, that i can't only implement POST for all requests, i must react on GET also.
I only want, that my form data will come via POST to my bean and not via GET.
How can i reach this?
With a filter or something else?
For your interest: i'm not able to use JavaScript in my application.
Thanks a lot!
I'm not sure I understood your question but if you just need to check if a method on your backing bean was invoked using POST or GET you can get that information from the HttpServletRequest object like so :
#ManagedBean(name="myBean")
#ViewScoped
public class MyMBean implements Serializable{
public void handleForm(){
HttpServletRequest req = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
if(req.getMethod().equalsIgnoreCase("POST")){
//Handle your form data
}
}
Just check FacesContext#isPostback().
if (FacesContext.getCurrentInstance().isPostback()) {
// It's a JSF POST request.
}

Resources