I am working on a social networking site using PHP, MySQL(PDO), JQuery, and HTML(CSS). I'm working on the profile page right now and I want to determine if the user is on their own page or another's to determine what inputs they'll have. I would like to keep a framework for the profile page and load the respective options rather than having 2 different pages (my profile vs other profile).
I'm learning JQuery and PHP as I go, so right now I am thinking, in JQuery, I can get the $_GET (?username= ) and compare it to the user id of who's logged in, then load the components I need based on that.
Or I determine the user in PHP then run a certain scrip to load the components.
Would on of these ways work, or is there a different/better way to do this?
I don't think you can use $_GET in JavaScript.
Instead, there is a URLSearchParams
const url = new URL('http://domain/path?username=someone');
const username = new URLSearchParams(url.search).get('username)'; // someone
The best security practice is to not rely on anything happening in browser.
This means you should always figure out privileges on the server (on PHP side).
Variant 1 (Simple)
Let's assume you have authenticated the user and have the user as $currentUser and their id as $currentUser->id in PHP.
Now this user wants to view some profile by requesting url "profile?id=555"
So here's (basically) what you do on PHP side:
$requestedProfile = (int)$_GET['profile'];
if ($requestedProfile == $currentUser->id) {
// they want own profile
show_controls_for_own_profile();
} else {
// they want someone else's profile
show_controls_for_other_profile();
}
In this case, jQuery has nothing to do here.
Variant 2 (Separate requests)
Further, let's assume you want to cache the entire profile page to quickly load it into browser, and only after that, ajax-load additional controls associated with user's privileges.
then you have two controller methods (php scripts, whatever) each serving it's own part:
public function showProfile() {
$requestedProfile = (int)$_GET['profile'];
if (profile_exists($requestedProfile)) {
show_the_profile($requestedProfile); // no check here
}
}
The method above would return the generic profile page by its ID (with empty ".controls" element) and on that page, some jquery code would ask the server to return appropriate variant of user-dependent part.
$.ajax('/user-controls.php')
.done(function(response) { $('.controls').html(response); });
Notice it does not tell the server any user ID - server should already know current authenticated user ID from the session!
The second function, same as in the beginning, will return just HTML for the controls:
// Example of getting current profile from server's headers
function get_viewed_profile_id()
{
// url of previous profile page, e.g. http://example.com/profile?id=555
$referer = $_SERVER['HTTP_REFERER'];
$query = parse_url($referer, PHP_URL_QUERY); // id=555
parse_str($query, $params); // ['id' => '555']
return $params['id']; // 555
}
// we should store the authenticated user in session,
// not rely on anything user sends from their browser
$currentUserId = $_SESSION['user']->id;
$requestedProfileId = get_viewed_profile_id();
// now that we know both viewed profile and current user,
// we can compare them
if ($requestedProfileId == $currentUserId) {
// they want own profile
show_controls_for_own_profile();
} else {
// they want someone else's profile
show_controls_for_other_profile();
}
Variant 3 (Passing PHP variable to javascript)
Same as above, but you don't rely on $_SERVER['HTTP_REFERER'], and move some logic to Javascript instead:
Browser asks:
// look up currently browsed profile from current window url
var q = new URLSearchParams(window.location.search);
var controlsURL = '/user-controls.php?viewedProfile=' + q.get('id');
// ask for controls, specifying the currently browsed profile
$.ajax(controlsURL)
.done(function(response) { $('.controls').html(response); });
And server responds with:
function get_viewed_profile_id()
{
return (int)$_GET['viewedProfile'];
}
// we should store the authenticated user in session,
// not rely on anyhting user sends from their browser
$currentUserId = $_SESSION['user']->id;
$requestedProfileId = get_viewed_profile_id();
// now that we know both viewed profile and current user,
// we can compare them
if ($requestedProfileId == $currentUserId) {
// they want own profile
show_controls_for_own_profile();
} else {
// they want someone else's profile
show_controls_for_other_profile();
}
in jquery you can use $.get() with datatype html
You can echo the PHP's GET value in JavaScript. But make sure, without makeItSafe (which you have to define yourself) this code can be exploited to perform cross site scripting attacks:
<script>
var myGlobalUserID = "<?php echo makeItSafe($_GET['userID']); ?>";
</script>
Simply declare one hidden field on page
<input type="hidden" id="username" value="<?php echo $_GET['username'];?>">
Get username value in it.
Then simply fetch that value in jquery
<script>
$(document).ready(function(){
var username = $("#username").val();
if(username == "abc"){
$("#div_one").show();
$("#div_two").hide();
}
});
</script>
using if() condition and hide() , show() method load component which you want to show to user.
Related
I'm using Ext.Ajax.request() to hit a PHP page that gives me some user specific info as a part of a login process. Basically I want to store some variables (cookie, session information, etc) in ExtJS. I created a model with the needed fields and a store to keep it. Even though the authentication is done only once I want to ensure that on a given time there is only one copy of the user's info. I want to use that info to hit PHP again without having to authenticate again (cookies).
Here's how I fetch it and store it:
Ext.Ajax.request({
url: 'api/get.php',
params: {
user : usr,
pass : pass
},
success: function(response)
{
var text = response.responseText;
var jtext = Ext.JSON.decode(text);
var login = jtext.loginData;
model.set('username', login.username);
model.set('cookie', login.cookie);
model.set('password', login.password); // doing this feels soo wrong!
store.insert(0, model);
store.sync();
console.log(store.getCount());
}
});
What is the better way of doing it? Since I'm using an external (to the PHP) service currently I only check if the user/pass is correct and if it is, I pass it from the client-side to the PHP functions that do whatever they have to do with the external service, authenticating each time with them. Alternatively I can pass the cookie each time to the PHP that in turn passes it down. I can also map JS<->PHP cookies to PHP<->service cookies and that would be even better.
Cheers!
Ext.util.Cookies.set('myObj',Ext.encode(obj))
Use something like this and when you want to use it
id = (Ext.decode(Ext.util.Cookies.get('myObj'))).id
I want to set a session variable to 0 when any of a certain set of links are clicked. To do this I have put the following in my javascript file:
$(window).load(function () {
$("#hdr li a").click(function () {
$.ajax({
type: "POST",
url: "clear.php",
data: "width=0"
});
});
});
(Ignore data: "width=0"... I don't use this data in clear.php. I put it there because I thought maybe I had to specify a data field.)
and in the file 'clear.php' I simply have:
<?php session_start();
$_SESSION['name'] = 0;
?>
So, the idea is that when any of the links in #hdr li are clicked, the user should be taken to the page that the link points to, via clear.php, which sets the session variable to 0.
This works in some browsers (Firefox and Chrome) but not in others (e.g., Safari).
Is this the standard/correct way to implement what I want? Also, how does the browser know where to go after visiting clear.php? Somehow it works, but my first thought was that I should pass the final destination URL into clear.php, and then use "header" to move from clear.php to the final destination.
Is Ajax required? If your re-directing the user to another page & you simply want to pass some data to that page then it may be simpler to include that data in your URL.
Link
Now your php would be simple:
$_SESSION['name'] = $_GET['new_session_variable'];
Now you've removed your dependency on JavaScript, does that make sense? :)
I feel it might be worth mentioning that your approach would be appropriate in certain situations, for example: if you wanted the user to be able to mark one of the links on the page as a favourite. Rather than redirecting them to the same page and reloading the majority of the pages content you might:
<a class="favourite" data-linkid="link123" href="mylink.php">My Link</a>
// Ensure your page has finished loading aka: 'ready' (almost always)
$(document).ready(function() {
// Listen for the click event
$('.favourite').on('click', favoriteLink);
// On the click - post the update via ajax and update your interface
function favoriteLink(event) {
event.preventDefault();
// Lets get the link id from our data attribute
var favourite_link = $(this).data('linkid');
// Post that information via ajax
$.post('ajax_handler.html', { link : favourite_link }, function(data) {
// And finally do something with the result!
$('.result').html(data);
});
}
My guess is this has something to do with the asynchronicity of AJAX, some browsers are properly firing the AJAX before the new link is loaded. Others might be canceling the AJAX request because the page is changing. Try preventing the default action of the anchor, and then use window.location to redirect them after the ajax call has returned.
$("#hdr li a").click(function (e) {
var href = $(this).attr('href');
e.preventDefault()
$.post("clear.php", function () {
window.location = href;
});
});
The visitor do not get to clear.php page since you are performing an ajax call.
Instead, what happens is that your browser sends a request underneath via javascript using XMLHTTPRequest object which do not break your browser behavior and as such load the page the a href points to.
As said : the ajax call is usless. You'd better include clear.php on top of your pages and test if whether or not you should set your session var, based on get param for exemple.
If you do want to keep the ajax call before the browser gets to a new page, you may attach an event handler on first common parent of your "resetting" links (event delegation) and test if you should send an ajax request to notify clear.php
I had this problem. I wanted to pass a different sql string to select different rows from a table depending on the link the user clicked on but i did not want to display the sql in a GET.
My solution was to set different session variables for each link and pass the NAME of the session variable from the link. I had several links but I have just included 2 here for the example. My code for the links was:-
<?php $_SESSION["extend_stats_sql_01"] = "";
echo ' View';}?> <br>
and
<?php $_SESSION["extend_stats_sql_02"] = " Where booking_status = 'Cancelled'";
echo ' View';}?> <br>
My code to retrieve the values on my next page to display the list with the correct sql depending on the link was:-
$stats_sql = "SELECT id, name, activity, email, diving_date, arrival_date, checkin_date, create_date, seller FROM guests ";
$sort = $_GET['sort'];
$sent= $_GET['sent'];
$result = $_SESSION["$sent"];
$stats_sql.= "$result";
$stats_sql.= " ORDER BY $sort";
obviously you need to start a session at the beginning of each page :-
session_start();
and when you have finished :-
// remove all session variables
session_unset();
// destroy the session
session_destroy();
I've been messing with a script, and i'm now currently at the protection part.
Basically i cant manage to receive a $_session['username'] request.
I can not use cookies, as these can be faked. And it's a pretty big security hole.
Is this a common issue?
(The non-ajax and ajax page have the same session-id, and yes. i do use session_start();)
If you know any good comment-scripts it would be appriciated if you would like to link! c: )
edit:
The user logs in, and the session is started.
Now i'm combining a page/post with a modified comment script. (found here: http://tutorialzine.com/2010/06/simple-ajax-commenting-system/ )
What i've done is that i made it work with multiple pages, and removed the user & password thing that was provided with the script.
The request is something similar to this:
$user = $_session['username'];
if(!($data['user'] = $user)){
$errors['error'] = $_session['username']; //just to see if it can find the username
}
The above request returns a null value, but if i run "echo $_session['username'];" on the page that calls java, i get "powback".
EDIT:
i couldn't get this to work, but i made a bypass. I managed to insert $_session['username'] directly into the database with an other kind of validation. The current one was stupid... It should work properly now. Thank you!
How are you passing the session ID if not via a cookie? If you're passing it via URL (which is an even bigger security risk), make sure you pass it in the URL of your AJAX request.
Try this
var v="any variable to be passed";
$.post( "passingfile.php",{name:v},
function(data) {
Alert("Pass OK");
});
return false;
});
If you for the security try not to pass session id via url
you can use this inside any function or document ready. and change page name where you want to post value.
var postRecord = 'variable='+value;
$.post("PHP_Page_Where_you_are_using_session.php", postRecord, function(response,status, xhr){
if (status == "success") {
alert('done');
}
else if (status == "error") {
alert('Something went wrong, we are working to fix it');
}
});
on another page you can get post value within $_POST['variable'];
change name of variable to another one that you want to use.
Frankly, it's just causing too much hassle in in v1.0 to have a functionality which requires three form submissions, with $_SESSION session data holding all of the intermediate stuff - only to have a user start an operation, then open a second tab and perform a second operation which tramples over the session data.
I doubt that this is malicious (but can’t discount it). More likely the user starts an operation, gets interrupted, forgets that they started or can’t find the original tab so starts again (then later finds the original tab and tries to complete the operation a second time).
Since I am coding in PHP I can detect the existence of session data on form submission (how would I do that with JS if the user as much as opens another tab – I guess that I would need Ajax – right?).
So, each time I start an operation I check for a flag in session data and if set I reload to a “I’m sorry, Dave. I’m afraid I can’t do that” page, else I set the flag and continue (remembering to clear it at the end of the operation).
I guess that that would work, but:
1) Is it acceptable to restrict browser apps to a single tab/instance?
2) Should I attempt to allow multiple instances in v2.0 ?
Any other comments, help or advice?
A better design would be to avoid storing user interaction state in the session. Put it in hidden form fields or something so that each client request carries its associated state with it. If you're concerned about the user tampering with it, use an HMAC to prevent that, and possibly encrypt it if it contains things the user shouldn't be able to see.
Only state that should be shared between tabs — like the user's login identity, or something like a shopping cart — should be stored in the session.
At most you can is keep a "last requested page" listing in the session file, with flags to indicate that the user shouldn't be allowed to move off it if it's one of these critical form flags. So if you're on form.php and it's a no-move-off one, then any new page loaded should present an "abort or close window" option.
You cannot prevent a user from opening up another tab/window, but you can prevent them from moving elsewhere in your site in those other windows/tabs.
However, consider that this is a very poor user experience. Imagine if Amazon trapped you in the shopping cart page and never let you on to another page without having to actually buy something. Consider updating your code to allow multiple different windows use the same form.
With every browser supporting tabbed browsing it would be a poor user experience to try to restrict browsing to a single tab (you might as well make a desktop app then).
One way you could solve this is by adding a CSRF token to your forms (as a hidden variable), that would be submitted with the request.
CSRF reference
There are many ways to generate the token, but essentially you:
create the token
store in your $_SESSION
output the form with <input type="hidden" name="{token name}"
value="{token value}" />
Then when the form submits you check $_REQUEST['{token name}'] == $_SESSION[{token name}]`.
If that token is different you know it wasn't the form you originally generated and thus can ignore the request until the real form comes in with the correct token.
One thing: if an attacker can figure out how you generate your CSRF tokens then they can forge requests.
Added the below script after I login(say dashboard.php)
<script>
$(document).ready(function()
{
$("a").attr("target", "");
if(typeof(Storage) !== "undefined")
{
sessionStorage.pagecount = 1;
var randomVal = Math.floor((Math.random() * 10000000) + 1);
window.name = randomVal;
var url = "url to update the value in db(say random_value)";
$.post(url, function (data, url)
{
});
}
else
{
var url = "url to remove random_value";
$.post(url, function (data, url)
{
sessionStorage.removeItem('pagecount');
sessionStorage.clear();
window.location = 'logout.php';
});
}
});
</script>
Added the below script in Header in rest of my pages - 'random_value' is from db for that user
<script>
$(document).ready(function()
{
$("a").attr("target", "_self");
if(typeof(Storage) !== "undefined")
{
if (sessionStorage.pagecount)
{
if('<?=$random_value?>' == window.name)
{
sessionStorage.pagecount = Number(sessionStorage.pagecount) + 1;
}
else
{
var url = "url to remove random_value";
$.post(url, function (data, url)
{
sessionStorage.removeItem('pagecount');
sessionStorage.clear();
window.location = 'logout.php';
});
}
}
else
{
var url = "url to remove random_value";
$.post(url, function (data, url)
{
sessionStorage.removeItem('pagecount');
sessionStorage.clear();
window.location = 'logout.php';
});
}
}
else
{
var url = "url to remove random_value";
$.post(url, function (data, url)
{
sessionStorage.removeItem('pagecount');
sessionStorage.clear();
window.location = 'logout.php';
});
}
});
</script>
If I were doing this now, I would probably code a single page AngularJs app (although any form of Js will do).
On start-up, look in local storage for a flag. If set, refuse to start, with suitable message, else set the flag & run the app.
Sure, a malicious user could get around it, since it's not a server-side check, but I would just refuse to support such.
I am working on a codeigniter site, the client has requested that the price columns in a datatable are hidden from view unless a user enters a correct password(which they will give out to clients over the phone).
The obvious way is to make the user login which then reveals a new table/page with prices included.
Can I achieve this via AJAX somehow?, i.e. a dialog box appears, the user enters a password, a request is sent and a new table loads with prices included?
I am a total rookie at Codeigniter, but I am learning everyday, please could someone point me in the right direction?
Thanks
Dan
actually its not really a code igniter issue, more javascript. add a controller function in ci which you call via ajax (a javascript framework like jquery is highly recommended).
to keep it simple you could add the password to the request. the controller function checks the password and if its correct it echos the price.
the javascript code might look something like that:
$.ajax({
type: "POST",
url: 'controller/function',
data: {'password': $('#password').attr(value)},
success: function(data){
$('#price').html(data);
},
});
You could achieve it via ajax: it would work something like this:
1.) User enters password in box and clicks button
2.) Click event on button triggers the following:
var xmlhttp = new XMLHttpRequest();
xmlhttp.open('POST', 'getPrices.php', true);
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4) {
if (xmlhttp.readState == 200)
putPricesIntable(xmlhttp.responseXML)
}
}
xmlhttp.send('password=' + 'password');
This question really has very little to do with a specific language or framework, but more a matter of how to best approach a problem. The problem in this case is displaying a column only if a password is entered correctly. So first you need to have a means of allowing the user of the website to enter the password. How this is done is again fairly irrelevant, it could be a form on the page, or it could be a separate page.
Once the password is submitted and found to be correct a session will need to be created for the user. This session is basically what will tell the page whether or not to display the column.
You would probably not want to solely rely on an ajax method as if the user has JavaScript disabled then they would never be able to see the column, instead only use JavaScript to enhance the usability of the website.
Ajax just means your login controller will return something machine readable (json/xml) rather than html.
Your controller really just needs to set a session variable.
class Login extends Controller {
function __construct() {
parent::Controller();
$this->load->model('user_m');
}
function json_login() {
$user = $this->user_m->get_user($_POST['username']);
if($user->password == md5($_POST['password'])) {
$this->session->set_userdata('username',$user->username);
print json_encode($this->user);
}
else {
print json_encode(FALSE);
}
return;
}
function logout() {
$this->session->destroy();
redirect('/theloginpage');
}
}
Assuming you are using jquery for the javascript the ajax call could work something like this:
$('#login_form').submit(function(event) {
event.preventDefault();
$.ajax({
type:"POST",
data:$(this).serialize(),
dataType:"json",
url:"/login/json_login",
success: function(data) {
if(data['username'] != null) {
$(this).append('<p>You are now logged in</p>');
reload_table_data();
}
else if(data == flase){
$(this).append('<p>Fail whale, wrong username or password</p>');
}
}
});
}
Now when displaying the data check if the 'username' has been set in the session. Also don't forget to create a logout method which destroys the session. You can return the table data as an html snippet and insert it straight into the DOM or json/xml loop though it.
The login form could be displayed anywhere on the page and there are plenty of libraries for jquery, dojo, prototype etc which will provide a dialogue box.