Recently, I have created a website where one can read temperature and humidity values, and set the wanted temperature value for an IoT device. For security, the IoT values can only be read or set when the user has logged in. This is done by setting the session ID when the login was successful.
Relevant part of login script:
<?php
if ($userData['username'] == $username && $userData['password'] == $password) {
echo "Login success.";
session_start();
$_SESSION['nID'] = true;
header('refresh: 3; url=app/index.php');
}
?>
The login is handled with a POST request.
As you can see, the user is redirected to app/index.php whenever the login was successful.
On the start of app/index.php, it is being checked if the session ID is set. If this is not the case, the user will be redirected to the login page.
Relevant part of app/index.php:
<?php
session_start();
if (!isset($_SESSION['nID'])) {
header("Location: ../index.html");
die();
} else {
//other content of the page
?>
This seems to be working correctly when I test it on my computer in a web browser. Now I am trying to make an Android application in Kotlin which first logs in with a POST request and then reads the values with a GET request using Fuel library.
Relevant part of the Android application:
val loggedIn = false
FuelManager.instance.basePath = "https://red2503.nl";
fun logIn(webPage: String, username: String, password: String) {
Fuel.post(
webPage,
listOf("username" to username, "password" to password)
).responseString { request, response, result ->
when (result) {
is Result.Failure -> {
val ex = result.getException()
Log.d("FAIL", ex.toString())
lock.unlock()
loggedIn = false
}
is Result.Success -> {
val data = result.get()
Log.d("SUCCESS", data.toString())
if (data.toString().contains("Login success.")) {
loggedIn = true
} else {
loggedIn = false
}
lock.unlock()
}
}
}
lock.lock() //wait for response
}
fun displayToast(text: String) {
val duration = Toast.LENGTH_LONG
val toast = Toast.makeText(applicationContext, text, duration)
toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0)
toast.show()
}
fun readTemperatureHumidity(webPage: String) {
Fuel.get(FuelManager.instance.basePath + "/" + webPage)
.response { request, response, result ->
println(request)
println(response)
val (bytes, error) = result
if (bytes != null) {
println("[response bytes] ${String(bytes)}")
}
}
}
submitButton.setOnClickListener {
logIn("iot/login.php", /* USERNAME */, /* PASSWORD */)
if (loggedIn) {
readTemperatureHumidity("iot/app/index.php")
} else {
displayToast("Login failed. Check internet connection.")
}
}
I know the login is working correctly, because the response of the login is "Login success.". However, when I send the GET request to app/index.php after logging in, the website redirects me to login form at ../index.html, but I expect it to reply with the values because the login was successful. I think this happens because the session ID does not stay set between the two HTTP requests. How can I solve this problem?
I think I gave all relevant information about the website and the application. If some parts unclear, please let me know.
I had to store the cookie of the response of the first request, and place it in the second request. See the answer to this post:
Setting cookie properly in fuel requests
I've created csrf_token and stored in session variable. while the form submission checked post variable with the session variable. It works perfectly in HTTPS but not in HTTP incognito window.
I just figure out this problem it's because of session value is varying each time on the HTTP request.
give me suggestion to solve this issue. Thanks!
if (! isset($_SESSION['csrf_token'])) {
$_SESSION['csrf_token'] = md5(uniqid());
}
if(isset($_POST['token']))
{
if (($_POST['token'] === $_SESSION['csrf_token'])) {
echo "match";
}
else{
echo "mismatch";
}
}
I'm trying to access a cookie's value (using $_COOKIE) immediately after calling the setcookie() function in PHP. When I do so, $_COOKIE['uname'] isn't set. Why?
Note, however, that $_COOKIE['uname'] is set as expected upon the next execution of the script, such as after a page refresh.
setcookie('uname', $uname, time() + 60 * 30);
echo "Cookie value: " . $_COOKIE['uname'];
The cookie isn't set until the response is sent back to the client, and isn't available in your PHP until the next request from the client after that.
However, when you set the cookie in your script, you can do:
setcookie('uname', $uname, time()+60*30);
$_COOKIE['uname'] = $uname;
$_COOKIE is set when the page loads, due to the stateless nature of the web. If you want immediate access, you can set $_COOKIE['uname'] yourself or use an intermediate variable.
For example:
if (isset($_COOKIE['uname'])) {
// get data from cookie for local use
$uname = $_COOKIE['uname'];
}
else {
// set cookie, local $uname already set
setcookie('uname', $uname, time() + 1800);
}
If you want to access a cookie's value immediately after calling the setcookie() you can't use $_COOKIE. The reason for this is in the nature of the protocol (see https://www.rfc-editor.org/rfc/rfc6265). When you use setcookie() it defines a Cookie to be sent along with the rest of the HTTP headers to the client (see http://php.net/manual/en/function.setcookie.php). But $_COOKIE on the other hand contains variables passed to the current script via HTTP Cookies from the client (http://php.net/manual/en/reserved.variables.cookies.php).
When you change $_COOKIE after calling setcookie() - like some answers here recommend - it doesn't contain only the Cookies from the client any more. This could interferer with assumptions made in third party code used in your application and may result in unwanted site effects. So in general it's not good practice and it's only an option when the calls of setcookie() are part of your own code.
A clean and transparent way to get a value set with setcookie() within the same request is to use headers_list() (see http://php.net/manual/en/function.headers-list.php):
function getcookie($name) {
$cookies = [];
$headers = headers_list();
// see http://tools.ietf.org/html/rfc6265#section-4.1.1
foreach($headers as $header) {
if (strpos($header, 'Set-Cookie: ') === 0) {
$value = str_replace('&', urlencode('&'), substr($header, 12));
parse_str(current(explode(';', $value, 1)), $pair);
$cookies = array_merge_recursive($cookies, $pair);
}
}
return $cookies[$name];
}
// [...]
setcookie('uname', $uname, time() + 60 * 30);
echo "Cookie value: " . getcookie('uname');
But notice this won't work in PHP CLI (e.g. PHPUnit). In such a case you could use third party extensions like XDebug (see http://xdebug.org/docs/all_functions#xdebug_get_headers).
You have to set the cookie variable by yourself if you need it immediately, by the time you load another page the real cookie would have been set as a result of the setcookie method.
setcookie('name', $value, time()+60*30);
$_COOKIE ['name'] = $value;
We can do this using AJAX calling.
If we want to create cookies on button click so first create a AJAX call for creating cookies then the success of first AJAX calling we can call another AJAX for getting the cookies.
function saveCookie() {
var base_url = $('#base_url').val();
var url = base_url + '/index/cookie';
$.ajax({
'url': url,
'type': 'POST',
'success': function (data) {
if (data) {
var url = base_url + '/index/get_cookie';
$.ajax({
'url': url,
'type': 'POST',
'success': function (response) {
var container = $('#show');
if (response) {
container.html(response);
}
}
});
}
}
});
}
<button type="button" onclick="saveCookie()">Save Cookie</button>
<div id="show"></div>
I had a similar problem where i used a function from a included file and solved it with a function that both returns the value of the cookie and sets the cookie.
function setCookie($input) {
setcookie('uname', $input, time() + 60 * 30);
return $input;
}
if(!isset($_COOKIE['uname'])) {
$uname = setCookie($whatever);
} else {
$uname = $_COOKIE['uname'];
}
echo "Cookie value: " . $uname;
Using ob_start() and ob_flush() you can send the cookie to client and retrieve it in the same run time. Try this:
ob_start();
setcookie('uname', $uname, time() + 60 * 30);
ob_flush();
echo "Cookie value: " . $_COOKIE['uname'];
Your script's setcookie() function runs when the web browser requests the page for the first time, in your case the reload. This cookie is stored in the users browser and isn't available to your script running on the server until the next request, or in your case the next reload.
Upon the next request the browser sends that cookie to the server and the array $_COOKIE will have the value that you initially set and the browser sent back upon the second request.
I set a constant at the same time the cookie was created
define('CONSTANT', true);
return setcookie('cookiename', 'cookie value goes here', time() + 60 * 60 * 24 * 30, '/');
I can then immediately do something by:
if(isset($_COOKIE['cookiename']) || $_COOKIE['cookiename'] || defined('CONSTANT') && CONSTANT)
I'm working on a HTML5 mobile app. The app only uses 1 html file which contains a login form. On submit javascript posts the username and password to a php script on the server which returns 'true' or 'false'.
When the authentication returns true the app changes the html5 page and stores the username and password in html5 local storage.
Since this is sensitive data my question is how to store these values in a secure way?
function handleLogin() {
var form = $("#loginForm");
var u = $("#username", form).val();
var p = $("#password", form).val();
if(u != '' && p!= '') {
$.post("http://www.mywebsite.com/login.php", {username:u,password:p}, function(res) {
if(res == true) {
//store
window.localStorage["username"] = u;
window.localStorage["password"] = p;
$.mobile.changePage("index-2.html");
} else {
/// error message
}
$("#submitButton").removeAttr("disabled");
},"json");
}
return false; }
I would suggest using Access tokens, since this can be updated and changed frequetly, it also doesnt reveal who the user or what their hashed password is.
http://php.net/manual/en/oauth.getaccesstoken.php
Edit: You do NOT want to use localStorage!
I am having trouble getting jQuery ajax to recognise a session. I am creating a php session from a login script, but what is happening is that when ajax loads the authenticated page, the session is always unset. For example, in the secure page, if I refresh the page, the session id changes each time. I have session_start(); in each page. Can someone please show me the correct way to handle sessions with ajax and php? I have spent 2 days and have used google so much, I will probably get an invite to there xmas lunch :-) I have included the relevant code and would be grateful for any help. Thanks
PS. If it makes any difference, I am trying to develop mobile app using jquery mobile.
login html js
$(function() {
$("#kt_login1").click(function() {
var user = $('#user').val();
var pass = $('#pass').val();
if (user == '') {
$("#login_message").html('This field cannot be empty')
$('label[for=user]').addClass("label")
return false;
}
else if (pass == '') {
$("#login_message").html('This field cannot be empty')
$('label[for=pass]').addClass("label")
return false;
}
else $('label[for=user]').removeClass("label");
$('label[for=pass]').removeClass("label");
//alert(user + pass + ok);
data = 'user=' + user + '&pass=' + pass;
$.ajax({
type: "POST",
url: "testajax.php",
cache: false,
data: data,
success: function(data) {
if (data == 'authenticated') {
//alert(user);
document.location = 'secure.php';
}
else $('#login_message').html('You are not authorised');
//$(ok).val('Logged In');
//$("#login").get(0).reset();
//$("#form").dialog('close');
},
error: function(xhr, ajaxOptions, thrownError) {
jAlert('There was an exception thrown somewhere');
alert(xhr.status);
alert(thrownError);
}
});
return false;
});
});
testajax.php
<?php
// test wether the user session is already set
$username = mysql_real_escape_string($_POST['user']);
$pass = mysql_real_escape_string(md5($_POST['pass']));
mysql_connect('localhost', 'root', '');
mysql_select_db('sample');
//now validating the username and password
$sql="SELECT * FROM user_usr WHERE username_usr='$username' and password_usr='$pass'";
$result=mysql_query($sql);
$row=mysql_fetch_array($result);
//if username exists
if(mysql_num_rows($result)>0) {
session_start();
$_SESSION['u_name']=$row['name_usr'];
/*
echo '<pre>';
print_r( $_SESSION['u_name'] );
print_r( $_REQUEST );
echo '</pre>';
exit;
*/
echo 'authenticated';
}
else
{
echo 'Unknown User';
}
?>
+++++SOLUTION+++++
Changed form input from submit to button and voila. All ok
you have to call session_start() each time working with a session (not only when creating it)
see: http://php.net/manual/en/function.session-start.php
There are a whole load of reasons this might be the case - but you're code is upside down! This may well be the cause (or a contributory factor).
You should not treat the existence of a session as evidence of authentication (the contents of the session is another thing altogether). Call session_start() at the top of your script - not conditionally, half-way through.
As to why your session data is not available...that's an FAQ here - have a look at some of the previous answers for potential causes / how to investigate.