Faces in ADF can't get the request parameters - jsf

I have an ADF web application with Faces 1.2
In my managed bean I am trying to access the parameters of the post request, but always getting null.
This is my post form that I am posting to the Faces:
<form name="input" action="http://127.0.01:7072/myapplication/faces/login.jspx" method="post">
<input type="hidden" name="user" id="user" value="myUserName"/>
<input type="submit" value="Submit"/>
</form>
FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("user");
FacesContext.getCurrentInstance().getExternalContext().getRequest().getParameter("user");
But I always get null and the method of the form I get is: GET, strange!

when you make a request for a URL like:
http://server/faces/somepage.jspx
ADF framework respone you by a "HTTP Error 302 Moved temporarily" response and redirect you to the URL like :
http://server/faces/somepage.jspx?_adf.ctrl-state=888888&_afrLoop=9999999
so your first POST request is omit and browser send an other request to the new URL that ADF returned in response, so because POST method send parameter in the request body the browser dont resend them in new Get request
so i think there is no way for you to get parameters direcly in side the ADF page ! :(
but i think the best way is to create a Servlet and get you param in it and put them to session and then redirect the user from servlet to your ADF page :)

I managed reading the request parameters through including my parsing operations in the filter mappings that my application was using.
In a very abnormal way FacesContext always rejected revealing the current parameters, till now it's a mystery for me why it's designed liked that, even through its external context ...

Related

JSF inputFile Refused to display 'mypage.xhtml' in a frame because it set 'X-Frame-Options' to 'deny'

I was following this answer by BalusC to try and upload a file to the server. I am using his code as-is.
When using JSF 2.2, the #{bean.save} was never reached, and the file was never saved.
The server's console showed nothing. But the js console showed this error:
Refused to display 'http://localhost:8080/my_app/hello.xhtml' in a frame because it set 'X-Frame-Options' to 'deny'.
jsf.js.xhtml?ln=javax.faces:1 Uncaught DOMException: Blocked a frame with origin "http://localhost:8080" from accessing a cross-origin frame.
at FrameTransport.callback (http://localhost:8080/my_app/javax.faces.resource/jsf.js.xhtml?ln=javax.faces:1:5109)
at HTMLIFrameElement.<anonymous> (http://localhost:8080/my_app/javax.faces.resource/jsf.js.xhtml?ln=javax.faces:1:5759)
I saw this answer which suggested it was a bug in JSF 2.2. So I uploaded to 2.3.
With JSF 2.3 the #{bean.save} is reached, and the file is successfully saved. But the js error remains, and I can't upload a second file.
Any ideas?
EDIT in case it helps: I don't know why, but after selecting the file to upload in the dialog, an <iframe> is added to my page somehow.
EDIT 2
BalusC and Selaron suggested I try to change the X-Frame-Options header to not 'DENY'. I tried adding a #WebFilter and setting the header there, like this:
public void doFilter(...)
{
HttpServletResponse response = (HttpServletResponse) res;
response.addHeader("X-Frame-Options", "sameorigin");
response.setHeader("MyHeader", "whatever");
chain.doFilter(req, res);
}
I added a second header MyHeader with value "whatever" to check if the response contained that header when getting to the browser.
Turns out MyHeader gets to the browser correctly, but X-Frame-Options still remains as 'DENY'.
As I'm using Spring Security, I figured maybe there was some other filter messing with my response?
So, I have this:
#Configuration
#EnableWebSecurity
public class BasicConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
...
http.addFilterAfter(
new CustomFilter(), SwitchUserFilter.class);
...
}
}
My CustomFilter works as the previous one I showed: MyHeader remains, but X-Frame-Options does not.
I added it after SwitchUserFilter because the doc for HttpSecurity.addFilter says that is the last filter in the chain.
I am a bit lost now. My couple of questions:
Am I right to assume the X-Frame-Options header is getting overwritten by some other filter?
How could I ensure the X-Frame-Options I set remains? Or, how can I put my filter at the end of the chain?
I found this issue where the Mojarra team planned to Implement "ajax" file upload #2577 and the commit actually implementing it to the jsf javascript.
Madly the documentation on issue 2577 are not accessible anymore and thus it does not explain the background on why an iframe is needed here.
The first passage of this blog gives a brief explanation on why AJAX file upload is/was(?) not possible directly:
Ajax Style File Uploading using Hidden iFrame
by Viral Patel · November 18, 2008
File uploading using AJAX is not possible. AJAX doesn’t actually post
forms to the server, it sends selected data to the server in the form
of a POST or GET request. As javascript is not capable of grabbing the
file from the users machine and sending it to the server, it’s just
not possible with AJAX. You have to resort to regular old form submit.
If you have read/seen it somewhere, then it is not through AJAX. File
uploading occurs through an iframe in this case. You have to use a
iframe to upload the files. So, you can use iframe to asynchronous
upload (Like AJAX , but its not AJAX).
So finally your options are to either - as BalusC commented - relax your X-Frame-Options header setting or to change your upload to not use AJAX:
<h:form enctype="multipart/form-data">
<h:inputFile value="#{bean.file}" />
<h:commandButton value="upload" action="#{bean.save}"/>
</h:form>

