How to programmatically log into a website?
Asked Answered
Q

2

0

I have looked at multiple examples on stackoverflow and cannot get it to work.

This is the url I need to log into programmtically:http://powerschool.fortschools.org/public/

I have tried many different ways but am unsuccessfully. Heres what I have currently:

Original Url before logging in: http://powerschool.fortschools.org/public/

Url after logging in: http://powerschool.fortschools.org/guardian/home.html

Form I think is submitted before login:

<form action="/guardian/home.html" method="post" name="LoginForm" target="_top" id="LoginForm" onsubmit="doPCASLogin(this);">
<input type="hidden" name="pstoken" value="308732667SkW2oaVnhxqIqM5PzqdGWrXW4jdQoB8W">
<input type="hidden" name="contextData" value="2AA011214C3F506D76216C5B459574636E2269F51AC438EB11081A7C735345A8">
<input type="hidden" name="dbpw" value="">
<input type="hidden" name="translator_username" value="">
<input type="hidden" name="translator_password" value="">
<input type="hidden" name="translator_ldappassword" value="">

<input type="hidden" name="returnUrl" value="">
<input type="hidden" name="serviceName" value="PS Parent Portal">
<input type="hidden" name="serviceTicket" value="">
<input type="hidden" name="pcasServerUrl" value="/">
<input type="hidden" name="credentialType" value="User Id and Password Credential">

<h2>Parent Sign In</h2>
<!--box content-->
<div id="noscript" class="feedback-alert" style="display: none;"> To sign in to PowerSchool, you must use a browser that supports and has JavaScript enabled. </div>
<fieldset id="login-inputs" class="group">
<div>
  <label>Username</label>
  <input type="text" id="fieldAccount" name="account" value="" size="39">
</div>
<div>
  <label>Password</label>
  <input type="password" name="pw" value="" size="39"><div id="login-help"><a href="/public/account_recovery_begin.html">Having trouble signing in?</a></div>
</div>
<div id="translatorInput" style="display: none;">
  <label>Translator Sign In</label>
  <input type="password" name="translatorpw" value="" size="39">
</div>
<div class="button-row">
  <button type="submit" id="btn-enter" title="Sign In To PowerSchool Parent Access" value="Enter" border="0">Sign In</button>
</div>
</fieldset>       
<!-- box content-->
</form>

After pressing the submit button the form changes to this (only the dbpw changes, (this was two seperate examples so the pstoken and the contextData did change)): Notice how the only thing that changes is the dbpw field

This is after you "fully log in" Data respone headers cookies

Here is my code (not working):

public static final String POWERSCHOOLLOGINURL = "http://powerschool.fortschools.org/public/";
    public static final String POWERSCHOOLLOGIN = "http://powerschool.fortschools.org/guardian/home.html";

    public static void main(String[] args) throws IOException {
        Map<String, String> nameToVal = new HashMap<String, String>();
        nameToVal.put("pstoken", "308732667b2uBDHKHeNJc1XTXdgDSVwxzHfzldM9M");
        nameToVal.put("contextData", "e1c94866f2ed77f3ae37bc1a2a477631");
        nameToVal.put("dbpw", "29e3fdf45f7959a5e0c894ad01b34941");
        nameToVal.put("translator_username", "");
        nameToVal.put("translator_password", "");
        nameToVal.put("translator_ldappassword", "");
        nameToVal.put("returnUrl", "");
        nameToVal.put("serviceName", "PS Parent Portal");
        nameToVal.put("serviceTicket", "");
        nameToVal.put("pcasServerUrl", "/");
        nameToVal.put("credentialType", "User Id and Password Credential");
        nameToVal.put("account", "horvste");
        nameToVal.put("translatorpw", "");
        nameToVal.put("returnUrl", "");
        nameToVal.put("pcasServerUrl", "/");
        nameToVal.put("credentialType", "User Id and Password Credential");
        Map<String, String> cookies = new HashMap<String, String>();
        cookies.put("JSESSIONID", "2C108FB2394FFE097E366BC3C34827B8");
        cookies.put("lastHref",
                "http%3A%2F%2Fpowerschool.fortschools.org%2Fguardian%2Fhome.html");
        cookies.put("uiStateCont", "null");
        cookies.put("uiStateNav", "null");

        Document doc = Jsoup.connect(POWERSCHOOLLOGIN).cookies(cookies)
                .data(nameToVal).method(Method.POST).post();
        System.out.println(doc.toString());

    }

