How can make automatic logout in php - javascript

I make web with login/logout.
If any link or button pressed on web I call ajax function to check login and if time expired logout user. In logout function I update my database.
But If I close browser or page user is not logged out and database is not updated. How can I add event listener for it.
PHP FILE
if (isset($_POST['action']) && !empty($_POST['action'])) {
$action = $_POST['action'];
switch ($action) {
case "checkLogin":
echo isLogged();
break;
case "logout":
logout();
break;
//and more
}
}
function isLogged() {
$data = array(
"login" => 0,
"username" => "null"
);
if(isset($_SESSION["user"]) && isset($_SESSION["start"])) {
$session_start = $_SESSION["start"];
//more then 600 sec
if(time() - $session_start < 600){
$data = array(
"login" => 1,
"username" => $_SESSION["user"]
);
}else{
logout();
}
}
return json_encode($data);
}
function logout(){
if(isset($_SESSION["user"])) {
$connection = connectToDB();
if($connection != null) {
$nickname = $_SESSION["user"];
$time = date("Y-m-d H:i:s");
$sql_statement = "UPDATE users SET is_login='0',last_login='$time' WHERE username='$nickname';";
$connection->query($sql_statement);
}
session_destroy();
}
}

There's no surefire way to "listen" for the user closing your window or, as #Taplar pointed out, powering off their computer. Using the technique of storing the login time within the session described in this question, you can run a cron or other kind of background task checking the database for sessions that are due to expire, and then expire them there.

You can add unload listener with async - false, so browser will wait while request is not finished:
$(window).unload(function() {
$.ajax({
type: 'GET',
url: '/logout',
async: false
});
});
Note that browser will "hang" during request, and it can confuse user

Related

Check if form has been submitted via ajax in php