JMeter Office360 online : JavaScript required to sign in error while authorization

When I try to login on sharepoint360 online site using JMeter, it gives JavaScript required to sign in error in response. I got below code in response.
<html>
<head>
<noscript>JavaScript required to sign in</noscript>
<title>Continue</title>
<script type="text/javascript">
function OnBack() {}
function DoSubmit() {
var subt = false;
if (!subt) {
subt = true;
document.fmHF.submit();
}
}
</script>
</head>
<body onload="javascript:DoSubmit();">
<form name="fmHF" id="fmHF" action="https://ApplicationURL.sharepoint.com/_forms/default.aspx?apr=1&wa=wsignin1.0" method="post" target="_self">
<input type="hidden" name="t" id="t" value="EgBZAgMAAAAEgAAAAwABJaEZDRmSdbQKqL6rJyYKAN1Z0valM74LOhnXMHkbILiqeyEyWkHmbZ3hVG8XvpXOVLvlnylOzhJx8KQgSsuO0d6P2quRRU168QMumuqH/qvLVkpZ5mPiBDDyI8l1z+E4++pxZ3H37uIevfjckj40rTlGYJ85aT0/nxcqDxlL6pxKStDm9GKNI81ypsDKv7dMEqg9lRDjJO5qmNEDiCP8jPB3WWke5pVqcn6c1MbnbHzKU2uHzekZqjxAflfvWu5LS9R+N6jciFZvicn8P0EV0LZHqmjXgUsoVMdn9gGemJYnQCoIbkk7Oo9DPaqXRsxApY5sqCwotEJvZ45AaBNAQkgBYABIAQAAAxBYNSeVFbxuVhW8blZOoQcACgAgAAAhAGtrQHNmd3Byb2R1Y3RkZXYub25taWNyb3NvZnQuY29tAGMAAC1rayVzZndwcm9kdWN0ZGV2Lm9ubWljcm9zb2Z0LmNvbUBwYXNzcG9ydC5jb20AAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAB0t1bGRlZXAABUt1bWFyAAAAACAAAAAAAAAAAAD//////////wAAFbxuVpUsb1YAAAAAAAAAAAAAAAANADEyMy42My42NS42NgAAAAAAAAAAAAAAAAAAAQAAAQAAAQAAAQAAAADU1N9WAQAAAQAAAAAAAAAAAAAAAAAANwBodHRwczovL3BvcnRhbC5taWNyb3NvZnRvbmxpbmUuY29tL0NoYW5nZVBhc3N3b3JkLmFzcHgA/////wAAAAAAAA==">
</form>
</body>
Thanks in advance.
Sunil
As per Apache JMeter Homepage
JMeter does not perform all the actions supported by browsers. In particular, JMeter does not execute the Javascript found in HTML pages. Nor does it render the HTML pages as a browser does
You need to extract the "value" attribute of that "t" hidden input and pass it along with other request parameters. I would recommend using CSS/JQuery Extractor or XPath Extractor for this.
Relevant configurations:
CSS/JQuery Extractor
Reference Name: anything meaningful, i.e. t
CSS/JQuery Expression: input[id=t]
Attribute: value
XPath Extractor
Use Tidy - check. If response is XHTML compliant it is not required however.
Reference Name: again, any JMeter Variable name, i.e. t
XPath Expression: //input[#id='t']/#value
Refer the extracted value as ${t} where required
Handle any other dynamic parameters similarly and you should be good to go. JMeter doesn't execute JavaScript but it can capture and execute JavaScript-driven HTTP requests. Given you perform load testing you shouldn't worry about what is happened in browser as JavaScript is being executed on client side only. See ASP.NET Login Testing with JMeter article for more detailed explanation and instructions.
Looking at how sharepoint authentication works, I believe you need to implement authentication using HTTP Request, instead of using login page, as explained here. Basically you will need 2 HTTP requests: first to extract the SAML token, and second to receive authentication cookies, which you can then use in the following HTTP requests, as you normally do.

