In user-based websites, it is very common for websites to use a page like "logout.php", and I even use them myself on my own projects, but now I am wondering why. So my question is: Are there any specific advantages to using a dedicated file for logging out users? Would it not be more organized to just create a method within any appropriate class, such as:
Here is an example written in PHP (this is similar to what I have started to use):
public class Admin {
private function logout() {
$_SESSION[ADMIN_ACCESS_KEY] = null;
unset($_SESSION[ADMIN_ACCESS_KEY]);
return ($_SESSION[ADMIN_ACCESS_KEY]) ? false : true;
}
}
This function would then be triggered by some $_POST or $_GET variable, or any other way of doing it.
My only guess about why it is so popular (google, facebook, etc. do this last I checked) to use single dedicated file for the logout process it that you can simply direct the user to the page (logout.php) and they will be logged out no matter what, provided that the page loads and executes properly. Can you think of any good advantages for either method?
It's not necessarily its own file. In most cases the site is running an MVC where url parameters are parsed into class methods. So though you are visiting host.com/account/logout - you are just simply calling the logout() method in the account class (in its simplest form) in the easiest way possible from the browser.
You'd think this could be done with JavaScript by simply deleting the cookies on the client side, but best practice is to destroy the server stored session also, so it can't be recovered by anyone (like an attacker)
The biggest advantage i can think of is that it allows developers to keep logout type logout button, which are not dependent on jquery or any other client-side javascript to log you out. You just redirect/link them to another page, which takes care of removing their session data.
Its just a plain, and simple URL. Sometimes people even prefer typing it in the URL, i know i do!
Related
I'm not sure if the title is correct way to ask this question, but here it goes.
Case:
I'm using CodeIgniter (2.1.3) to make AJAX calls and fetch JSON data. Being aware that you can't really "secure" AJAX as the JavaScript is always accessible by the user I was wondering what are the possibilities to make it as hard as possible for people to automate the AJAX calls.
Let's say you have a game where you keep requesting queue data for constructing buildings and training troops. If I would want to bot that website I could just find out how the AJAX calls work and make a script to log myself into the domain and call the AJAX calls manually.
The goal of doing this is; Might 10000 people try to bot the website, the layers of hinderance I would build into the AJAX calls might reduce those 10000 to maybe 100, thus making it easier to track for the administrators who still managed to cross all layers.
In this case we can also see what they are doing and try to add more checks/layers to prevent the majority to be able to bot the website.
Confirming an actual session
The first layer I was thinking of is the passing of a random hash to the page that is loaded and storing that hash in the PHP Session too. This way the visitor can "only" get JSON back from the AJAX calls that get the hash value that was given to that single page load. So if they try to fetch the HASH with a regular expression match in one cURL/wget call, they can't use it in the call to fake the AJAX call.
I still think there is an issue here with multiple page loading tho. I might be tracking if people are opening a new page under their login-name and give them a message they may not operate on multiple pages to work with the application. Also it might be problematic with automation tools like Selenium.
In CodeIgniter I do this now:
<?php
public function index()
{
$this->load->helper(array('security', 'url'));
$this->load->library('session');
$data = array();
// AJAX Security
$data['hash'] = sha1(hash('md5', (microtime() - rand(0, 1^3)) * rand(0, 1^12)));
$this->session->set_userdata('live_hash', $data['hash']);
$this->load->view('jqueryjson', $data);
}
public function xhr()
{
$json_data = json_decode($data_set);
if (isset($data_set['hash']) AND $data_set['hash'] == $this->session->userdata('hash')) {
echo 'HASH security layer passed<br />';
echo json_encode(array('JSONDATA TO BE SEND BACK'));
}
else {
echo 'Please do not call the page outside a browser.';
}
}
?>
I know this approach is kind of naive, but I'm wonder how others do this (client-side) to prevent the majority of botters. Off-course I'm also validating all the passed data on the server-side to be sure no data is customized outside the standards the data should have.
I think this problem isnt only bound to ajax calls, but to every request made in a webpage.
To prevent access by automatons most sites use some kind of captcha images.
Idea:
Maybe you could place the graphical elements to trigger the ajax calls in varying places inside an image, so that only a human would click on them on the right spot. I am thinking of an image showing the element of which only you know the position. You simply send the position of the click inside the image with the ajax-request and compare if it was the right spot...
2.Idea:
Open up a captcha-window after 10 ajax-requests made too fast with an image inside, so that
the user has to verify himself as a human. Without the verification no ongoing game.
Maybe you could build the verification somehow in the game, so that a user doesnt see it as a captcha right away.
Lucian
I'm using codeigniter with jquery and it would be nice if you explain me how to protect the controller from direct access.
For example,
I have view with that standard jquery line:
$('#handler').load('tools/get_stats');
Tools it is my controller with function for loading statistics. If I write direct in browser full address of script http://site.com/tools/get_stats, browser open, of course, that data.
How to protect direct controller access from browser ? I want my data were loaded only in view, not on controller direct access.
The CodeIgniter Input Class has a method called is_ajax_request() for this purpose.
if ($this->input->is_ajax_request())
{
//do something
}
else
{
show_error("No direct access allowed");
//or redirect
}
If you have a dedicated Ajax Controller, you can of course include this logic in the __construct() method, otherwise it may be implemented on a method by method basis within your controllers.
See:
http://ellislab.com/codeigniter/user_guide/libraries/input.html
In general you can't do it in a meaningful way due to the need to provide access and the simplicity of HTTP. Or more basically, you can't deny access to information you need to provide (in this case stateless connection info). The best initial steps are to make sure that the controller only allows access to data that the user should have access to (regardless of how they connect), rather than trying to restrict based on the easily tampered with request information.
That being said, if you have some odd reason to really chase after this, you could use some form of single use token passed with the AJAX request. You could, for instance, generate a random key, persist it somewhere (ideally just in memory in something like a hash table since there should never be a long enough delay to warrant otherwise) and pass it out with the page that will issue the ajax request. The token is passed back with the request and removed, and then that token will no longer be valid. The controller would not be able to be accessed directly since it would need a token.
This would still be able to be worked around since the process could be halted and an issued token used, but it would deter anyone just playing around with curl (so really its not worth the effort).
Long story short, you can't do this in any way that anyone couldn't work around within 10 minutes. Focus on making sure you only expose the data you want no matter how its retrieved.
I'm currently writing a couple of MVC sites using Kohana as my framework. Each has a simple admin area where the admin can upload and edit content. I'm currently storing the admin's user model in a session and checking whether or not they're an administrator with the following method:
private function checkAdmin()
{
if (!isset($_SESSION['admin']) || $_SESSION['admin']->Level !== 'admin')
{
header('Location: /admin');
exit;
}
}
I call this method in all of the other Admin controller methods, like so:
public function writeReview()
{
$this->checkAdmin();
// rest of the method
}
I'm just wondering if there's anything I can do to improve this. It just seems like a single point of failure that's giving me a bad smell, so I'm a bit weary to move on before getting this nailed down.
If this is Kohana version 2.x, I would move the $this->checkAdmin(); into the constructor of your controller. If this is version 3.x, I would put it in the before() method. This will ensure that every route will be protected.
Your function appears to be redirecting to /admin only if the user is not an administrator. If that's the intended result, then fine.
-- Forget this, my mistake.
The checkAdmin() function, as it relies on a redirect, is only useful in situations where you want to redirect. If, for example, you are using this in the processing script (and you should be checking if it's an administrator in the processing script), you just want a return true or return false. I suggest that be the base function, and a redirect function call that, or alternative, accept and optional parameter to redirect.
If you want to let users share their logins fine, but otherwise generating a per session/login key and storing it in the DB will lock things down even further. This way, if someone logs in with your password, you'll get kicked out and instantly know that it's been compromised.
Other basic things to do - store dates of last login, IPs.. this kind of stuff. It's not just one single thing, but lots! :)
I'm trying to create a login process. But it seems impossible to create one process that will work with a desktop app and a standard website.
Instead I have the login function in Usermanagement.php (which is a class, icyntk) but then in another php file (api/login.php) I have:
<?php
require_once '../usermanagement.php';
$m = new usermanage();
echo $m->login($_POST['username'], $_POST['password']);
?>
And then I will still need to make another login.php just to be used with the login form on the website. As I can't see anyway to get the result (the echo) of the api/login.php script from the index.php file (where the login form is, it only has HTML in though).
Is there anyway I can simplify this so I only need one login.php?
As I understand you, what you want is:
a website/webapp having a login
a desktop app (not in PHP!) logging in using the same login method
One way is to export the login method using the same API in both your website and the remote application, so you would be using JavaScript on client-side to access the API from there (AJAX/JSON). You will want to use some framework for that like jQuery for client-side simplification of AJAX (among many other uses) and maybe the JSON module in PHP (to use json_encode; beware that the module may not be available on some webspaces so if that's out of control don't use it). Of course you do not need to use XML or JSON in your API responses but it's easier to open the API to other (including desktop) applications without the need to manually implement a lot of parsing functions to process the response in your interface classes.
Keep in mind that your website/webapp will not work without JavaScript if you do it this way! On non-public parts of a website that's okay, as is for a webapp used by a known user group, but you should not depend on client-side scripting for public parts of a website.
Another solution to simplify that is by using a PHP framework, so you can write the server-side frontend easier. This will basically enable you to give a button a serverside function which is simply calling your login method and acting accordingly by setting a redirect or replace some panel or whatever you like to continue with after the login.
Of course you can do all that by yourself but this will usually result in either a lot of messy code or an implementation of your own framework. If you want to do it on your own, start by posting the form to the same PHP file instead of an extra login.php and add a hidden field like:
<input type="hidden" name="action" value="login"></input>
In PHP, check $_POST['action']=='login' and call the login method.
Edit: While your website will work with a PHP session or a cookie, you may want to track login status with an own session token which you can pass to your desktop app so it can be used for consecutive calls to the API, so you don't need to handle cookies. These tokens should also be bound to the IP and maybe other "individual" information of the client; that information should ideally be hashed into the token or the token encrypted (client-side won't have to "decrypt" that, just return it for authentication). Tokens should also time out after inactivity.
Also, having read your older question, I fear you could be trying to do something bad like sending a hash over the network and simply check that hash with your user table because JS side encoding was discussed there. If you like to implement some encryption algorithm on client-side, either make sure it's secure (difficult to do that unless you are into cryptography) or resort to SSL.
As the data from your Desktop App is unlikely to be sent via the $_POST array, I would say no. Websites and Desktop Apps are two completely different types of applications, and it would be unrealistic to think you could share much of the front-end code between the two.
I would try to abstract as much of the functionality as you can into core classes, and then create two separate front-end implementations that utilize the core, each in their own way.
I'm going to get really "limby" and go out on a freaking huge limb and say that this is what you're trying to do:
<?php
if(isset($_POST['username'])) {
require_once '../usermanagement.php';
$m = new usermanage();
echo $m->login($_POST['username'], $_POST['password']);
}else{
?>Put your login form HTML here<?php
}
This way you only need one login.php file.
I'm not sure how to describe this, but basically I have a PHP class file:
class HelloHello {
public function getSomeData($input_parameter){
// code to retrieve data from the database
}
public function deleteSomeData($input_parameter){
// code to delete data from the database
}
}
This class is on the server and is part of the backend that connects with a database, and it's meant to be accessed by the frontend SWF only (not to be directly accessed). I've setup Flex to read this class and access it. But how do I make sure that someone doesn't develop a script that can call this php file directly and access its methods? For example using a script to add data in a fast automated way, or use the delete method directly, ouch.
Is this a legitimate concern, or this can't be done?
If a user can view it through your flash application, the user can view it with his application. You could go through the [ugly] mess of trying to "secure" your script by introducing cookies and authentication and the like, but thats messy, and of course, it can be gone around.
Instead of trying to stop others from accessing your php file, focus on making it more secure.
If you know the url where swf runs, can't you just in PHP limit the requests to that url? Disregard all other requests.
You can secure your file by adding security and authentication. If you cannot do that (it is a public application) you should implement some techniques which can prevent specific situations: do not allow calling your script too many times per second from the same IP, add CAPTHCA in order to check that the entered data were from a human and not a machine and maybe another ones.
You could also implement a challenge-reponse security system that makes sure the client you use is actually the intended recpipient of the data. That way, you would embed a secret key into the SWF. The PHP app sends a one-time string, the client does something to it according to its secret and then sends the answer back -- which your server can validate and then continue to run.
For some basic mathematical foundations to this, there's quite some documentation online.