I'm doing a script to update several queries that we use in our project everytime we deploy a sprint.
I'm trying to replicate the same request that I'm testing on Fiddler, that it is working, in the following way:
System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
String host = 'redmine.our-domain.com';
String url = 'http://redmine.our-domain.com/queries/4088';
String REDMINE_SESSION_COOKIE = "_redmine_session=BAh7DkkiDHVzZXJfaWQGOgZFRmkvSSIKY3RpbWUGOwBGbCsHmouFWkkiCmF0aW1lBjsARmwrByk211tJIg9zZXNzaW9uX2lkBjsARkkiJTMzZWJkNmI1MzA4MzZkNmMxNGYwNjY1OWQxMDZjZmU3BjsAVEkiEF9jc3JmX3Rva2VuBjsARkkiMVB3bDlCb0F5NFFCbTd3dmdGWGx0VjdEL05WYjhVRGExdFluQmNMbnFZTHM9BjsARkkiCnF1ZXJ5BjsARnsHOgdpZGkC%2BA86D3Byb2plY3RfaWRpAssBSSIWaXNzdWVzX2luZGV4X3NvcnQGOwBGSSIMaWQ6ZGVzYwY7AEZJIg1wZXJfcGFnZQY7AEZpaUkiFWZqbGVzX2luWGV4X3NvcnQGOwBGSSINZm2sZW5hbWUGOwBG--5c961485290b3c98f38de934b939d25cc01e092f"
String data = "_method=put&authenticity_token=Pwl9BoAy4QBm7wvgFXlsV7D%2FNVb8UDa2tYnBcLnqYLs%3D&query%5Bname%5D=Current+sprint+1.75-test+API+0+0+1&query%5Bvisibility%5D=2query%5Bgroup_by%5D=category&f%5B%5D=status_id&op%5Bstatus_id%5D=o&f%5B%5D6=fixed_version_id&v%5Bfixed_version_id%5D%5B%5D=6030&c%5B%5D=tracker&c%5B%5D=status&c%5B%5D=priority&c%5B%5D=subject&c%5B%5D=assigned_to&c%5B%5D=fixed_version&c%5B%5D=start_date&c%5B%5D=due_date&c%5B%5D=estimated_hours&c%5B%5D=done_ratio&c%5B%5D=parent";
byte[] body = data.getBytes("UTF-8");
HttpURLConnection http = (HttpURLConnection) new URL(url).openConnection();
http.setRequestMethod('POST');
http.setRequestProperty('Cookie', REDMINE_SESSION_COOKIE);
http.setRequestProperty('Content-Type', 'application/x-www-form-urlencoded');
http.setRequestProperty('Host', host);
http.setRequestProperty('Content-Length', "${body.length}");
http.setDoOutput(true);
http.getOutputStream().write(body);
Both, data's authenticity_token and session cookie are fakes, but I'm copy-pasting the Fiddler one.
I'm adding the Host and Content-Length because Fiddler always add them.
Fiddler returns a 302 status that it is right, because Redmine redirects the page.
With the code above I receive a 422 status (Unprocessable Entity) with this message in the body:
Invalid form authenticity token
I've spent 3 days trying to figure out what I'm doing wrong to clone the request. Any clue?
You should rather try to use Redmine's API to acheive your goal, instead of trying to send html form data to controller.
Redmine login form creates also invisible form data fields, which you can see while inspecting with your browser (F12 usually).
One such, hidden field is authenticity token, and it's generated new, every time form is rendered.
Fiddler probably works, because it's performing basic authentication, as described here:
http://www.redmine.org/projects/redmine/wiki/Rest_api#Authentication
So in your code, you must remove part of code trying to mimic form data, and use basic authentication instead, like this:
System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
String host = 'redmine.our-domain.com';
String url = 'http://redmine.our-domain.com/queries/4088';
String auth = Base64.getEncoder().encodeToString((username+":"+password).getBytes(StandardCharsets.UTF_8)); //Java 8 - not sure for 7
HttpURLConnection http = (HttpURLConnection) new URL(url).openConnection();
http.setRequestProperty("Authorization", "Basic "+auth);
http.setRequestMethod('POST');
http.setRequestProperty('Cookie', REDMINE_SESSION_COOKIE);
http.setRequestProperty('Content-Type', 'application/x-www-form-urlencoded');
http.setRequestProperty('Host', host);
http.setRequestProperty('Content-Length', "${body.length}");
http.setDoOutput(true);
http.getOutputStream().write(body);
Related
I'm building a java 8 console program to get data from a remote web service.
That service needs an authorization token in the form:
"Authorization: Bearer <my token>".
My connection code:
final URL url = new URL("https://<service url>");
final HttpURLConnection cnn = (HttpURLConnection) url.openConnection();
cnn.setRequestMethod("GET");
cnn.addRequestProperty("Authorization", "Bearer "+token);
Map<String, List<String>> props = cnn.getRequestProperties();
int size = props.size(); // size is always 0
cnn.connect();
int status = cnn.getResponseCode(); // status is always 404
I found "Authorization" is a disallowed request property so I run this code with JVM property
-Dsun.net.http.allowRestrictedHeaders=true.
Running my code I can find cnn.getRequestProperties() is always empty as my property was discarded and not used and, maybe a consequence of that, connection status is 404 (Forbidden).
I cannot ask to service-supplier to change the way everybody can authorize himself to its service.
Anybody know the way to get "Authorization" property accepted ?
Thanks,
Marco
So I am writing a java program that does some basic http post and get requests to the VKontakte API. So far so good. I have all keys and tokens required so far, but am Struggling with one thing:
When I get my oauth2 token, I have to get it through the browser.
You actually have to call the following url:
https://oauth.vk.com/authorize?client_id=YOUR_ID&redirect_uri=https://oauth.vk.com/blank.html&response_type=token
... which then redirects you and 'prints' the access token in the address bar. Now I want to do all of that programmatically.
So far, I have the following:
private static String oauth2Token() throws IOException{
String url = "https://oauth.vk.com/authorize?client_id=6046940&redirect_uri=https://oauth.vk.com/blank.html&response_type=token";
URL obj = new URL(url);
HttpURLConnection connection = (HttpURLConnection) obj.openConnection();
//GET TOKEN HERE
return oauth2Token;
}
But I don't know how to continue. If I trigger the Http connection like this, How can I get the address I am being redirected to (e.g. containing the oauth2 token)?
I am trying to connect to an API using Grails 3.1.4.
In fact the authentication is done and I getthe generated token after sending email and password.
I am trying to send queries after that. However, I can't send the token in header of the http query
String url="www.myurl.com"
CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL))
connection = (HttpURLConnection) new URL(url).openConnection()
connection.setRequestMethod("GET")
connection.setDoOutput(true)
connection.setDoInput(true)
connection.setConnectTimeout(10000)
connection.setRequestProperty("content-Type","application/x-www-form-urlencoded")
connection.setRequestProperty("Set-Cookie","token/"+token)
OutputStream output = connection?.getOutputStream()
output.write(query.getBytes())
It all depends on the authentication mechanism used. If JWT tokens are used, you need to add a http header with the keyword "Authentication" and a value of "Bearer ". Please ask your service supplier which mechanism is used. Usually a 401 statuscode is an indication you are doing something wrong.
Please excuse me if any of this sounds very stupid or inexperienced, however I have looked everywhere else and haven't been able to find a simple explanation as to how to properly implement this.
So far I have made a restful call to a server running on openAm; the call sends my user name and password credentials and returns to me a secure token. I then need to make another restful call to request certain json files in their api.
I understand that in my second restful call I need to somehow embed the token with it so the server knows that I am allowed to access the requested data. My question is what is the proper way to go about this. I have found/heard of multiple possibilities such as passing it in the header, parameters, or as a cookie, but each time my request is redirected to the log in url instead of returning my request.
From my understanding it appears the cookie method works best (if I'm wrong then please post a different method). So for openAm authentication, how do I properly build a cookie with my token. Once the cookie is built how do I embed that into the connection. Do I need to make a whole new connection or can I redirect my original connection with the cookie? Any help or advice is greatly appreciated.
Some of my code, using HttpURLConnection:
//takes url and builds our connection
String url = "http://some.url.net/openam/json/authenticate";
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("X-OpenAM-Username", name);
connection.setRequestProperty("X-OpenAM-Password", pass);
connection.setRequestProperty("Content-Type", "application/json");
//takes in the connections response
BufferedReader in = new BufferedReader(new InputStreamReader(response, "UTF-8"));
String output = in.readLine();
//this is to cut the token out of the response
int i = 14;
while(true){
if (output.charAt(i)=='"'){
break;
}
i++;
}
String token = output.substring(14,i);
//build our new connection and second call
url = "https://other.url.net/api/v1/resource/attributes";
HttpURLConnection request_conn = (HttpURLConnection) new URL(url).openConnection();
/*
request_conn.setRequestProperty("iPlanetDirectoryPro", token);
request_conn.setRequestMethod("POST");
request_conn.connect();
*/ //Tried to put the token through the header, doesnt work
/*
Cookie cookie;
cookie = new Cookie("iPlanetDirectoryPro", token);
cookie.setDomain(".di2e.net");
cookie.setPath("/");
cookie.setSecure(true);
request_conn.addCookie(cookie);//addCookie() doesnt work for a urlConection?
*/ //Tried building the cookie and adding it to the new conection
How to pass input to a php web page using a automated script ,i.e. i just want to know how pass arguments to text fields using a script. like passing input to username and password field of a web page and then pressing submit button(that too with a script).
favorable language: JAVA
Try Selenium. Selenium is great at automating web browsers.
http://seleniumhq.org/
Also has pure support with Java. But not only.
When it comes to custom methods, see ...
String urlParameters = "param1=a¶m2=b¶m3=c";
String request = "http://example.com/index.php";
URL url = new URL(request);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setInstanceFollowRedirects(false);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("charset", "utf-8");
connection.setRequestProperty("Content-Length", "" + Integer.toString(urlParameters.getBytes().length));
connection.setUseCaches (false);
DataOutputStream wr = new DataOutputStream(connection.getOutputStream ());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
connection.disconnect();
source (Java - sending HTTP parameters via POST method easily)
if you web page uses the GET method to accept data (i.e. from URL), just connect to the web pages giving the data you want to pass:
http://www.mysite.com/mypage.html?data0=data0,data1=data1
if the web page uses POST things get a little bit more complicated: you have to forge an appropriate HTML request with all your data in the header (as POST method requires)
You can use the Apache HTTPClient - see the example at:
http://hc.apache.org/httpclient-3.x/methods/post.html
This allows you to simulate submitting a fully filled form directly to the destination page and grab the results.
Remember that, after the call, you have to grab and store the session cookie in the response and resubmit it to the following pages you want to "visit" to stay "logged on"
I would like to show how I would do to pass an input to the HTML. I usually use python to send request to the page where I need to input the data. Before doing that you need to know if you need to supply web-cookies or not, if yes, copy the cookie, if you need to be logged in otherwise not, just check that. Once that is done, you need to know the field names for the input area as you will be using them to POST or GET data using your script. Here is sample usage.
import urllib
import urllib2
import string
headers = {'Cookie': 'You cookies if you need'}
values = {'form_name':'sample text', 'submit':''}
data = urllib.urlencode(values)
req = urllib2.Request('website where you making request to',data,headers)
opener1 = urllib2.build_opener()
page1=opener1.open(req)
#OPTIONAL
htmlfile=page1.read()
fout = open('MYHTMLFILE.html', "wb")
fout.write(htmlfile)
fout.close()