In my web-app I need to register http clients accessing from a local network behind a router.
I started with remoteHost : remotePort combination, but soon enough it became clear, that the port numer gets regenereated upon each connection.
I need to be able to identify the clients on something similar to MAC address, some property that doesn't change. I wanted to use headers[ "X-Forwarded-For" ], but it's not present at all:
[Pragma=no-cache, Cache-Control=no-cache, Host=somhost.com:8822, Upgrade=websocket, Connection=Upgrade, Sec-WebSocket-Key=scnlM7hzjjy3cklJhJciA==, Sec-WebSocket-Extensions=x-webkit-deflate-frame,deflate-frame, Sec-WebSocket-Version=13]
What are the other options to identify clients?
You could use an API key, that is, a unique identifier that the clients send along with each request to identify themselves. Depending on the authentication method you are using, you could consider the standard HTTP Authorization header to send this value:
Authorization: API-Key <value goes here>
Or create a custom HTTP header for this purpose. But be careful with custom headers: proxies might strip them out.
One option is using cookies. As the client accesses the webapp for the first time we could set a cookie on the client side that has a very long expiry date.
During the subsequent user re-logins we can rely on this cookie as cookies get sent to the server.
You can try this bit of PHP to see what the server knows about an incoming http request:
$keys = array_keys($_SERVER);
echo "<table bgcolor='black' cellpadding='1' cellspacing='1'>\n";
echo " <tr bgcolor='yellow'><td><b>Key</b></td><td><b>Value</b></td></tr>\n";
foreach ($keys as $key) {
echo " <tr bgcolor='white'><td>" . $key . "</td><td>" . $_SERVER[$key] . "</td></tr>\n";
}
echo "</table>\n";
Are you identifying the user at the keyboard or the device making the request? Do you need to track these long term or only for the duration of a use session? Do your users connect from multiple devices?
Client side id certificates could work, depending on how the local machines are managed. If they are accessing your app from someplace they've already authenticated, then setting up a single sign on solution could work. Prompting for authentication always works too.
Related
i am having some issues and almost no documentation on internet about id session tokens and Java web services. We have a server (Tomcat providing web services on JAX-WS + SOAP) that is providing an API to query an SQL server.
I have to code a simple Java client that communicates with the server through this web services. The issue is that before being able to use any of its server WSDL methods, the client has to authenticate through a web server method where you send the user/pass, and the server gives back to client a session-id (alfanumeric string).
The rest of the methods do not have any kind of parameter where i can pass the session id, so i suppose it has to be used as a "context". I have found information about how in JAX-WS you can maintain session-id:
https://weblogs.java.net/blog/ramapulavarthi/archive/2006/06/maintaining_ses.html
Hello port = new HelloService().getHelloPort();
((BindingProvider)port).getRequestContext().put(BindingProvider.
SESSION_MAINTAIN_PROPERTY,true);
in my case, if i want to receive the cookie session-id, i have to:
org.tempuri.RUWebService service = new org.tempuri.RUWebService();
org.tempuri.RUWebServiceSoap myport = new org.tempuri.RUWebServiceSoap();
String session-id = myport.Auth(user,pass);
where the session-id is an UUID variable is a String of a hex variable: 8-4-4-4-8 .. that i can change to real hex like:
java.util.UUID uuidFromHyphens = java.util.UUID.fromString("6f34f25e-0b0d-4426-8ece-a8b3f27f4b63");
I tried the following code, where i change "port" variable to "myport", trying to match both examples:
((BindingProvider)myport).getRequestContext().put(BindingProvider.
SESSION_MAINTAIN_PROPERTY,true);
It compiles, but when i consult the web server through some of its methods, i receive a "null", the same as if i do not make the auth procedure. My issue i think is that i don't know what i am doing wrong with cookie session-id auth procedure.
If somebody could help me, i would be grateful.
regards.
Either you pass it as Request Parameter using GET or POST methods
(or)
Put the session id in outgoing HTTP header, like
GET / HTTP/1.0
Accept: text/plain
Accept: text/html
Session-Id:DFF55566_SOMEID
But for both of this to work, your web server must expect the Session Id from client in some format either at server level (or) your application level.
I have an app engine application that runs REST web services.
I want to extract the ip address from all requests that are handled by my web services.
from javax.servlet.http.HttpServletRequest i'm trying to extract the ip address checking the "X-Real-IP" , if empty or "unknown" check the first ip in the list of "X-Forwarded-For" header if empty or "unknown" get it from request.getRemoteAddr().
I thought i covered all the cases but i'm still getting ip addresses like 10.x.x.x, or 127.0.0.1 or unknown.
I know that app engine applications are running behind load balancers, and instances are dynamic and i'm certainly omitting a header in the request cuz i can see the original ip address in the logs (from google) .
Edit : all the requests i'm working on are direct request to service (no queue or cron requests).
Any idea of the other headers to check ?
thx .
The answeres of this Question might help you. There are a lot of headers to check for:
private static final String[] HEADERS_TO_TRY = {
"X-Forwarded-For",
"Proxy-Client-IP",
"WL-Proxy-Client-IP",
"HTTP_X_FORWARDED_FOR",
"HTTP_X_FORWARDED",
"HTTP_X_CLUSTER_CLIENT_IP",
"HTTP_CLIENT_IP",
"HTTP_FORWARDED_FOR",
"HTTP_FORWARDED",
"HTTP_VIA",
"REMOTE_ADDR" };
I'm in the process of learning how to use HP Quality Center's REST api to query and manipulate data. Unlike REST standard, this API is not completely stateless. It uses cookies to store authentication sessions.
I've tried to implement a very simple test, using the Jersey Client library. I can successfully authenticate my user, by sending my credentials. The API reference claims that this will set a cookie, and I am good to go with further calling the REST api. However, a simple "is-authenticated" call returns a 401, Authentication failed.
I have a feeling that the cookie writing or reading is not working properly, as everything else seems to work as it should. But I haven't been able to find out if or how cookies are set and read, when no browser is involved. So How does cookies work, when calling cookie-setting REST services from java VM? Does it work at all? Where are they stored?
I am using Eclipse Kepler as my IDE, if that matters at all, and a 32-bit java 1.6 JDK and JRE.
Code, and response strings below:
1. Logging in:
Client client = ClientBuilder.newClient();
Response response = client
.target("http://[host]:[port]").path("qcbin/authentication-
point/alm-authenticate")
.request().post(Entity.entity("<alm-authentication>
<user>username</user>
<password>secret</password></alm-authentication>",
MediaType.TEXT_XML_TYPE));
System.out.println(response.toString());
Output:
InboundJaxrsResponse{ClientResponse{method=POST,
uri=http://[host]:[port]/qcbin/authentication-point/alm-authenticate,
status=200, reason=OK}}
API Return description:
One of:
HTTP code 200 and sets the LWSSO cookie (LWSSO_COOKIE_KEY).
HTTP code 401 for non-authenticated request. Sends header
WWW-Authenticate: ALMAUTH
2. Verifying Logged in:
response = client.target("http://[host]:[port]")
.path("qcbin/rest/is-authenticated")
.request().get();
System.out.println(response.toString());
Output:
InboundJaxrsResponse{ClientResponse{method=GET,
uri=http://[host]:[port]/rest/is-authenticated, status=401,
reason=Authentication failed. Browser based integrations - to login append
'?login-form-required=y to the url you tried to access.}}
PS: adding the ?login-form-required=y to the URL, will bring up a log-in window when called in a browser, but not here. Appending the line to the URL actually still gives the same error message, and suggestion to append it again. Also, when called in a browser, the is-authenticated returns a 200, success, even without the login-form.
When you log in, you're getting a cookie which is a name plus a value.
The REST server expects you to pass this in the request header with every request you make.
Look into the object which you get for client.request(); there should be a way to specify additional headers to send to the server. The header name must be Cookie and the header value must be name=value.
So if the server responds with a cookie called sessionID with the value 1234, then you need something like:
client.request().header("Cookie", "sessionID=1234")
Related:
http://en.wikipedia.org/wiki/HTTP_cookie
I am trying to "spoof" a Firefox HTTP POST request in Java using java.net.HttpURLConnection.
I use Wireshark to check the HTTP headers being sent, so I have (hopefully) reliable source of information, why the Java result doesn't match the ideal situation (using Firefox).
I have set all header fields exactly to the values that Firefox sends via HTTP and noticed, that the sequence of the header fields is not the same.
The output for Firefox is like:
POST ...
**Host**
User-Agent
Accept
Accept-Language
Accept-Encoding
Referer
Connection
Content-Type
Content-Length
When I let wireshark tap off my implementation in Java, it gives me a slightly different sequence of fields:
POST...
**User-Agent**
Accept
Accept-Language
Accept-Encoding
Referer
Content-Type
Host
Connection
Content-Length
So basically, I have all the fields, just in a different order.
I have also noticed that the Host field is sent with a different value:
www.thewebsite.com (Firefox) <---> thewebsite.com (Java HttpURLConnection), although I pass on the String to httpUrlConnection.setRequestProperty with the "www."
I have not yet analyzed the byte output of Wireshark, but I know that the server is not returning the same Location in the header fields of my response.
My questions are:
(1) Is is possible to control the sequence the header fields in the request, and if yes is it possible to do using HttpURLConnection? If not, is it possible to directly control the bytes in the HTTP header using Java? [I don't own the server, so my only hope to get the POST method working is through my application pretending to be Firefox, the server is not really verbose, my only info are: Apache with PHP]
(2) Is there a way to fix the setRequestProperty() problem ("www") as described above?
(3) What else could matter? (Do I need to concern the underlying layers, TCP....?)
Thanks for any comments.
PS. I am trying to model a situation without cookies being sent, so that I can ignore the effect.
First, the order of the headers is irrelevant.
Second, in order to manually override the host header you need to set sun.net.http.allowRestrictedHeaders=true either in code
System.setProperty("sun.net.http.allowRestrictedHeaders", "true")
or at JVM start
-Dsun.net.http.allowRestrictedHeaders=true
This is a security precaution introduced by Oracle a while ago. That's because according to RFC
The Host request-header field specifies the Internet host and port
number of the resource being requested, as obtained from the original
URI given by the user or referring resource (generally an HTTP URL).
the headers order is not important. the headers got by server are also out-of-order. And you can not control httpUrlConnection header order. But if you write your own TCP client, you can control your header order. like:
clientSocket = new Socket(serverHost, serverPort);
OutputStream os = clientSocket.getOutputStream();
String send = "GET /?id=y2y HTTP/1.1\r\nConnection: keep-alive\r\nKeep-Alive: timeout=15, max=200\r\nHost: chillyc.info\r\n\r\nGET /?id=y2y HTTP/1.1\r\nConnection: keep-alive\r\nKeep-Alive: timeout=15, max=200\r\nHost: chillyc.info\r\n\r\n";
os.write(send.getBytes());
The Second question is answered by Marcel Stör in the first answer.
a
I got lucky with Apache Http Components, my guess is that the "Host" header's missing "www." made the difference, which can be set exactly as intended using Apache's HttpPost:
httpPost.setHeader("Host", "www.thewebsite.com");
The Wireshark output confirmed my suspicion. Also this time the TCP communication prior to my HTTP post looks different (client ---> server, server ---> client, client ---> server) instead of (client ---> server, server ---> client, client ---> server, client---> server).
Now I get the desired Location header value and the server is also setting the cookies. :)
For the most part, this question is resolved.
Actually I wanted to use the lightweihgt HttpUrlConnection because that's what the Android Developers blog suggesting. The System.setProperty("sun.net.http.allowRestrictedHeaders", "true") might work as well, if it allows to "www." in the Host value.
I have just implemented my first Restlet application (finally :]) and now I'm onto a bigger question. I built a really simple resource called LoginResource, which allows a POST and a GET operation to allow users to login and to check if they're logged in, respectively. Now that I've implemented this and I can actually have a client call the server, "log in," and see a result, how can I actually keep track of whether someone is logged in or not?
My application needs the following:
I need a way to have a client initially log in and be able to see if they're logged in via a resource.
I need to provide "secured" access to a list of objects via another resource. It's pretty simple, but it depends on me being able to control access, which as of right now I'm unable to do as I don't have any sense of sessions activated.
Is there an easy way to allow for me to enable sessions and keep users logged in for a time? If this were PHP, this would be my code:
// login.php: login code
$username = $_POST['username'];
$password = $_POST['password'];
if (validate($username, $password)) {
session_start();
$_SESSION['is_logged_in'] = "yarp";
echo get_login_success();
} else {
echo get_login_failure();
}
// list.php: display list of objects
if (isset($_SESSION['is_logged_in']))
echo get_object_list();
else
echo get_security_error();
I hate to bring it all back to PHP, but hey, it makes for quick pseudo-code.
Have a look at HTTP Basic, HTTP Digest and HTTP OAuth authentications (all supported by Restlet).
For some clients such as browsers, cookie based authentication is still used in REST but without a server-side sesssion.
Check this link:
http://restlet.tigris.org/issues/show_bug.cgi?id=605