hi typically a codeigniter mvc controller accepts an id as a parameter for a controller function. For example:
/photo/edit/1
A user would edit image id 1 from the photo controller. What is the best practice to prevent a user from editing someone else’s image..for example editing id 2? Restriction has to include more than just verifying a logged in user, because a logged in user will still be able to edit image 2.
I was thinking that i would write a library that implements a permission function, that is called on all controller functions. I would pass the user id and the url to the library function which would contain logic to verify if a user could execute that function or in this case edit an image.
The problem i see is..it will be tedious to write the logic code for all functions of my site, as each is different logic. Is there a better generally practiced way?
You generally handle the checking in the controller itself, so if, for instance you have the currently logged in user, and the photo object from the db, just store the photo's owner in the db record and compare them.
It really is not all that tedious, you are simply verifying ownership of the object before processing actions on it.
example...
if ($the_user->id == $the_photo->owner_id) {
//allow their actions
}
else {
redirect('/'); //if not, kick em out
}
Related
I am so confused about how to implement and how to follow SRP (single responsibility principle ) in a Laravel controller.
Suppose we have a controller which we have to do these things:
e.g
public function StorePost() {
// check user login()
//check number of current user Post count =>which must be less than 10
//store post
//send an email to user which your post has saved
//return =>api:json /web : redirect
}
I know that I can implement some DB queries in the repository but I don't know how to implement others of my logic code to achieve SRP
Also, I know there is a Heyman package to achieve these but I want to implement it by myself.
SRP in this context basically means each class and method should only be responsible for a single behaviour/feature. A rule of thumb is a class or method should change for one reason only, if it changes for multiple reasons, it needs to be broken down into smaller parts.
Your storePost method should not bother with checking the user login, that should be handled elsewhere before invoking storePost. storePost shouldnt change if the auth mechanism changes like switching from api token to json web token or something else. Laravel does this in the middleware level with the auth middleware.
Checking the users post count, this can be checked in the validation stage. storePost shouldn't change if we add more validation logic. In Laravel you can use FormValidation for this
For storing the post, the controller doesn't need to know how to call the DB, you can use the active record style using the model class or maybe create a service or repository class if your use case requires that. storePost shouldn't change if we decide to change DB vendor like going NoSQL.
For sending email, again the controller doesnt need to know how to send the email like what the subject/body recipients are. storePost shouldnt change if we need to change the email layout. Laravel has Notification for that
For serialising the response to json, the controller doesnt need to know how to format the response. if we decide to update how our json looks, storePost shouldnt change. Laravel has API Resources for that
So, ultimately in this example, the responsibility of the controller method is basically to glue all these together. It basically does what you wrote down, it only responsible for maintaining the step by step behavior, everything else is delegated to someone else. if the behavior change, like adding new behavior e.g notify all follower, storePost will change.
I am trying to create a suitable authentication check for a CakePHP service. Currently it appears that the user session is created initially during login, but never checked beyond this during a single session.
eg. Renamed the username, changing the password or ID in the user's database entry has no effect on the session.
Is there a preferred method for this type of, constantly checked, authentication? Essentially the user should be confirmed access at every request.
My current solution would involve extending the AuthComponent and storing a hash of the user data (including the encrypted password) and checking this at every request. I also considered storing the session ID in this same token, but noticed that CakePHP does not even use the session_start() function.
This functionality appears necessary for me, and I would have thought others would also require such a solution. I have yet to find Cake documentation or community solutions similar to what I need.
Well, you can use isAuthorized() function from AuthComponent. It's being called with every request.
public function isAuthorized($user){
return true; //allow the user to see the page
}
You can debug($user) to see the actual data and if you want "new" information from your database, you can always get them like this:
public function isAuthorized($user){
$current_user_from_database = $this->User->findById($user['id']);
if($current_user_from_database['User']['username'] != $user['username']){
$this->Session->setFlash('You\'ve changed the username. Please, login again.');
$this->redirect($this->Auth->logout);
return false;
}
return true;
}
Look at the API for more info and from the PDF book. You can look at this video about AuthComponent too. It's great.
If you need any more information or help, feel free to ask.
Btw. you have to configure AuthComponent in your Controller if you want isAuthorized() function to get called with every request.
If Session.timeout will work correctly with a setting of zero minutes, you're set. http://book.cakephp.org/2.0/en/development/sessions.html
I am developing an ASP.Net MVC 3 Web Application. Within some of my Views I display tabular data to the user, and beside each record in the table there is an Edit link. When the user clicks this link it takes them to an edit page where they can edit and update the record.
My issue is that once the user clicks the edit link, the URL becomes something like this
http://www.mytestsite.com/myData/edit/3
The '3' is the ID of the record to be updated, however, there is nothing stopping the user from changing the '3' to another digit, and this then means they can edit potentially a record which does not belong to them.
Does anyone have a solution on how I can prevent this from happening?
Thanks for you help.
You need to introduce Authentication and Authorisation into your application. Here is one article of many out there on how to get started with this. You will additionally need to work out how to store logged on user identity and then how to attach this to the record when it was created in the first place. You must then validate, on the server, that the subsequent edit request is being made by the user who created the record in the first place (or by a user who has a role on your system which allows them to do this, such as an Administrator).
Even if the ID wasn't being displayed on the URL a malicious user could still manipulate the HTTP Request to pass an ID of their choice. In any secure system you should always, always, always validate that the currently logged on user genuinely has permission to carry out the requested action. You should never rely on what comes back from the browser to determine this (aside from the authentication context which is managed securely by the MVC framework. Usually).
I believe you should have the information about who have the edit permission on this purticular resource, in your tables. Ex : in your table you might have the "CreatedById" column where you store the ID of the user who created this record. Now in your edit action method, you check the "CreatedById" of the current Item is same as of the "UserId" of the Current user (you maye get this from the session, if you stored it there). Something like this.
public ActionResult Edit(int id)
{
int currentUserID=1; // TO DO : get this value from session or somewhere
ProductVieWModel product=myRepo.GetProduct(id);
if(product!=null)
{
if(product.CreatedById==currentUserID)
{
return View(product);
}
else
{
return View("NotAutherized");
}
}
return View("ProdcutNotFound");
}
You should try using the GUID data type as it helps in these kind of situations, and the user cannot easily guess the next value
I need functionality for authentication handling and some basic role based authorization (just block some pages to a role and allow some pages on another).
I already read this question: What is the best Authentication and Authorization library for CodeIgniter?
However the question it's from 2009 so maybe there is a new technology that works better now.
Any suggestion, expecially if you have used the library, are appreciated
All of the Auth libraries I know of restrict you in some form or other out of the bag. Its usually a good idea to build your own auth library, break it down so you dont restrict yourself to using codeigniters native AR.
For role/permissions I usually just store a json object to my permissions column in say users. I prefer this over using a more complicated technique
In my main Controller(non-restrictive) I just create a permissions(array)var and loop through it inside my child controllers to implement a restriction.
example:
sql column
`permissions` varchar(200) NOT NULL DEFAULT '["r", "u", "d"]';
main controller
protected $permissions = array();
protected function _get_permissions()
{
return (array)json_encode($this->user->permissions);
//get permissions from user (array/object)
}
extended children
if(in_array('r', $this->permissions))
{
//user can read something
}
I like skittles answer so I post it here (he is not posting):
I'm pretty sure this is not what you wanted to hear, but I prefer to
roll my own classes. I'm not afraid to re-invent the wheel
I prefer to use a salted hash. What I will typically do is take their
plain text password and add a string to it derived from a $config item
I call $config['encryption_salt']. Then I run the newly built string
through php's sha1 function and store the result in the database.
As for authorization, I will typically build a permissions lookup
table in my db and assign users a permission_id value in their user
record. Then my site can be conditionalized allow or disallow
activities based on their permission_id
If Skittle will post answer I'll mark it
I'm kind of new with CodeIgniter and I'm still learning (a lot).
So I have a view and when I submit a form I 'call' the controller by surfing to the right URL dynamically e.g. site/delete
class Site extends Controller {
function index(){$this->load->view('...')}
function delete() {
$this->site_model->delete_row();
$this->index();
}
}
Now when that action is done (deleted the row) I'm calling $this->index(); to redirect to my initial page (which is good) but my url stays: site/delete . I want my URL to be ../site/index (or without the /index)
Any help would be appreciated :-) .
So far I found something to solve this:
instead of:
$this->index();
I'm using:
redirect('site');
Does anyone know this is a good practice?
Redirect is what you should use.
In the user guide:
http://codeigniter.com/user_guide/helpers/url_helper.html
they use it after checking if a user is logged in. Depending on if they are or not, they redirect to a different place.
Also, note that any code after the redirect won't run. Make sure and redirect after you've done everything you need to.
My preferred method is to have actions like that handled by the same method that will be seen by the user afterwards.
What if you go to /site/delete afterwards, as a user? It will either have to detect and throw a error (show a message) or redirect to an appropriate page. /site/delete has no meaning.
For example, if a user would normally see an overview after deleting, then my form will be posted to /site/index; with index quickly checking for the condition and calling _delete() in the same controller, before doing its normal work.
That way, if the user refreshes the page, or presses 'back', things should look consistent to them.
Another example would be that /settings/edit would post to itself - this means that it can act on the post and show any output (e.g. validation errors). It means there's no /settings/do_edit location on my site, and also means that the user can go back to /settings/edit safely, and see a form for editing their settings.
I suppose this is a subjective take on a perhaps objective question, and I would encourage feedback on my view, but it's my way of avoiding the problem you have asked about.
$this->index();
Call of function in a function simply execute the functionality within that function.
And url never changed.
for changing the url you should use.
redirect ( base_url().'site');
but you should load url helper in constructor.