I have a login form which is validated using javascript and then sent to php file for further processing. Form is submitted via ajax.
Currently, i have an if statement in php file that checks whether form has been submitted, problem is this if statement never evaluates to true. Hence my php code inside my if statement never runs. When request is sent via ajax, .onload event gets invoked without if statement inside php file evaluating to true.
Question
Once the form is submitted to php file via ajax, how can i detect in php file that form has been submitted via javascript.
Here's my php code
<?php
require 'DbConnection.php';
// if form is submitted
if(isset($_POST['login-btn'])) {
$username = $_POST['username-field'];
$password = $_POST['password-field'];
echo '<script>alert(\'form submitted\')</script>';
verifyLoginCredentials($username, $password);
} else {
echo '<script>alert(\'form not submitted\')</script>';
}
// verify admin login credentials
function verifyLoginCredentials($username, $password) {
global $dbConnect;
$query = 'SELECT full_name, username, password FROM admins WHERE username = ?';
$statement = $dbConnect->prepare($query);
if($statement) {
$statement->bind_param('s', $username);
$statement->execute();
$resultSet = $statement->get_result();
// since there will be only one row returned at max, no need of a loop
$row = $resultSet->fetch_assoc();
if($row != null) {
$adminFullName = $row['full_name'];
$adminUsername = $row['username'];
$adminPassword = $row['password'];
// if username/password is correct start session and store
// username, password, full name in the session
if($username === $adminUsername && password_verify($password, $adminPassword)) {
session_start();
$_SESSION['current_admin_fullname'] = $adminFullName;
$_SESSION['current_admin_username'] = $adminUsername;
$_SESSION['current_admin_password'] = $adminPassword;
}
else { // if username/password combination is incorrect
echo 'Incorrect Username/Password Combination';
}
} else { // if username doesn't exists in the database
echo 'Entered username isn\'t registered';
}
} else {
echo 'Error while preparing sql query';
}
}
?>
and here's relevant javascript code
let loginForm = document.querySelector('.login-form');
let usernameField = document.getElementById('username-field');
let passwordField = document.getElementById('password-field');
// submit login form to server using ajax
function ajaxFormSubmit() {
'use strict';
let ajaxRequest = new XMLHttpRequest();
let url = 'admin login.php';
// login form submitted on server successfully
ajaxRequest.onload = function () {
if (ajaxRequest.readyState === 4 && ajaxRequest.status === 200) {
console.log(ajaxRequest.responseText);
displayInfoMessage(ajaxRequest.responseText, 'success');
}
};
// error while login form submission on server
ajaxRequest.onerror = function () {
if (ajaxRequest.status !== 200) {
console.log(ajaxRequest.responseText);
displayInfoMessage(ajaxRequest.responseText, 'error');
}
};
ajaxRequest.open('POST', url, true);
ajaxRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
ajaxRequest.send(new FormData(loginForm));
}
function validateForm(e) {
'use strict';
// prevent form submission
e.preventDefault();
if (anyEmptyField()) {
displayInfoMessage('Please fill all the empty fields', 'error');
highLightEmptyFields();
//return false;
return;
}
// check if username is in right format
if (!(regexTester(/^[A-Za-z0-9_]+$/g, usernameField.value))) {
displayInfoMessage('Username not valid', 'error');
highLightTextField(usernameField);
//return false;
return;
}
// check if username is atleast 3 characters long
if (usernameField.value.length < 3) {
displayInfoMessage('Username should contain atleast 3 characters', 'error');
highLightTextField(usernameField);
//return false;
return;
}
// check if password is in right format
if (!(regexTester(/^[A-Za-z0-9_]+$/g, passwordField.value))) {
displayInfoMessage('Password not valid', 'error');
highLightTextField(passwordField);
//return false;
return;
}
// check if password is atleast 6 characters long
if (passwordField.value.length < 6) {
displayInfoMessage('Password should contain atleast 6 characters', 'error');
highLightTextField(passwordField);
//return false;
return;
}
//return true;
// submit form information to server via ajax
ajaxFormSubmit();
}
// add submit event listener on login form
loginForm.addEventListener('submit', validateForm);
There is no guaranteed way to know that the form was submitted via ajax.
Normally this is done via headers, in our case HTTP_X_REQUESTED_WITH which can be retrieved via the global $_SERVER variable.
Do note that headers can easily be spoofed.
You can check like so:
if(isset($_SERVER['HTTP_X_REQUESTED_WITH']) && !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')
{
// code here
}
Here's a few links to look at:
https://paulund.co.uk/use-php-to-detect-an-ajax-request
How to check if the request is an AJAX request with PHP

Access $_POST data on a PayPal API returnURL

I have built a cart using localStorage and I'm using the PayPal PHP SDK to process the payment.
On clicking to pay by PayPal, via AJAX, I am posting $_POST the localStorage data (the cart) and form data (the user's details) to a PHP page where I have the PayPal API setup, which then grabs the $_POST data (to create the items, transaction, payment, redirectURLs) and on success it returns the approved URL to redirect to PayPal (using window.location.href, and this all works fine.
var formData = form.serialize();
var cartData = JSON.parse(localStorage.getItem('drfStorage'));
$.ajax({
url: rootURL + 'api/payment__paypal.php',
type: 'POST',
data: { formData: formData, cartData: cartData },
beforeSend: function() {
console.log('processing');
},
success: function(data) {
console.log('success!');
console.log(data);
window.location.href = data;
},
error: function(xhr,err) {
console.log('readyState: '+xhr.readyState+'\nstatus: '+xhr.status);
console.log('responseText: '+xhr.responseText);
}
});
Then my returnURL which is set as redirect__paypal.php?pp_success=true is visited, which if the $_GET request is 'success' then it validates and takes the payment.
This all works well up until this point. The next stage is that I want to send an email receipt to the user containing some of the data from the localStorage HOWEVER the issue is that on this returnURL there's no longer the localStorage stored in the $_POST request. I could obviously pass all this information as a $_GET request but don't really want this information in the URL (?email=&address=&order=) etc.
Is there any way or advice you can see me being able to access the localStorage OR $_POST data before it went off to PayPal on the returnURL?
Below is what is currently contained within my redirect__paypal.php to aid with explanation.
use PayPal\Api\Payment;
use PayPal\Api\PaymentExecution;
// Require relevent libraries
require_once('./sendgrid/sendgrid-php.php');
require_once('./api__paypal.php');
// SendGrid API init
$sgAPIKey = "REMOVED FROM EXAMPLE";
if (isset($_GET['pp_success'])) {
$approved = $_GET['pp_success'] === 'true';
if ($approved) {
$payerID = $_GET['PayerID'];
$paymentID = $_GET['paymentId'];
$payment = Payment::get($paymentID, $api);
$execution = new PaymentExecution();
$execution->setPayerId($payerID);
$payment->execute($execution, $api);
// Set email confirmation settings
$email_admin = 'REMOVED FROM EXAMPLE'; // Client
$email_customer = 'REMOVED FROM EXAMPLE';
$email_admin_subject = 'You have a new order from Testing McTest via PayPal';
$email_admin_customer = 'Your Testing McTest order';
ob_start();
require_once './confirmation__email--admin.php';
$email_admin_body = ob_get_contents();
ob_end_clean();
ob_start();
require_once './confirmation__email--customer.php';
$email_customer_body = ob_get_contents();
ob_end_clean();
// SendGrid init
function send_email($from_email, $to_email, $subject, $body/*, $attachments*/) {
global $sgAPIKey;
$from = new SendGrid\Email(null, $from_email);
$to = new SendGrid\Email(null, $to_email);
$content = new SendGrid\Content("text/html", $body);
$mail = new SendGrid\Mail($from, $subject, $to, $content);
//foreach($attachments as $a) {
// $mail->addAttachment($a);
//}
$sg = new \SendGrid($sgAPIKey);
$response = $sg->client->mail()->send()->post($mail);
}
// Send confirmation to customer first before it clears the attachments
if ($email_customer) {
send_email($email_admin, $email_customer, $email_admin_customer, $email_customer_body/*, $attachments*/);
}
// Send to confirmation to admin
if ($email_admin) {
send_email($email_admin, $email_admin, $email_admin_subject, $email_admin_body/*, $attachments = []*/);
}
} else {
}
}
I think you need to save your data somewhere before your redirct to PayPal.
On a redirect, all $_POST fields are lost.
The easist way is to save all data in your session ($_SESSION)
You can grab it from there when you are back from PayPal ;)

retriving user information through Paypal Javascript login button

i have integrated paypal login button (javascript button) and when i am clicking on it its getting to the paypal site for authentication.
following is my code for paypal button
<span id="paypal"></span>
<script src="https://www.paypalobjects.com/js/external/api.js"></script>
<script>
var url = document.URL;
paypal.use( ["login"], function(login) {
login.render ({
"appid": "***",
"authend": "sandbox",
"scopes": "profile email address phone https://uri.paypal.com/services/paypalattributes",
"containerid": "paypal",
"locale": "en-us",
"returnurl": "http://stereotribes.dev/login"
});
});
</script>
after successful authentication its redirecting me to my server url again.
now my question is how to receive user information after authentication done.
i have searched around paypal site but i am not getting the clear idea to retrieve user informatoin.
can anybody help me in this?
Thanks in advance
Take a look at Instant Payment Notification (IPN). It will POST transaction data to a listener script you have configured on your server immediately when transactions happen, so you can automate tasks like updating your database, sending email notifications, etc. in real-time.
If you need data available on your return URL you can use Payment Data Transfer (PDT), which is very similar to IPN. The only thing about that is if people don't make it back to your return URL for some reason then that code will never run, so it's not recommended that you do any database updates, email notifications, or anything like that from your return URL.
Again, IPN will be triggered regardless of whether they make it back, so you can rest assured that code will run as expected.
After wasting 1 day i came up with the following code(solution), hope it may save someone's time ...
in my return url ("http://stereotribes.dev/login") i have written following code ...
if($_REQUEST['code']) {
$model->getPaypalEmail($_REQUEST['code']);
}
$_REQUEST['code'] (token) will be send by paypal and same code we have send back via curl to confirm identity...
public function getPaypalEmail($code){
if($code){
$strGetCodePaypalLoginDetails = $code;
if ($strGetCodePaypalLoginDetails != '') {
// Change this curl_init url according to your environment.
$ch = curl_init("https://api.sandbox.paypal.com/v1/identity/openidconnect/tokenservice");
$flag_result = 1;
curl_setopt_array($ch, array(
CURLOPT_POST => 1,
CURLOPT_POSTFIELDS => 'client_id=********&client_secret=*****&grant_type=authorization_code&code=' . $strGetCodePaypalLoginDetails,
CURLOPT_RETURNTRANSFER => 1
)
);
$arrResponse = curl_exec($ch);
if ($arrResponse === false) {
$arrResponseToken = 'Curl error: ' . curl_error($ch);
$flag_result = 0;
} else {
//Operation completed without any errors
$arrResponse = json_decode($arrResponse);
$strAccess_Token = $arrResponse->{'access_token'};
// Change this curl_init url according to your environment.
$chToken = curl_init("https://api.sandbox.paypal.com/v1/identity/openidconnect/userinfo/?schema=openid&access_token=" . $strAccess_Token);
curl_setopt_array($chToken, array(
CURLOPT_RETURNTRANSFER => 1
)
);
$arrResponseToken = curl_exec($chToken);
if ($arrResponseToken === false) {
$arrResponseToken = 'Curl error: ' . curl_error($chToken);
$flag_result = 0;
}
}
}
$arrResponseToken = json_decode($arrResponseToken, true);
print_r($arrResponseToken); //here you will get info from paypal
}
}

How is a plugin like facebook login plugin build up?

How does the plugin communicate with the facebook server without exposing too much information.
I would like to know how I can build myself a plugin that would communicate between the website it's installed on and my website.
My knowledge is limited to HTML5, CSS3, PHP5, Javascript and some Jquery.
I realise that there could be alot of ways, I was just wandering if you could point me in the right direction, or give me an idea. (: thanks in advance!
Take a look at the easyXDM framework, which allows you to do this quite easily, and if you have a chance, read Third Party JavaScript, which explains what you want to do in detail.
Some years ago, I wrote about this topic on scriptjunkie, it's as relevant now as then (although more browsers support postMessage now).
Create an application on developers.facebook.com
Download the facebook SDK for PHP since this is what you know (https://developers.facebook.com/docs/reference/php)
Read their guideline on how to implement login (it is easy and helpful)
https://developers.facebook.com/docs/facebook-login/login-flow-for-web/
This is a sample PHP function that you can build on:
function facebook_login()
{
$user = new user();
// Call Facebook API
if (!class_exists('FacebookApiException')) {
require_once ('facebook.php');
}
$facebook = new Facebook(array(
'appId' => $app_id,
'secret' => $app_secret,
));
$fbuser = $facebook->getUser();
if ($fbuser) {
try {
// Proceed knowing you have a logged in user who's authenticated.
$me = $facebook->api('/me'); //user
$uid = $facebook->getUser();
}
catch(FacebookApiException $e) {
echo error_log($e);
return;
}
}
// redirect user to facebook login page if empty data or fresh login requires
if (!$fbuser) {
$loginUrl = $facebook - getLoginUrl(array(
'redirect_uri' => $_SERVER["HTTP_REFERER"],
false
));
$logout = $facebook->getLoginUrl();
echo $loginUrl;
return;
}
// user details
$user->name = $me['name'];
$user->email = $me['email'];
$user->fbid = $uid;
// Check user id in your database
$user->selectbyfbid();
if ($user->database->rows > 0) {
// User exist, Show welcome back message
// User is now connected, log him in
}
else {
// User is new, Show connected message and store info in our Database
// Insert user into Database.
$user->insert_fb();
}
$_SESSION["access_token"] = $facebook->getAccessToken();
login_user($user);
}
In your HTML:
<a href="#" onclick="LoadingAnimate();">
<div class="fb-login-button"
onlogin="javascript:CallAfterLogin();"
data-width="600" data-max-rows="1"
data-show-faces="false"
scope="publish_stream,email,publish_actions,offline_access">
JavaScript code:
function CallAfterLogin(){
FB.login(function(response) {
if (response.status === "connected")
{
LoadingAnimate(); //show a waiting gif or whatever
FB.api('/me', function(data) {
if(data.email == null)
{
//Facbeook user email is empty, you can check something like this.
ResetAnimate();
}else{
AjaxResponse();
}
});
}
});
}
function AjaxResponse()
{
var myData = 'connect=1&action=fb_login';
jQuery.ajax({
type: "POST",
url: "/process_user.php",
dataType:"html",
data:myData,
cache: false,
success:function(response){
if(target.length > 1)
window.location.href = target;
else
location.reload();
},
error:function (xhr, ajaxOptions, thrownError){
//$("#results").html('<fieldset style="color:red;">'+thrownError+'</fieldset>'); //Error
}
});
}
I hope this helps you start!

PHP Comet cause page reload slow

Hi I am tring to implement the comet with PHP and jquery. The comet is started on every page load. However it cause loading of any page in the website become very slow like 10 seconds, it seem to be waiting for the previous request to the server to die() at the if($elapse > 10)
But if a ajax connection connection is aborted, isn't the PHP should stop executing furher ? Any idea why reloading page become slow ?
function getPendingCheckin()
{
ignore_user_abort(false);
$iCreatedDate = $this->input->post("iLastCreateDate");
$aCheckin = [];
$prev = time();
while(! $aCheckin )
{
$aCheckin = $this->getData();
if($aCheckin || connection_aborted() == 1)
{
break;
}
else
{
sleep(1);
$elapse = time() - $prev;
if($elapse > 10)
{
die();
}
}
}
header('Content-type: application/json');
echo json_encode($aCheckin);
}
Javascript
$(window).ready(function(){
var iLastCreateDate = $('#iLastCreateDate').val();
function startGetPendingCheckin()
{
$.ajax({
type: "POST",
url: "/kc/comet/getPendingCheckin",
data: 'iLastCreateDate=' + iLastCreateDate,
error : function(msg)
{
//alert("Error get pending checkin");
},
success :function(o)
{
if(o)
{
//process data
}
startGetPendingCheckin();
}
});
}
startGetPendingCheckin();
})
No, php execution is not (always) aborted. I noticed that on heavy scripts runned on local machine.
You may fail to run 2 parallel request to php scripts due to not closed session. Usually it is auto-closed after termination of the script. With default behavior (sessions in lockable files, no manual closing) it is not possitble to have 2 simultaneous requests from the same user — the latter would be blocked by the former and will wait for its termination.
You may close session as long as you checked everything about user authorization.

Categories

Resources