I learning about programming, data transfer over the web and APIs. I created a simple model of a data transfer between two websites. I have three basic questions about the below process. In reviewing, assume both websites are setup with TLS.
Would the below simple process be a good secure architecture for data transfer between two websites?
Would this simple example be called an API?
In this example how could additional security be implemented (i.e. API Key etc..)?
Website 1 - A simple web form to capture and send data:
<!DOCTYPE HTML>
<html>
<head>
</head>
<body>
<?php
// define variables and set to empty values
$name = $email = $gender = $comment = $website = "";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$name = test_input($_POST["name"]);
$email = test_input($_POST["email"]);
$website = test_input($_POST["website"]);
$comment = test_input($_POST["comment"]);
$gender = test_input($_POST["gender"]);
}
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
?>
<h2>PHP Form Validation Example</h2>
<form method="post" action="include/redirect.php">
Name: <input type="text" name="name">
<br><br>
E-mail: <input type="text" name="email">
<br><br>
Website: <input type="text" name="website">
<br><br>
Comment: <textarea name="comment" rows="5" cols="40"></textarea>
<br><br>
Gender:
<input type="radio" name="gender" value="female">Female
<input type="radio" name="gender" value="male">Male
<input type="radio" name="gender" value="other">Other
<br><br>
<input type="submit" name="submit" value="Submit">
</form>
</body>
</html>
Website 1 Include file that runs on submissions of the form:
<?php
if (isset($_POST['name']) && $_POST['name']!="") {
$name = $_POST['name'];
$url = "https://localhost/api/api/".$name;
$client = curl_init($url);
curl_setopt($client,CURLOPT_RETURNTRANSFER,true);
$response = curl_exec($client);
$result = json_decode($response);
echo "<table>";
echo "<tr><td>Name:</td><td>$result->name</td></tr>";
echo "<tr><td>Amount:</td><td>$result->amount</td></tr>";
echo "<tr><td>Response Code:</td><td>$result->response_code</td></tr>";
echo "<tr><td>Response Desc:</td><td>$result->response_desc</td></tr>";
echo "</table>";
}
?>
Website 2 - Called in the include file: https://localhost/api/api/".$name;. Website 2 receives data and assigns an amount to it and returns the data.
<?php
header("Content-Type:application/json");
if (isset($_GET['name']) && $_GET['name']!="") {
$name = $_GET['name'];
}
else {
response(NULL, NULL, 400,"Can't process options now, visit local dealer");
}
if($name=="Joe"){
$amount = "700";
$response_code = "Good";
$response_desc = "Good";
response($name, $amount, $response_code,$response_desc);
}
else {
response(NULL, NULL, 200,"Can't process options now, visit local dealer");
}
function response($name,$amount,$response_code,$response_desc){
$response['name'] = $name;
$response['amount'] = $amount;
$response['response_code'] = $response_code;
$response['response_desc'] = $response_desc;
$json_response = json_encode($response);
echo $json_response;
}
?>
Would the below simple process be a good secure architecture for data transfer between two websites?
Yes, this can work. If you just want the two web servers to communicate with each other I would recommend limiting access to the script via a .htaccess file or a firewall though so it's not publicly accessible.
Of course, wherever possible calling methods via PHP instead of sending HTTP requests between scripts is more secure, faster and better in almost any way.
Would this simple example be called an API?
An application programming interface (API) is a connection between computers or between computer programs. It is a type of software interface, offering a service to other pieces of software.
From Wikipedia: API
Well yes, you have implemented an API. Your computer is able to communicate with the server to send and receive data and your two websites/servers can also communicate with and offer services to each other.
In this example how could additional security be implemented (i.e. API Key etc..)?
As I've mentioned earlier, depending on your requirements you can limit access to the API endpoint used for server to server communication ("https://localhost/api/api" in this case) to prevent someone other than your server from using it (Use a .htaccess file or check for the IP in the code)
Further, there are a few ways to prevent spoofing attacks in the server to server part of it, including (Source):
Using HTTP basic authentication (or OAuth if you want to go way further)
Using a shared secret (API Key)
Including a signature to verify the contents have not been changed (e.g. HMAC, see Is HMAC required when using TLS communication?)
This is by no means comprehensive, I hope it could povide some answers and points to research further.
Related
Given below is the test code for the issue
If an invalid email with extension .com.com is given it is treated as valid
Please help to resolve the same
Thanks in advance
<?php
if(isset($_POST['submit']))
{
function validate_email($email)
{
$exp = "^[a-z\'0-9]+([._-][a-z\'0-9]+)*#([a-z0-9]+([._-][a-z0-9]+))+$";
if(eregi($exp,$email))
{
if(checkdnsrr(array_pop(explode("#",$email)),"MX"))
{
return 1;
}
else
{
return 0;
}
}
else
{
return 0;
}
}
$email = $_POST['email'];
print $details= validate_email($email);
}
?>
<form action="" method="post">
<h1> Email </h1>
<input type="email" name="email">
<button type="submit" name="submit"> SUBMIT </button>
</form>
How should it know that that email address is wrong?
A valid email address is already "someone#company"
Where "company" could be your intranet systems hostname. For reasons like that FILTER_VALIDATE_EMAIL doesn't check for a "valid" TLD, as it could not know if it is valid.
As for that it is recommended to NOT write a more specific check on your own, as in a lot of scenarios those checks could render your application useless.
You can use
$pattern = "/^[_a-z0-9-]+(\.[_a-z0-9-]+)*#[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$/i";
or Just
filter_var('email#email',FILTER_VALIDATE_EMAIL)
You can use this regex :
^([a-z\'0-9\._-]+)#([a-z0-9]+)((\.[a-z0-9]{2,3})(\.[a-z0-9]{2})|(\.[a-z0-9]{2,3}))$
Working well with "john.doe#gmail.com" or "john.doe#domain.co.uk", but it's very difficult to match all the possibilities now too many different tld are availables.
You should try the API of an email verification service.
Regards
I have a page which takes input data from users trying to create a new account on my website. Although I want to check the values of the data before the page is redirected to send the input data to the database. I have created a verification form which redirects back to the same page when the user clicks submit, so as to check the values, but if all the values are okay, then I want to send the parameters inputted to another page which will input them in the database. Is there a way to do this conditionally in PHP? I've tried to implement it with a simple boolean checking if any of the parameters inputted are incorrect, but don't know how to send the params along with the redirection.
Here is a shortened version of the code with just some of the forms:
<?php
// Connection to database
include_once("createConnection.php");
$hasErrors = false;
$errorFName = $errorLName = $errorEmail = "";
$fName = $lName = $email = "";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (empty($_POST["fName"])) {
$errorFName = "This field is required.";
$hasErrors = true;
}
else {
$name = validation($_POST["fName"]);
//name cannot contain any symbols or numbers
if (!preg_match("/^[a-zA-Z ]*$/",$fName)) {
$errorFName = "Only letters and white space allowed";
$hasErrors = true;
}
}
if($hasErrors==false){
**???**
}
function validation($input) {
$input = trim($input);
$input = stripslashes($input);
$input = htmlspecialchars($input);
return $input;
}
?>
<form class="loginForm" method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>">
<table class="loginTable">
<tr>
<td><label for="newDetail">First Name: </label>
<input type="text" class="formBox" value="" id="newDetail" name="fName">
<?php echo $errorFName;?>
</td>
</tr>
<tr>
<td><label for="newDetail">Password: </label>
<input type="text" class="formBox" value="" id="newDetail" name="pword">
</td>
</tr>
<tr>
<td><button type="submit" class="loginButton" name="submitNew">Submit</button></td>
</tr>
</table>
</form>
Thanks!
You could store the $_POST variables in sessions.
$_SESSION["firstname"] = $_POST["fname"];
Then redirect to the required page
header("location: welcomepage.php");
Then grab the variables from the session and process, maybe insert to database for future use.
$firstname = $_SESSION["firstname"];
You could redirect manually with a <meta http-equiv="refresh">:
echo '<meta http-equiv="refresh" content="0, welcomepage.php?params=params">';
I'm not quite sure why you would like to pass parameters to other page - it qould be much easier to process them right here. If it is a general messines of the code you dislike - you can pass data to a function or a method from an included file.
However, if it is really necessary to save data from a separate page I would recommend sending them via cURL:
$post = array(/*put all your variables here*/);
$params = http_build_query($post);
$url = 'http://your.domain.com/receiver.php';
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $params);
$result = curl_exec($curl);
This way anything you would output on the receiving page will end up in $result, so you can confirm to a user that his/her data was saved.
NB: whatever you would end up doing - do NOT pass the data to the receiving page as GET. It is insecure and every time someone does this a puppy dies!
More info on curl: http://php.net/manual/en/book.curl.php
I am making a user system on a website and I cannot get the form to post to the file.
Here is the form in the HTML file:
<form method="post" action="php/userlogin.php">
<p><input type="text" name="usernameL" value=""></p>
<p><input type="password" name="passwordL" value=""></p>
<p><input type="submit" name="submit" value="Login"></p>
</form>
And the userlogin.php in the php directory:
<?php
$username = $password = "";
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$username = test_input($_POST["usernameL"]);
$password = test_input($_POST["passwordL"]);
}
function test_input($data) {
$data = trim($data);
$data = stripslashes($data);
$data = htmlspecialchars($data);
return $data;
}
?>
I'm new to forms and can't find an answer anywhere or even a question like this. How would I fix this?
You code is working fine.
The problem might be with the file structure. Please check that.
Ex: If your html file in the root folder of your project, Then the userlogin.php files should be there in project_root_folder/test/
So the file structure should be...
Root/
index.html
Test/
userlogin.php
Code is fine.
Just output the values of the variables.
echo $username.' '.$password;
You can see that the data is being posted.
Well your code seems to work perfectly fine, maybe the problem is with your testing enviroment, you need solution like XAMPP https://www.apachefriends.org/ to run php scripts on your computer. Other way is to run scripts remotely on some free webhosting that supports php.
If this is not the case then to check if actually data was sent, modify your code this way:
...
if ($_SERVER["REQUEST_METHOD"] == "POST") {
$username = test_input($_POST["usernameL"]);
$password = test_input($_POST["passwordL"]);
echo $username."<br/>";
echo $password."<br/>";
}
...
I have a PHP form, from which I need to submit POST data to a third-party URL and redirect to a confirmation page.
I have no control over the third-party page and that provides no confirmation after POST, so I need to add that into my code.
Here is the process in more detail:
PHP form on www.example-site-1.com/form.php, which uses basic htmlspecialchars($_SERVER["PHP_SELF"]); to perform validation, before redirecting:
<?php
// Setup Empty Fields
$first_name = $last_name = $job_title = "";
// Setup Empty Error Messages
$first_nameError = $last_nameError = $job_titleError = "";
// Validate Field Entry
if ($_SERVER["REQUEST_METHOD"] == "POST")
{
$valid = true; // Redirect if valid
if (empty($_POST["first_name"]))
{$valid = false; $first_nameError = "Provide first name";}
else
{$first_name = htmlspecialchars($_POST["first_name"]);}
if (empty($_POST["last_name"]))
{$valid = false; $last_nameError = "Provide surname";}
else
{$last_name = htmlspecialchars($_POST["last_name"]);}
if (empty($_POST["job_title"]))
{$valid = false; $job_titleError = "Provide your job title";}
else
{$job_title = htmlspecialchars($_POST["job_title"]);}
// Start session
session_start();
// Register session
session_register('first_name');
session_register('last_name');
session_register('job_title');
// Populate
$_SESSION['first_name'] = $first_name;
$_SESSION['last_name'] = $last_name;
$_SESSION['job_title'] = $job_title;
// Redirect valid form to process
if($valid)
{header('Location: process.php');
exit();
}
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
</head>
<body>
<div>
<form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>" name="submit_data" method="POST" id="submit_data">
<fieldset>
<legend>Your Details</legend>
<p><label for="first_name">First Name</label><input type="text" id="first_name" size="20" maxlength="50" value="<?php echo $first_name;?>" name="[first_name]" /><br /><span class="error"> <?php echo $first_nameError;?></span></p>
<p><label for="last_name">Surname</label><input type="text" id="last_name" size="20" maxlength="50" value="<?php echo $last_name;?>" name="[last_name]" /><br /><span class="error"> <?php echo $last_nameError;?></span></p>
<p><label for="job_title">Job Title</label><input type="text" id="job_title" size="30" maxlength="30" value="<?php echo $job_title;?>" name="[job_title]" /><br /><span class="error"> <?php echo $job_titleError;?></span></p>
</fieldset>
<input type="submit" value="Submit" />
</form>
</div>
</body>
</html>
I've added sessions to carry over into the subsequent page, but perhaps I don't need these. Also, the {header('Location: process.php'); is there for example, but that is really what I am stuck on; how should I perform the following?
Essentially, once somebody clicks Submit, I need 2 things to happen (both from the one click):
1) Form data is submitted to a third-party site (for demo purposes, www.example-site-2.com/submit.php) using POST. User should never see that page (it is a plain white screen, with no feedback provided to the user).
2) User that clicked submit should be transferred to a thank you/confirmation page on www.example-site-1.com/thanks.php
Is this possible?
As mentioned, I unfortunately have no access to edit the third-party site, so cannot add a confirmation after POST on that site.
PHP solution would be great, or JavaScript would be fine.
Any help or ideas much appreciated. Thanks
Maybe you could use cURL? Something like this I think could do the trick
// Where to make our request (third party site)
$ch = curl_init($urlToThirdParty);
// Make the request
curl_exec($ch);
// Did anything went wrong=
if (curl_errno($ch)) {
die('Oops: ' . curl_error($ch));
} else {
// Make sure we got a 200 back (indicating success)
$httpStatusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($httpStatusCode != 200) {
die('Oops. Status code: ' . $httpStatusCode);
}
}
curl_close($ch);
// If we made it this far, redirect to thank you page
header('Location: '.$thankYouURL);
Hope this helps!
You could do the POST request yourself, using curl for instance.
//set POST variables
$url = 'http://domain.com/get-post.php'; //URL of that site with a blank page
$fields = array( //your parameters here
'lname' => urlencode($last_name),
'fname' => urlencode($first_name),
'title' => urlencode($title),
'company' => urlencode($institution),
'age' => urlencode($age),
'email' => urlencode($email),
'phone' => urlencode($phone)
);
//url-ify the data for the POST
foreach($fields as $key=>$value) { $fields_string .= $key.'='.$value.'&'; }
rtrim($fields_string, '&');
//open connection
$ch = curl_init();
//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL, $url);
curl_setopt($ch,CURLOPT_POST, count($fields));
curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);
//execute post
$result = curl_exec($ch);
//close connection
curl_close($ch);
If you just send the user to the third party site (as you are doing now) then there is no getting them back.
There are 2 ways that come to mind, 1 submit the form request to the third party site using ajax, grab the response, and then redirect the user to the thanks page on your site.
Or, if you don't want to use javascript, have the form submit to your thanks page, then have some php in there that submits the form request to the third party site (using curl) before displaying the thanks content
What you should do I think is:
create a random token (a random number) and save it in a $_SESSION['user_token'].
$_SESSION['user_token'] = random_number(); // random_number() is a custom function which generates a random number of some length
Then saves the data returned from the form to a database. Your table must have a column called "token_value" or "user_token". When the user returns to you page, check the session with the database:
$stmt = $db->prepare("SELECT * FROM form_data WHERE token_value = ?");
$stmt->bind_param("s", $_SESSION['user_token']);
// and the rest of DB-related operation
I'm still relatively new to PHP. I'm trying to build a privacy settings page for members to opt out of automatic emails for triggered events (i.e. private message notification). I want the checkbox set automatically based on the database setting. As of now, the form does update the database correctly, but the checkbox status does not show the correct setting unless the Submit button is pressed twice, or the page is reloaded. Setting would be '0' for unchecked, '1' for checked. I'd love to use Ajax or jQuery to handle this, but I don't know those at all.
privacysettings.php
<?php
$id = "";
$pm_mail_able = "";
$pm_email = "";
if (isset($_GET['id'])) {
$id = preg_replace('#[^0-9]#i', '', $_GET['id']); // filter everything but numbers
} else if (isset($_SESSION['idx'])) {
$id = $logOptions_id;
} else {
header("location: index.php");
exit();
}
//query to get checkbox status
$sql = mysql_query("SELECT * FROM members WHERE id='$id'");
while($row = mysql_fetch_array($sql)){
$pm_mail_able = $row['pm_mail_able'];
}
switch ($pm_mail_able) {
case 0:
$pm_setting = NULL;
break;
case 1:
$pm_setting = "checked=\"checked\"";
break;
}
if(isset($_GET['pm_email']) && !empty($_GET['pm_email'])) {
$updateqry = mysql_query("UPDATE members SET pm_mail_able='1' WHERE id='$id'");
} else {
$updateqry = mysql_query("UPDATE members SET pm_mail_able='0' WHERE id='$id'");
}
?>
<html>
Email Notifications<br />
<form name="testform" method="get" action="PvResult.php">
When a friend sends me a private message
<input type="checkbox" name="pm_email" value="on"<?php echo $pm_setting;?> />
<br /><br />
<input type="submit" value="Submit" />
</form>
</html>
PvResult.php
<?php
$url = 'http://www.mywebsite.com';
//If the form isn't submitted, redirect to the form
if(!isset($_GET['Submit']))
header('Location: '.$url.'/privacysettings.php');
//Redirect to the correct location based on form input
$pm_email = $_GET['pm_email'];
$url .= '/privacysettings.php?pm_email='.$pm_email;
header('Location: '.$url);
?>
Okay, hopefully this won't just answer your question, but give you a few best practices you might want to consider.
You can combine these two scripts into one relatively easily. Also, I'd highly suggest using a POST instead of GET; GET is very limited and is not intended to submit data like you're using it. If you're going to be changing data in a back-end store, using GET will bite you. Maybe not today, maybe not tomorrow, but it will, trust me.
You really should consider moving to PDO instead of the mysql_ functions. PDO is a lot better in handling parameterized queries, which you really should have here for better security, and it's more portable if someday you want to move to a different database system.
I'm still a little hazy on how your app is getting the $id. Most apps get it from a $_SESSION variable, making sure that the user has successfully validated a login. If you're not doing that, please do. You might want to thoroughly digest this article, it's got a lot of juicy best practices regarding authentication and "remember me"-type functionality.
Here's a bit of a rewrite. I haven't actually tested it, but it should give you a pretty good idea on where to go with your immediate needs. If it throws any errors (remember the disclaimer: I haven't actually tested it!), let me know and I'll try to debug it.
<?php
$message = '';
$pm_setting = '';
$id = 0;
// Put your $id retrieval logic here. It should look something like:
if (isset($_SESSION['id'])) {
$id = $_SESSION['id'];
if (!preg_match('/^\\d{1,10}$/', $id) > 0) {
// Someone is trying to hack your site.
header("location: scum.php");
exit();
}
$id = intval($id);
}
// Quick security note: You might want to read up on a topic called
// session hijacking if you want to ensure your site is secure and
// this $id isn't spoofed.
if (isset($_POST['Submit'])) {
// The form is being submitted. We don't need to read the current
// pm_mail_able setting from the database because we're going to
// overwrite it anyway.
if ($id > 0) {
$pm_mail_able = 0;
if (isset($_POST['pm_email']) && $_POST['pm_email'] === 'on') {
$pm_mail_able = 1;
$pm_setting = 'checked ';
}
$query = 'UPDATE members SET pm_mail_able='.$pm_mail_able.
' WHERE id = '.$id;
mysql_query($query);
// Another quick security note: You REALLY need to consider
// updating to PDO so that you can bind these parameters
// instead. The mysql_ functions are probably going to be
// deprecated soon anyway.
if (mysql_affected_rows($query) > 0)
$message = '<p style="color: #00a000;">Settings saved!</p>';
else
$message = '<p style="color: #a00000;">User id not valid.</p>';
}
else
$message = '<p style="color: #a00000;">User id not valid.</p>';
}
else {
// This is the first load of the form, we need to just display it
// with the existing setting.
if ($id > 0) {
$query = mysql_query('SELECT * FROM members WHERE id = '.$id);
if (($row = mysql_fetch_array($query, MYSQL_ASSOC)) !== FALSE)
if ($row['pm_mail_able'] === 1) $pm_setting = 'checked ';
}
}
?>
<html>
<body>
<?= $message ?>
<!-- Without action parameter, form submitted to this script. -->
<form name="testform" method="post">
E-mail notifications<br />
<input type="checkbox" name="pm_email" value="on" <?= $pm_setting ?>/>
When a friend sends me a private message
<br /><br />
<input type="submit" value="Submit" />
</form>
</body>
</html>
Try to do these settings and see if it will work:
1) You need to add an space between "on" and "checked=checked"
<input type="checkbox" name="pm_email" value="on" <?php echo $pm_setting;?> />
2) You have to reference the submit button by its name, not its value
<input type="submit" name="Submit" value="Send" />
3) When the setting is "0", set $pm_setting as a empty string, instead of NULL
case 0:
$pm_setting = '';
4) Maybe there is some problem with $_GET['pm_email'] and the else is always being executed
5) If the things work when you press the Submit button twice, it means that the form is passing some GET var that make the code work, so try to discover what var is this