How to submit xml data to a web site?

I am using a third party to process transactions. They have an api that says XML content should submitted via an HTTP POST variable named “XML”.
I know how to create the xml, but not sure how to post it to their site. They have a destination url. Can you tell me how to do the Post to their site?
You need to carefully check. Usually you just post XML to an URL. However in this case (indicated by the variable name) it seems that a (typically only used for html forms) form post is needed.
The easiest way is to create a html form with that one field, something like this:
<form method="post" action="http://their url" name="payload">
<input type="hidden" id="XML" name="XML" />
</form>
Then you can fill the field with your XML and do a payload.submit()
Let us know how it goes

How to programmatically send POST request to JSF page without using HTML form?

I have very simple JSF bean like shown below:
import org.jboss.seam.annotations.Name;
#Name(Sample.NAME)
public class Sample {
public static final String NAME="df";
private String text = "text-test";
public void sampleM(){
System.out.println("Test: "+text);
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
And JSF form connected with this component:
<h:form id="sampleForm">
<h:commandButton id="sampleButton" action="#{df.sampleM()}" value="ok" />
</h:form>
Now, I would like to programmatically send POST request to this form.
According to my investigation the key here are POST parameters.
Selected properly gives proper results (String 'Test: text-test' is printed on serwer's console).
So the question is: How should I select POST data that was correct?
JSF form shown above produces this HTML form:
<form id="sampleForm" name="sampleForm" method="post" action="/pages/main/main.smnet" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="sampleForm" value="sampleForm" />
<input id="sampleForm:sampleButton" type="submit" name="sampleForm:sampleButton" value="ok" />
<input type="hidden" name="javax.faces.ViewState" id="javax.faces.ViewState" value="j_id65" autocomplete="off" />
</form>
So these parameters are corrent.
But how can I find out what parameters (name and value) will be sufficient for any other component?
For example: when I send POST data the same like in shown HTML form but with different 'javax.faces.ViewState' parameter value, component method will not be executed.
I understand that you're basically asking how to submit a JSF form programmatically using some HTTP client such as java.net.URLConnection or Apache HttpComponents Client, right?
You need to send a GET request first and make sure that you maintain the same HTTP session (basically, the JSESSIONID cookie) across requests. Let your HTTP client extract the Set-Cookie header from the response of the first GET request, obtain the JSESSIONID cookie from it and send it back as Cookie header of subsequent POST requests. This will maintain the HTTP session in the server side, otherwise JSF will treat it as a "View Expired" which may return either on a decently configured JSF web application a HTTP 500 error page with ViewExpiredException, or on a badly configured JSF web application behave as a page refresh.
As part of JSF's stateful nature and implied CSRF attack prevention, the forms must be submitted with a valid javax.faces.ViewState value as the client has retrieved itself on the initial GET request. You also need to make sure that you send the name=value pair of all other hidden fields and particularly the one of the submit button along as well.
So, if your initial GET request gives you this HTML back
<form id="sampleForm" name="sampleForm" method="post" action="/pages/main/main.smnet" enctype="application/x-www-form-urlencoded">
<input type="hidden" name="sampleForm" value="sampleForm" />
<input id="sampleForm:sampleButton" type="submit" name="sampleForm:sampleButton" value="ok" />
<input type="hidden" name="javax.faces.ViewState" id="javax.faces.ViewState" value="j_id65" autocomplete="off" />
</form>
then you need to parse it (Jsoup may be helpful in this) and extract the following request parameters:
sampleForm=sampleForm
sampleForm:sampleButton=ok
javax.faces.ViewState=j_id65
Finally send a POST request on /pages/main/main.smnet with exactly those request parameters (and the JSESSIONID cookie!). Be careful though, it's possible that a (poor) JSF developer has skipped e.g. id="sampleButton" from the <h:commandButton> and then JSF would autogenerate one which looks like in this format sampleForm:j_id42. You can't hardcode them as the value may change depending on the component's position in the server side tree and you would then really need to parse it out the obtained HTML.
Nonetheless, it's wise to contact the site owner/admin and ask if there isn't a web service API available for the task you had in mind. A decent Java EE website which uses a JSF application for a HTML frontend usually also uses a separate JAX-RS application for a REST frontend. It is much more easy and reliable to extract information via such a web service API than by scraping a HTML document.
See also:
How can i programmatically upload a file to a website? (this also concerns JSF)
How to use java.net.URLConnection to fire and handle HTTP requests

Using Post when doing a sendRedirect

I have a requirement that a jsf page needs to be launched from a custom thin client in user browser (thin client does a http post). Since the jsf page may be invoked multiple times, I use a jsp to redirect to the jsf page with params on url. In jsp I do a session invalidation. The jsp code is below:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<%#page session="true" %>
<%
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma", "no-cache");
session.invalidate();
String outcome = request.getParameter("outcome");
String queryString = "outcome=" + outcome ;
response.sendRedirect("./faces/MyPage.jspx?" + queryString);
%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"></meta>
<title>title here</title>
</head>
<body></body>
</html>
My jsf page uses mutiple drop down items with autoSubmit enabled. I set the params on session when the form first inits and then use it from there when an action button is ultimately clicked by user. Following is the code I use to get the param in jsf backing bean constructor:
FacesContext ctx = getFacesContext();
Map sessionState = ctx.getExternalContext().getSessionMap();
outcome = (String)sessionState.get("outcome");
if(outcome == null) //if not on session, get from url
outcome = (String)JSFUtils.getManagedBeanValue("param.outcome");
This way I can get the param even after multiple autoSubmits of drop downs.
My problem is that I cannot have parameters show up on browser address bar. I need a way so that the parameters can be passed to the jsp page. I cannot post direct to jsp from thin client since I need the jsf page to have a new session each time the client launches user browser. This is imp due to the above code snippet on how I use params in the jsf page.
Is there nay way to use a post when doing a sendRedirect so that I do not have to pass params on url? I cannot use forward since when an autoSubmit fires on jsf page, it causes the browser to refresh the jsp page instead.
Is there any better way to handle the jsf page itself so that I don't have to rely on storing params on session between successive autoSubmit events?
Since you invalidate the session, no, you cannot.
The only way would be putting it in the session scope. Why are you by the way invalidating the session on first request? This makes really no sense.
Unrelated to your actual problem, doing sendRedirect() in a scriptlet instead of a Filter and having a bunch of HTML in the same JSP page is receipt for big trouble. Do not write raw Java code in JSP files, you don't want to have that. Java code belongs in Java classes. Use taglibs/EL in JSP only.
No. Because sendRedirect send the web-browser/client a 302 with the new location and according to the following it will usually be a GET, no matter what the original request was.
According to HTTP/1.1 RFC 2616 http://www.ietf.org/rfc/rfc2616.txt:
If the 302 status code is received in response to a request other
than GET or HEAD, **the user agent MUST NOT automatically redirect the
request unless it can be confirmed by the user**, since this might
change the conditions under which the request was issued.
Note: RFC 1945 and RFC 2068 specify that the client is not allowed
to change the method on the redirected request. However, ***most
existing user agent implementations treat 302 as if it were a 303
response, performing a GET on the Location field-value regardless
of the original request method***. The status codes 303 and 307 have
been added for servers that wish to make unambiguously clear which
kind of reaction is expected of the client.
Maybe playing carefully with ajax can get you something.
Update: Then again, as user: BalusC pointed out, you can redirect by manually setting the headers, as in:
response.setStatus(307);
response.setHeader("Location", "http://google.com");

Resources