I am testing forum PhpBB with help of HTML unit. I want to add message in one of topic of PhpBB forum. I enter the message in textarea and click the submit button, but new page doesn't have my message. What seems to be the problem?
final ArrayList<HtmlForm> formList=(ArrayList<HtmlForm>) page.getByXPath("//form[#id='postform']");
final HtmlTextArea myMessage=formList.get(0).getTextAreaByName("message");
myMessage.type("text");
final HtmlSubmitInput submit_post = formList.get(0).getInputByName("post");
page=submit_post.click();
if (page.asText().contains("text")) {
System.out.println("right");
}
Thank you for help!
One way around this is to construct a custom http post request.
Use FIddler to capture the traffic and then replicate it with HTMLUnit. It should look something like below
public Page postMessage() throws Exception
{
URL url = new URL("YOURURL");
WebRequest requestSettings = new WebRequest(url, HttpMethod.POST);
requestSettings.setAdditionalHeader("Accept", "*/*");
requestSettings.setAdditionalHeader("Content-Type", "application/x-www-form-urlencoded");
requestSettings.setAdditionalHeader("Referer", "REFERER");
requestSettings.setAdditionalHeader("Accept-Language", "en-US,en;q=0.8");
requestSettings.setAdditionalHeader("Accept-Encoding", "gzip,deflate,sdch");
requestSettings
.setRequestBody("YOURPOSTREQUEST");
Page page = webClient.getPage(requestSettings);
return page;
}
Related
I tried to login in some sites with HtmlUnit with this code:
HtmlPage page1 = webClient.getPage("https://somesites.com/");
HtmlForm form = (HtmlForm) page1.getElementById("FormLogin");
HtmlInput name = form.getInputByName("user_name");
name.setValueAttribute("my_password");
HtmlInput password = form.getInputByName("password");
password.setValueAttribute("my_password");
HtmlButton button = (HtmlButton) page1.getElementById("btnX");
HtmlPage page2 = button.click();
And this sites using ajax to show its data. But this ajax call can not be accomplish if login not succeeded. In chrome browser I can do this by typing in address bar like https://somesites.com/success/site.json so If I delete some cookies variable this never return any result.
My question was, how to make ajax call that maintain browser session after login success?
First of all, you want to set a AjaxHandler for your Webclient
webClient.setAjaxController(new AjaxController(){
#Override
public boolean processSynchron(HtmlPage page, WebRequest request, boolean async)
{
return true;
}
});
then, also make sure that the cookies are being stored (note that this should only be necessary if you need to initialize a new WebClient with old Cookies):
CookieManager cookieManager = new CookieManager();
webClient.setCookieManager(cookieManager);
Now you have a WebClient which stores your Cookies. Do your working login, and then simply execute the ajax call via Javascript:
page.executeJavaScript("[ajax call]").getJavaScriptResult();
If you only want to access the json data, you can simply navigate to the url and get the text. IF you are successfully logged in, it will work:
HtmlPage jsonPage = webClient.getPage("https://somesites.com/success/site.json ");
System.out.println(jsonPage.asText());
From there on you can parse it as JSON or do whatever you need to do with it.
In Spring I usually did a redirect-after-submit(get method mapping) to prevent the user of submitting a form ,
but when i pressing F5 it will go to get method mapping again and display me this kind of confirm message. how could i prevent this message every time on F5.
Here is the code for controller -
ScheduleDetail objScheduleDetail = new ScheduleDetail();
HttpSession session = request.getSession(true);
String condition = "";
try{
int careProfessionalIDF = (Integer) session.getAttribute("careProfessionalIDF");
condition = "CareProfessionalIDF = "+careProfessionalIDF;
objScheduleDetail.setCareProfessionalIDF(careProfessionalIDF);
}catch (Exception e) {
int careProviderIDF = (Integer) session.getAttribute("careProviderIDF");
condition = "CareProviderIDF = "+careProviderIDF;
objScheduleDetail.setCareProviderIDF(careProviderIDF);
}
List<ScheduleDetail> ScheduleDetailList = objScheduleDetailManager.getAllScheduleDetail(condition+" ORDER BY ScheduleDetailIDP DESC");
model.addObject("List_of_ScheduleDetail",ScheduleDetailList);
model.addAttribute("ScheduleDetail", objScheduleDetail);
return "hospital/scheduleDetail";//jsp page
edited code
#RequestMapping("/editAddressType.html")
public String editAddressType(ModelMap model,HttpServletRequest request)
{
int addressTypeIDP = Integer.parseInt(request.getParameter("AddressTypeIDP"));
AddressType objAddressType = new AddressType();
objAddressType = objAddressTypeManager.getByID(addressTypeIDP);
model.addAttribute("AddressType", objAddressType);
return "jsp/addressType";
it open addressType.jsp with data tht we bind with `model.addAttribute`. now if i press F5 it show alert message as above image.
**get method**
#RequestMapping(value="/getAddressType.html", method=RequestMethod.GET)
public String getAddressType(ModelMap model, HttpServletRequest request) throws RemoteException
{
AddressType objAddressType = new AddressType();
model.addAttribute("AddressType", objAddressType);
return "hospital/addressType";
}
If you implement the POST - REDIRECT - GET pattern correctly, you will not see the warning from the browser that you mentioned. The warning is shown when the Page being viewed is in response to a POST request. The traditional pattern, FORM - POST - SUCCESS page.
The code you provided in the question is not enough to reach the root cause of the problem. I'm listing key points of the implementation here, please compare with your code and you'll understand what the mistake is.
To show the user the form, where they are supposed to enter data for submission. (Just the starting point, could be any page in your application.)
#RequestMapping(value = "/checkout/{cartId}.htm", method = RequestMethod.GET)
public ModelAndView showCheckoutForm(...) {
......
return new ModelAndView("/WEB-INF/jsp/form.jsp")
}
The form POSTs to a handler method, which issues a redirect to the user, pointing to a URL that will show the details of the resource created as a result of the POST.
#RequestMapping(value = "/checkout/{cartId}.htm", method = RequestMethod.POST)
public View submitCheckoutForm(....) {
return new RedirectView("/checkout/confirmation/" + cartId + ".htm");
}
The details of the created resource will be shown by a handler method like the following. Note that at this point, if your implementation worked properly, the URL in the user's browser will change to the path redirected by the POST handler. And a fresh GET request will be issued to the server.
#RequestMapping(value = "/checkout/confirmation/{cartId}.htm", method = RequestMethod.GET)
public ModelAndView showCheckoutConfirmation(....) {
return new ModelAndView("viewThatShowsCheckoutConfirmation");
}
If your implementation is similar, the confirmation page is a result of a GET request, so browsers won't issue a warning for re-POSTing data if you refresh the page.
My suspicion is that your POST handler is not issuing a redirect to the user, it is instead rendering the confirmation page itself.
Hope this helps. Please let me know if this does not solve your problem.
I have a mailing campaign where all links include google analytics tracking code such as:
http://example.com/account/somePage.html?utm_source=example&utm_medium=email&utm_campaign=reminder
The context /account/** is protected via Spring security and once the user clicks on the link on the email, he is re-directed to login BEFORE actually seeing somePage.html. This way the first page that is displayed is something like /login.do which does not have the analytics tracking code. Therefore google does not track my source, medium and campaign parameters.
Any ideas how to solve?
Based on http://support.google.com/analytics/answer/1009614?hl=en , I updated my LoginController that shows the login page to redirect to /login?GOOGLE_PARAMATERS:
private static final String ALREADY_REDIRECTED = "ALREADY_REDIRECTED";
....
#RequestMapping(value = "/login", method = RequestMethod.GET)
public ModelAndView loginView(HttpServletRequest request, HttpServletResponse response){
....
Boolean alreadyRedirected = (Boolean) request.getSession().getAttribute(ALREADY_REDIRECTED);
if (alreadyRedirected==null){
SavedRequest savedRequest = new HttpSessionRequestCache().getRequest(request, response);
if (savedRequest!=null){
String source[] = savedRequest.getParameterValues("utm_source");
if (source!=null && source.length>0){
// we need to redirect with login instead
String mediums[] = savedRequest.getParameterValues("utm_medium");
String medium = mediums.length==0 ? "" : mediums[0];
String campaigns[] = savedRequest.getParameterValues("utm_campaign");
String campaign = campaigns.length==0 ? "" : campaigns[0];
String redirect = "redirect:/login?utm_source=" + source[0] + "&utm_medium=" + medium + "&utm_campaign=" + campaign;
mav.setViewName(redirect);
// mark not to do twice
request.getSession().setAttribute(ALREADY_REDIRECTED, new Boolean(true));
return mav;
}
}
}
We have similar problem and have solved with the next solution.
We have a signup form via Ajax, and in the callback if everything is OK we auto-login the user and lost Google Analytics tracking code for Funnel visualization because of Spring Security session invalidation and set up a new cookie.
What we have done by JS just before auto-login call the new user this
_gaq.push(['_trackPageview', '/signupDone']);
https://gist.github.com/moskinson/5418938
signupDone is a fake url that does not exists.
This way GA receive a call of a new url is loaded and we can track the funnel!
http://packageprogrammer.wordpress.com/2013/04/19/seguimiento-con-google-analytics-a-traves-del-login-con-spring-security/
I'm trying to login to Facebook page using HtmlUnit and view its HTML content. I'm trying to fill up the login credentials through HtmlUnit but I don't see the session being carried when the submit button is clicked.
Couldnt find much content on htmlunit session management classes. I have also attached the code that I'm currently using to attempt this problem. Any help appreciated!
WebClient webClient = new WebClient();
HtmlPage page1 = webClient.getPage("https://www.facebook.com");
List<HtmlForm> listF = page1.getForms();
HtmlForm form = null;
for(int i=0; i<listF.size(); i++)
{
if(listF.get(i).getId().equals("login_form"))
{
form = listF.get(i);
}
}
HtmlTextInput uName = form.getInputByName("email");
HtmlPasswordInput passWord = form.getInputByName("pass");
HtmlSubmitInput button = form.getInputByValue("Log In");
uName.setValueAttribute(FACEBOOK_UNAME);
passWord.setValueAttribute(FACEBOOK_PASS);
HtmlPage page2 = button.click();
Found the answer. Just enabled cookies before starting to get webpages. It works.
Added the below piece of code
WebClient webClient = new WebClient();
CookieManager cookieMan = new CookieManager();
cookieMan = webClient.getCookieManager();
cookieMan.setCookiesEnabled(true);
Another advice is if you are trying to restore HTTP session in HtmlUnit, instead of using webClient.getCookieManager().addCookie(cookie);, use this instead :
webClient.addCookie("cookieName=cookieValue", URL, null);
I'm having a problem using Winnovatives PDFConverter on pages that are protected by Extranet security (which is based on ASP.Net Membership).
I've tried several different approaches, but the following I can get to work on my local machine, but not anywhere else.
Code for login page, this code should bypass the login process for:
// check that the current "user" isn't logged in and is the Winnovative UserAgent
if (!Sitecore.Context.IsLoggedIn && Request.UserAgent.Contains(".NET CLR"))
{
//Login with a dummy user I've created
Sitecore.Security.Authentication.AuthenticationManager.Login("extranet\\pdf", "pdf", true);
//redirect to former page
}
The page that generates the PDF uses this code:
private void PDFPrint(string url)
{
PdfConverter pdfConverter = new PdfConverter();
pdfConverter.LicenseKey = "our license";
url = Request.Url.Scheme + "://" + Request.Url.Host + url;
byte[] downloadBytes = pdfConverter.GetPdfFromUrlBytes(url);
HttpResponse response = HttpContext.Current.Response;
response.Clear();
response.AddHeader("Content-Type", "binary/octet-stream");
response.AddHeader("Content-Disposition", "attachment; filename=" + Sitecore.Context.Item.Name + ".pdf" + "; size=" + downloadBytes.Length.ToString());
response.Flush();
response.BinaryWrite(downloadBytes);
response.Flush();
response.End();
}
The Exception I'm getting is this:
"Could not get the metafile from url. Could not get image from url.The URL is not accessible.."
I've also tried this trick from the Winnovative FAQ to no avail:
http://www.winnovative-software.com/FAQ.aspx#authenticationQ
I've also tried to use WebClient or HttpWebRequest to retrieve the content.
But nothing I do seems to work other than locally.
Basically I want to create a way of either getting Winnovatives converter to use the current logged in user, my custom "pdf" user og some other way of getting the html from the response.
I hope this question isn't too vague, but I find it kinda hard to ask. But basically I want to get some html content from a page on a Sitecore solution I control, which is protected by Sitecore normal Extranet security. This html content should be in string or byte[] format.
Help me Stackoverflowers, you're my only hope! :P
I contacted Sitecore to ask if they had a solution.
Their solution was to create a Processor that would set an active user based on some criteria.
This is the code I made for my site (it's probably not the best solution as UserAgent can be spoofed):
public class MyResolver : HttpRequestProcessor
{
// Methods
public override void Process(HttpRequestArgs args)
{
var userAgent = args.Context.Request.UserAgent ?? "";
SiteContext site = Sitecore.Context.Site;
if (site.Name == "site_name_in_webconfig" && userAgent.Contains("this_should_only_be_in_thepdfcreators_userAgent"))
{
Sitecore.Security.Accounts.User pdfuser = Sitecore.Security.Accounts.User.FromName("extranet\\theUser", true);
AuthenticationManager.SetActiveUser(pdfuser);
}
}
}
and then add the following to the web.config, before the UserResolver:
<processor type="Namespace.MyResolver, Assembly" />
I hope this will help some others out there.
I've found a similar issue on the ASP.NET forums and the answer to that was to use a newer version of the PDF tool: SessionState Problems ?