note: HtmlUnit is not an acceptable answer (it's to slow and doesn't work on android).

Quinnquinol answered 13/1, 2014 at 22:37 Comment(4)
Sites with Cross Site Scripting validation will reject this logins.Maxama
What is cross site scripting?Quinnquinol
en.wikipedia.org/wiki/Cross-site_scripting Found it so how do I get around itQuinnquinol
@Maxama Is it because I am copy and pasting session data? Namely the dbpw, contextdata, pstoken, etc. into my code?Quinnquinol
A
0

You'll have to simulate what md5.js (which can be found in the resources tab of dev tools) is doing with the form on submit:

    function doPCASLogin(form) {
   var originalpw = form.pw.value;
   var b64pw = b64_md5(originalpw);
   var hmac_md5pw = hex_hmac_md5(pskey, b64pw)
   form.pw.value = hmac_md5pw;
   form.dbpw.value = hex_hmac_md5(pskey, originalpw.toLowerCase())
   if (form.ldappassword!=null) {
     // LDAP is enabled, so send the clear-text password
     // Customers should have SSL enabled if they are using LDAP
     form.ldappassword.value = originalpw; // Send the unmangled password
   }

   // Translator Login
   var translatorpw = form.translatorpw.value;
   var i = translatorpw.indexOf(";");
    if (i < 0) {
        form.translator_username.value = translatorpw;
        form.translator_password.value = "";
    }
    else {
        form.translator_username.value = translatorpw.substring(0,i);
        translatorpw = translatorpw.substring(i+1); // Get the password
        translatorpw2 = translatorpw;
        translatorpw = b64_md5(translatorpw);                   // Added in move to pcas
        form.translator_password.value = hex_hmac_md5(pskey, translatorpw);
        if (form.translator_ldappassword!=null) {
            // LDAP is enabled, so send the clear-text password
            // Customers should have SSL enabled if they are using LDAP
            form.translator_ldappassword.value = translatorpw2; // Send the pw for LDAP
        }
    }

    return true;
}
Acrosstheboard answered 13/1, 2014 at 22:48 Comment(5)
Is their any easier way? Seems like a lot of work (not laziness but trying to be efficient). How would I simulate this? My password stays constant everytime I login.Quinnquinol
I took a look at the form submission. I'm not sure about the cookies you're setting, but at the very least, you're missing the "pw" key in your key value map, have you tried posting with that as well?Acrosstheboard
Yes I have. I retried it and it still did not work. The code in the question was my most 'recent' code. I tried to log in many different ways prior to posting this question and still had no success.Quinnquinol
I was thinking that the pstoken and contextData are used to hash the user's password. Sure enough, I came across this: github.com/ws/PowerAPI-php/blob/master/PowerAPI.php seems like someone has tried logging in in an automated manner in the past. You'll have to scrape the login page for the pstoken and contextData and do something similar to what this user has done in PHPAcrosstheboard
I'm going to leave you with this link that may help you in building the md5 hmac string you'll need for "pw": #3208660Acrosstheboard
P
0

I have a different approach. I know my code is PHP, not Java, but it still may inspire someone to adapt it into another language. The idea is simple : 1- capture the entire login web page, 2- change the action, 3- add username and password to the inputs, and 4- programmatically click the submit button. Here is the code in PHP with the 4 steps (specific for the website the OP wants) :

▬▬1▬▬
$page = file_get_contents( "http://powerschool.fortschools.org/public" );

▬▬2▬▬
$page = str_replace( 'action="/guardian/home.html"',
       'action="https://powerschool.fortschools.org/guardian/home.html"',
                     $page );

▬▬3▬▬
$page = str_replace(
'<input type="text" id="fieldAccount" name="account" value="" size="39" />',
'<input type="text" id="fieldAccount" name="account" value="■█■█■" size="39" />',
                     $page );

$page = str_replace(
'<input type="password" id="fieldPassword" name="pw" value="" size="39" autocomplete="new-password" />',
'<input type="password" id="fieldPassword" name="pw" value="■█■█■" size="39" autocomplete="new-password" />',
                    $page );

▬▬4▬▬
echo "$page
      <script>
       document.getElementById('btn-enter-sign-in').click();
      </script>";

The ■█■█■ represent the username and password.

I could not use it to log in because it didn't let me to create an account to test it (it asks the ids of children in that school), but I have used this code to enter other websites programmatically.

By the way, the action must be changed in order to run this code locally (yeah, works great from localhost).

Pampa answered 4/3, 2021 at 15:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.