I have a Java application that I need to integrate our existing PHP website with. The vendor wants us to do a server-side redirect to allow for secure authentication and single-sign-on, but I'm not sure how to do that in PHP. The vendor explained the workflow as follows:
User clicks on a 'Open Application' link on our PHP site
The PHP application hits a page on the Java application, sending the authentication parameters
If successful, the PHP application sends the headers back to the user's browser, which forces a 'redirect', otherwise the PHP app displays an error
What this will allow would be for our PHP app to securely talk to the Java app, and the client never has to send any sort of authentication.
From what I understand, .NET and Java have this capability built in, but I can't find a way in PHP to do this. Any ideas?
UPDATE
I'm not talking about using the header("Location: ..."); function to do a redirect. The kicker with this server-side redirect is that the app does the authentication and sends all that information back to the client so that the client is then logged in. Using header("Location: ...") just forces the browser to go elsewhere.
UPDATE 2
autologin.php (Simulates the user logging into an external app via curl)
// The login 'form' is at login.php
$ch = curl_init('http://domain.local/login.php');
// We are posting 2 variables, and returning the transfer just so it doesn't dump out
// Headers are processed by the callback function processHeaders()
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'processHeaders');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, 'username=user&password=pass');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
// Execute curl, close the connection, and redirect the user to a 'restricted' page
$response = curl_exec($ch);
curl_close($ch);
header("Location: http://domain.local/restricted.php");
function processHeaders($ch, $header) {
// Dump the response headers to the client
header($header);
strlen($header);
}
login.php (Contains the 'login' form)
session_start();
if($_POST) {
if($_POST['username'] == 'user' && $_POST['password'] == 'pass') {
$_SESSION['auth'] = 1;
$_SESSION['token'] = md5(time());
} else {
echo 'Auth failed';
}
} else {
echo 'Invalid access type';
}
restricted.php (Restricted page)
session_start();
if($_SESSION['auth']) {
echo 'Secret Token: '.$_SESSION['token'];
} else {
echo 'Please log in';
}
The idea is that the user wants to ultimately get to 'restricted.php'. 'login.php' contains the code necessary to log in. What I want to simulate is the user filling out the form on 'login.php' and logging the user into 'restricted.php'.
The above snippets of code work together on my local tests (hitting autologin.php redirects to restricted.php and the secret token is printed out), but I can't seem to get it to work cross-application. The apps will be on the same domain (https://domain.com/myapp, https://domain.com:1234/vendorapp).
I've never done this before in any language, I'm just going off of what my vendor has told me they've done. Apparently they've never dealt with PHP before and have no idea what to do.
like this:
header("Location: http://www.example.com/")
But it must come before any other code...see php.net
You just output a normal HTTP redirect header() like this:
<?php header('Location: http://www.example.com/'); ?>
Re Update
If I understand correctly you'd need to do this:
Browser POSTs login request to PHP server
PHP script packages the login information in some specific form for JSP app
PHP script POSTs (via cURL) or SOAPs or whatever is necessary to JSP app
PHP receives the response and parses out the necessary information
PHP sends header and/or body data back to browser
Step 4, parsing the information, depends on how you send and receive the information. If you receive them in the header via cURL, you'll need to set CURLOPT_HEADER to true and parse the necessary data out of the response. This may be as simple as splitting the string on the first blank line or more complicated, that depends on your specific situation.
How this logs in the user in your app is something you need to handle as well. The JSP app probably handles the actual password and username and hands you back a token of some sort which you'll need to keep track of.
It sounds like you are looking for the curl library, which is usually bundled with PHP.
http://php.net/manual/en/book.curl.php
<?php
session_start();
// Receive username / password from $_POST
// Prepare CURL object for post
// Post u/p to java server
// Read response
if($success)
{
header('Location: nextpage.php');
$_SESSION['LoggedInTime'] = time();
exit;
}
else
{
//display error
}
Update:
Later, you can check $_SESSION['LoggedInTime'] + 3600 > time() to see if they are still logged in. Every time they visit a logged in page, do this:
if($_SESSION['LoggedInTime'] + 3600 > time())
{
$_SESSION['LoggedInTime'] = time() + 3600;
}
else
{
header('Location: /login.php?Message=session+expired');
exit;
}
Hope this helps.
If you are trying to integrate php and java on the web, you may want to look into Quercus/Resin. Your PHP can then call java code directly. Since they are running on the same server, the java code could write any cookies, setup any sessions or doing any necessary setup processing.
http://www.caucho.com/resin-3.0/quercus/tutorial/module/index.xtp
Related
I am trying to redirect to the same HTML page with an error message saying all fields are required if any of the fields are left empty. I am using Servlets, MYSQL, and HTML to build this project, I am able to store data in MYSQL but stuck at this point, Please help me.
You can use RequestDispatcher to dispatch your HTML resource. But you need to handle displaying error messages in client side (using JS). But it's better to use JSP, so you can achieve it easily
Well, since you didn't show any code, the whole idea is:
Using client side:
You can use JavaScript in the client to confirm if an HTML field is empty or not
validate.js
var field = document.forms["form_name"]["user_input"].value;
if (field==null) {
alert("all fields are required");
return false;
}
Use server side
I'm not a servlet guy but in PHP you can do this:
validate.php
if(isset($_POST["user_input])){
$field = $_POST["user_input"];
if(empty($field){
echo "error, all fields are required"
}
Hope this helps
Hy,
I want to do calls to a different rest api from my play application. I'm using the javaws included library.
The specific call requires that I send form data. However I have no idea how I can send the correct data along with my request.
As far as I can see the library only supports sending url-encoded-form-data.
Does anyone know how I can send form-data along with my request like a normal website doing a form submission?
At the moment I have this:
Promise<WSResponse> promise = WS.url("http://localhost:"+port+"/login").setContentType("multipart/form-data").post("emailAddress=" + email +"&password=" + password);
Thanks,
Use application/x-www-form-urlencoded instead of multipart/form-data.
Promise<WSResponse> promise = WS.url("http://localhost:"+port+"/login")
.setContentType("application/x-www-form-urlencoded")
.post("emailAddress=" + email +"&password=" + password);
I know there are a lot of questions related to this issue, but I'm facing an specific requirement for this purpose of posting data from PHP to a Rest Web Service. The details are explained above, but in summary, when I post data to a url (REST WS) and set the CURLOPT_POSTFIELDS the data is not being added to the request.
The scenario: I have a lot of Java Web Services (REST) running as modules, for example, I have a fileUploadModule which is a REST, I have a databaseModule which is another rest and finally a SearchModule, which is another REST.
I can invoke them directly my rest modules using a link like:
http://[MY IP]:8020/system.file.ws.module.ModuleFile/getResults/jsonp?fileName=fileName
http://[MY IP]:8021/system.search.ws.module.ModuleSearch/getResults/jsonp?xmlQuery=myXml
For the case of files and database, the programmer that was managing the code before me used gwt that connected to the module through a proxy; for instance:
http://[MY_PROXY_IP]:8013/system.file.ws.module.ModuleFile/getResults/jsonp?fileName=fileName
and in my proxy I can print the value of the request received, in this case I use a GET and I can print the request as:
GET /system.file.ws.module.ModuleFile/getResults/jsonp?fileName=idc1&folderType=campaign&callback=__gwt_jsonp__.P0.onSuccess&failureCallback=__gwt_jsonp__.P0.onFailure HTTP/1.1
. Now I am responsible for search that should run through PHP. I tested the url directly to the module and it works, but if I try to it by a proxy it does not seems to be working, it reach my proxy but when I print the request it is incomplete:
POST /system.search.ws.module.ModuleSearch/getResults HTTP/1.1
and I am supposed to receive something like the module file, I share my php code, all seems to be ok, but I don't know what can I be doing wrong... when I set the parameters in CURLOPT_POSTFIELDS the string is not being set
$url = "http://192.168.3.41:8013/system.search.ws.module.ModuleSearch/getResults";
try {
$ch = curl_init();
curl_setopt ($ch, CURLOPT_URL, $url);
curl_setopt ($ch, CURLOPT_POST, 1);
$rawXml = $_POST['rawXml'];
$rawXml = str_replace("%", "%25", $rawXml);
$rawXml = str_replace("&", "%26", $rawXml);
$rawXml = str_replace("=", "%3D", $rawXml);
echo $rawXml;
curl_setopt ($ch, CURLOPT_POSTFIELDS,'xmlQuery='.$rawXml);
$info = curl_exec ($ch);
curl_close ($ch);
echo $info;
} catch (Exception $e){
echo $e->getMessage();
}
please I would really appreciate your help or observations. Than you very much in advance.
After long time, I saw this without an answer. I discovered the fail of this some time ago. This issue occurred because, when reaching server side, for some reason a batch file I did not noiced was adding an additional line to my content, and whenever I read the request content with my proxies, I used a "\n" delimiter, I mean, I have been reading my data using as the EOF indicator a line jump, that's why the content was never shown. I had to modify the code inside my proxy to allow reading the request until the end, not when finding a "\n" character. I mean, the content of the post was set in every case, but a batch process was corrupting that data. So thata was the issue, I just solved it by making sure that my reader always read my entire file considering even line jumps and white lines.
Regards.
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
For starters; Im not so literate in coding.
I am pretty interested in a script on how to trigger/ or throw a Basic/Standard "Authentication Required" Dialog on a specific directory or site and the credentials that would be inputed there by the users, to be checked against another database thats on another website.
i.e. Like those "Check who blocked you on msn" websites that they get your credentials from their website and they check against the Hotmail database or servers and tell you if the credentials are incorrect (try again) or if its correct it redirects you to the specific website that is implemented by the Administrator. (in this situation Hotmail Contact List)
And also when it checks that the credentials are correct how do I make the script to store those credentials into a specific .txt file or folder?!
The only difference is that I just want it to be Basic Authentication Dialog Like This Example Here But I want this to implement on my sites.
I hope Im comprehensible.
Thank you very much in advance.
You will need to send a 401 response code to the browser which will make the browser prompt for a username and password. Here's an example in PHP taken from the PHP manual:
<?php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
header('WWW-Authenticate: Basic realm="My Realm"');
header('HTTP/1.0 401 Unauthorized');
echo 'Text to send if user hits Cancel button';
exit;
} else {
echo "<p>Hello {$_SERVER['PHP_AUTH_USER']}.</p>";
echo "<p>You entered {$_SERVER['PHP_AUTH_PW']} as your password.</p>";
}
?>
You should be able to do the same thing in the language of your choice, although you will need to research where the username and password variables are stored in the language you use.
As an alternative, you may also be able to configure this in your web server. That way the web server handles authentication and you only need to program your application to get the current user name which is usually found in the "REMOTE_USER" environment variable. In Apache you might restrict access to a specific folder as follows:
<Directory /usr/local/apache/htdocs/secret>
AuthType Basic
AuthName "Restricted Files"
# (Following line optional)
AuthBasicProvider file
AuthUserFile /usr/local/apache/passwd/passwords
Require user rbowen
</Directory>
See the Apache documentation on authentication and access control for more information. Even if you are using a different web server, rest assured that this is a common feature in web servers. I'm sure you will be able to find the equivalent functionality in whatever web server you are using.
Java imports have been excluded...
To show the username/password dialog...
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setHeader("WWW-Authenticate", "Basic realm=\"My Realm\"");
httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, "");
To decode the request...
private boolean authenticateRequestOk(HttpServletRequest request)
{
String authorizationHeader = request.getHeader("Authorization");
if (authorizationHeader != null)
{
byte[] decodedUsernamePassword;
try
{
decodedUsernamePassword = Base64.decode(authorizationHeader.substring("Basic ".length()));
}
catch (IOException e)
{
log.error("Error decoding authorization header \"" + authorizationHeader + "\"", e);
return false;
}
String usernameAndPassword = new String(decodedUsernamePassword);
String username = StringUtils.substringBefore(usernameAndPassword, ":");
String password = StringUtils.substringAfter(usernameAndPassword, ":");
if (USERNAME.equalsIgnoreCase(username) && PASSWORD.equalsIgnoreCase(password))
{
return true;
}
}
return false;
}