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! :)
Related
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!
I have two websites on one server, with urls http://testintranet/ && http://mvc.testintranet/ until now they'be just running plain php. I have been able to transfer a user between the two sites, and maintain their session using a get header: /?session_id=26c81c54a93e145ba2cc50a43d77c4ca
I've had no problem doing this so far, but I'm trying to put cakephp on the second one, cakephp seems to be overriding the session id. How can I stop cakephp from doing this?
To be precise, http://testintranet is the plain php, and I'm trying to transfer session info from that site to http://mvc.testintranet which is running cake.
Glibly
I'm pretty sure that you could use a combination of controller logic and a small modification to your form to accomplish this. I feel there may be a better alternative, but I don't have time to look to far into it before I go to work. This solution should work just fine, but I've never tested anything like this, so let me know.
In your form, you'll want to change the action a little, using whatever variable you're storing your session_id in instead of $_SESSION['id']:
form action="http://mvc.testintranet.com/controller/action/" method="post"
then in your controller method (for this example, view):
function view($sessionId = null) {
if($sessionId) {
//do whatever you need to do here. For Example:
$this->Session->write('Session.id', $sessionId);
}
Tada. Hope this helps, let me know how it works for you.
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.
I'm using the MVC model (I think thats what its called) and I have separated my site into smaller pages and includes.... Is it safer/better or worse (with no benefit) to check the same conditional twice?
For example, I have an accounts page that looks something like this:
// Must be logged in
if(isset($_SESSION['userID'])){
include('edit_user.php');
}
and then in my edit_user.php page I have something like this:
// Must be logged in
if(isset($_SESSION['userID'])){
if(isset($_POST['editUser'])){
//Validate the form
}
?>
<form>
// Display the form
</form>
<?php
} // End main IF
So pretty much I'm checking if the user id is set twice... I'm pretty mush doing the same thing with all my pages (that require users be logged in). Is that really necessary? My initial thought was to prevent unregistered users from accessing the edit_user.php form directly and doing things (I was also thinking of just redirecting if users do access the page directly). What do you guys think/suggest?
Edit
I dont think I explained myself too clearly... That was just an example... Here's a better example to better get across the reasons for my question:
...Account page
if(isset$_SESSION['userID'])){
include('edit_user.php');// edit user form
include('change_password.php');// change password form
include('change_pic.php');// change photo form
}
and from within each of my includes, again I'm asking for a SESSION['userID']... So, what do you guys suggest now?
Well, it is redundant, which violates the "Don't Repeat Yourself" (DRY) principle of design. If your edit_user.php file is publicly accessible, then you definitely need checks in there, so you could probably remove the other checks, as long as you're sure of the functionality.
It's arguable that your code is clearer with the checks in place, however, in the long run redundancy like that will lead to more maintenance hassles.
You shouldn't need to have the multiple checks in there. If all requests go through the controller, then you should only need to add the check in the controller. That is the point of the controller, to direct the request. The view outputs data. The model interacts with the database (and enforces business logic).
In many cases redundancy is beneficial, but in your example it's unnecessary. It also goes against the principle of DRY (Don't Repeat Yourself). The more you repeat the same code, the more time you waste (you also face the possibility of adding errors to your code due to repetition). You should be fine with the check solely in edit_user.php.
Since you're using MVC, here's what I suggest: Define some authentication functions that are globally accessible. Then, in your controller's constructor methods, use them to see if the user should be granted access to that section. If they're not authorized you can redirect them to another page, or display an error message, for example. Of course you can use a finer-grained methodology and place the calls to your authentication functions in the beginning of certain controller methods.
You should always validate input that comes in from outside your control, so every php script that can be accessed by a user should check.
Even if you don't expect it, if a user can see a link in the url to a page that is 10 forms deep in your site then they can still jump directly to it.
Joomla uses a nice method, which is to put this right at the top of each PHP file:
defined('_JEXEC') or die('Restricted access');
_JEXEC is defined in the main entry point. You could do something like:
if ( isset($_SESSION['userID']) ) {
define('LOGGED_IN', 1);
include('edit_user.php');
}
With this in edit_user.php and other files:
defined('LOGGED_IN') or die('You must be logged in.');
I have found what looks like a good, secure PHP login script, however i am having trouble figuring out how to implement it. (It is located here http://www.adesdesign.net/php/tutorials/php/php_login1.php)
I am new to PHP so don't know much yet. I can't figure out how you actually authenticate a user and return a message to them if it fails and where to stick all the functions and classes mentioned throughout.
I know it may be very obvious to some but i just don't get it!
Thanks.
Not the easiest script/way to do it, but quite complete. You say you're new to php, what about OOP ?
IMO, this one seems easier : tutoriel.
Principle always stays the same : you have in your database a table with your user.
The visitor come and try to log.
If his login/password are good, you redirect him to his profil/any page you want and you store in $_SESSION['verifiedUser'] = true ,
if his login/pass are wrong, he's redirected to the login page, with an error message.
And in every page restricted to logged user, you add
if (!isset[$_SESSION['verifiedUser']) )
header('Location:loggingForm.php');
Clement answer is perfect.
May be the pear Auth class can be usefull
Just a note because you siad your are new to php: the authetication process is not the only important thing. You should also think about the ACL (access control list), a mechanism which allows an authenticated user to do some things but not others on one or more pages
--
Dam