I am trying to create a log in system in php. I have 3 files. index.php, login.class.php (defines Login class), securePage.php.
Login class has different functions such as getUserName(), addUser(), etc.
index.php creates a new $login object, has a log in form and create a new account form.
When you create an account on the index.php page,
$login->addUser($username, $password, $first_name, $last_name, $email); function executes which creates a new account.
After you log in and hit submit, the script checks your username/password/etc and redirects you to securePage.php.
After I redirect to securePage.php from the login.class.php, I am not sure what's the best way to check if the user has logged in correctly and have all the user's information handy.
Right now my securePage.php creates a new login object
$login = new Login; and checks if the user has access to the page by calling checkAccess within the Login class.
// Check if the user has access to this page, otherwise redirect to login page
if($login->checkAccess()) {
//blah blah blah
}
This is how checkAccess function looks inside Login Class
public function checkAccess() {
// check the session access
if(isset($_SESSION['username']) ) {
//
return true;
}
}
I feel this is bad implementation because
a) I create a brand new login object and lose my data
b) I only check if the session is secure by checking if session's username is set which can be probably faked.
What's the best way to implement securePage.php in terms of still having all the user data and checking if the user is logged in?
Session data is server side data -- it can only be faked through manually guessing PHPSESSIONID (You can read up on that here).
The way that this is normally handled is one of two ways. If HTTP Authentication is being used (which has some major benefits, BTW), then basically every time a secure transaction needs to occur, the UN/PW have to be tested. On the other hand, if the server is storing the value (say in $_SESSION or some other framework equivalent), then the server already has the data and there is no point in re-querying.
If you have implemented the methods __sleep and __wakeup properly, you can simply store the entire login object in $_SESSION, which would generally be my preference.
Your session is stored server side, and thus is a good way to check for a login status. There are some issues like f.e. account sharing but they shouldn't be a problem for the application you are developing.
I wouldn't be checking on the username though, I'd add a key called 'authorised' or something. also I'd call the function isAuthorised instead of checkAccess, as checkAccess would indicate using user roles/rights to me.
Related
I created a system that uses username/password login system with with 'phpass' class to store hashes and check passwords when user logs in.
I also use AJAX to load user information (that can only be retrieved if user is logged) with javascript.
My question is, should I check for user's authentication in every page and in every file that returns AJAX values or just create a 'connection' entry in MySQL database.
Is it wrong to use 'phpass' functions in every page and request because of performance or is it wrong to use the database method?
What's the best method to keep user connected and check in every page if the user is logged?
Use a $_SESSION and check it on every page
i.e.
$loggedIn = ($_SESSION['logged_in']) ? TRUE : FALSE;
if($loggedIn == TRUE){
//Do stuff here for a logged in user...}`
If you include some config file in header or some other file, which is available on whole website then check in that file for logged in session, rather adding code to every page
I have two forms. One is for the registration form and the other is the login form. My login form is already working but when I try to access the registration from in localhost instead of prompting me the login page, I can still be able to access the registration from which is wrong.
It should prompt me to the login form first because I am not yet logged in.
How would I do it?
Here's one approach.
I assume you have a library script that's loaded by your pages. Somewhere in there, define a session on every page:
session_start();
Then, when the user logs in with valid credentials, save some information into the global $_SESSION array. For example, if you had a login($username, $password) function that returned a row from your user database (or a user object):
if ($user = login($username, $password)) {
$_SESSION['user'] = $user->id;
// Probably store some other stuff about the user here too
}
To check if you're logged in:
if (!empty($_SESSION['user'])) { /* .. */ }
And to log out:
$_SESSION['user'] = false;
Or
unset($_SESSION['user']);
Obviously this is simplistic, and you'll probably want to look at things like:
Changing the default session ID with the session_id($id) function
Creating an object or a series of functions around your session
Auto-populating and refreshing information about your user
But this is a start.
Also see:
The PHP session functions: http://us3.php.net/manual/en/ref.session.php
How this is done in a real life PHP social networking engine: https://github.com/Elgg/Elgg/blob/master/engine/lib/sessions.php
Take a look at PHP Sessions. You can use $_SESSION to store peristent information about user, whether they have already registered or not.
You should check which form was submitted in your php code using the name attribute of your forms. So if your login form has the name="loginForm" and registration has name="regisForm"then in your code do this
if(isset($_REQUEST['loginForm'])) {
...//do something with loginForm
}
else if(isset($_REQUEST['regisForm'])) {
..//do something with regisForm
}
You have to store the information on whether the user is signed in or not in a way that enables you to check for it on every subsequent page. Usually this is done using the so called sessions - details would be too much for this anwer here - I strongly suggest you learn about sessions in PHP. Another (simpler) way would be to store the fact that the user is signed in in a cookie, but this is usually not as good as it can be tampered easily. But using cookies might be the quick and dirty approach until you learn the details of session variables. In any way you have to learn more for accomplishing your goal here. You might find that the easy looking tasks can become quite complex when you start implementing them. The easier things are for your users, the more work the coder has to do. But that's also what makes coding interesting in the long run... Don't give up.
I'm working on this project in Codeigniter and i created login and register script but I don't know how to validate user on every page.
When user logs in what data to store in session (Ci session user_data), so i can compare it to database on every page to se if the session is valid?
I'm using codeigniter's session class and I'm storing the values automatically in the database. Please help me I'm stuck here...
My session is handled like this :
1. When ever any user reaches my webpage he gets unique hashed (md5) session id that is checked when ever a page is loaded. If it exists do nothing if it doesn't generate a new one. It changes every 5 minutes.
2. When user logs in what data to pass to so i can compare it to the database later on ( on every page load)
I don't know if storing only the 'is_logged' = 1 cookie is safe. I want to check cookies on every server request.
Upon succesful login, you create a
$this->session->set_userdata(array('authorized' => true));
You can then make an auth library, or a model method, whatever suits you that just checks if this session data exists.
function is_logged()
{
return (bool)$this->session->userdata('authorized');
}
if FALSE, user is not logged, if TRUE it is. You can call this function on every controller's method you need to place behind authentication, or in controllr's constructor if you need it for all methods (ex. an admin panel)
have a look, for ex., on how Ion Auth, one of the mainstream Auth Libraries in CI, handles the thing (uses the logged_in() method which does the same as in my example code. Keep in mind that sessions are encrypted, and if stored in database security is even higher);
https://github.com/benedmunds/CodeIgniter-Ion-Auth/blob/2/libraries/Ion_auth.php
Sessions are stored on the server so no validation is required. You only need to validate what you put in the session.
Sessions are authenticated by the user supplying a session_id cookie (PHPSESSID).
Cookies on the other do require validation, but cookies shouldn't be used to store critical data so it's a bit moot.
You should have write a function in helper like session_helper.And in constructor of your class call this helper method.If your user is logged in correctly then it will continue,other wise it will redirect to log in page.Your Helper should be like this
function session_set()
{
$ch=&get_instance();
if($ch->session->userdata('your_session_id')=='')
{
redirect('your_login_page');
}
and in controller you should check like this(constructor)
session_set();
Hope this will work for you
As in many web applications, when my users log into my site, I set several session variables that control permissions for accessing site functionality.
Whenever a user undertakes an action that would result in a change to those permissions, I update the session variables as part of the normal processing flow.
But sometimes a user's session needs to be updated based on the actions of another user. For example, a moderator upgrades a user's permissions. The moderator does not have access to the user's session space, so the normal update functions cannot be run for the affected user.
I have considered a few ways of forcing an update to another user's session, but they all have drawbacks:
I could search for and delete their
session from the sessions table, but
this requires a full table scan
(where sessdata like '%user_id%'),
and it could cause the loss of
content that the affected user may be
engaged in generating.
I could force a session update
periodically, such as when
sess_time_to_update is triggered.
But there is no guarantee that this
will transpire prior to the user
attempting to access the
functionality for which the update is
needed.
I could run a complete series of
variable updates on every page load,
but the whole point of maintaining a
session is to avoid that overhead.
I could set a flag indicating the need
for a session update, but that signal
would have to be interrogated at every page execution, and in every controller. (I know that I could extend CI_Controller as MY_Controller, but I don't want to do that)
I'm already sending the user an email
notifying them of the change in
permission, and it's easy enough to
make them click a session update link
(or even log out and log back in).
But there's no guarantee they are
going to even read beyond the subject
line, let alone actually click the
link.
So is there anything I'm missing? Am I looking for a magic bullet that does not exist?
(Note that I've tagged this with CodeIgniter, and made reference to CI-specific technical details, because that's what I'm using. That said, this isn't a CI-specific (or even a PHP-specific) issue.)
Thanks for the help!
Well, one option would be to set an "ACL Version" number (either for all users, or for each user). Then when initializing the session (well, when you call session_start()) check to see if the stored version matches the session's version. If it doesn't, refresh the ACL.
Another slightly different way would be to add a column to the sessions table ("status" or "dirty", etc). Then, instead of killing the session, simply update that status to 1. Then when loading the session, check that flag to see if it's 1. If so, reload the cached data in the session and set it to 0. If not, continue on...
As far as updating another user's session, I wouldn't do that... If sessions are managed by PHP, then you'll need to kill the current session and start the one you want to modify. That's just asking for problems... (you need to do that, since PHP's mechanism does not use serialize.).
As far as deleting their session, I wouldn't worry about the full table scan. Unless you have a TON of users updating permissions all the time, it's not going to matter. The data loss is a significant concern, so that nicks that idea...
As far as the other 2 options, I think you hit the nail on the head, so I have nothing else to offer on them...
I'm going to take a stab, though my approach is not entirely applicable to Code Igniter.
The way I've solved this problem in the past is to make a User object model with a constructor that takes the UserID from the database primary key where the credentials are stored. I'll write a static login method that checks login credentials and then instantiates and returns an instance of user if the login is correct for a row and then sets the session.
So far so good, right? So all your permissions, access levels etc are stored in the database. Just like having a login method, we can have a refresh method that reinstantiates the object, re-fetching from the db off the already obtained primary key.
class User{
public function __construct($uid){
//fetch from the db here
$sql = 'SELECT FROM User_Table WHERE UserID = ?';
$params = array($uid);
//fetch and assign using your flavor of database access, I use PDO
//set all your object properties for access, as well as user_id, something like
//$this->user_id = $result['UserID'];
}
public static function Login($uname, $pass){
$sql = 'SELECT UserID FROM User WHERE Username = ? AND Password = ?';
$params = array($uname, md5($pass));
//again I'm going to employ pseudocode here, fetch according to your preferred system
if(!empty($result)){
$_SESSION['user'] = new User($result['UserID']);
}else{
//login failed!
return false;
}
}
final public function _refresh(){
//refresher method. Since the controller sets all the object properties for access
//reconstructing and assigning it refreshes these priveliges.
$_SESSION['user'] = new User($this->user_id);
}
}
Using this model, whenever I am performing an action with the user in the session that might potentially need time-sensitive permissions, I can call refresh on the user object all ready in the session. Let's say we have a controller function to access a restricted form.
function _topSecret(){
$_SESSION['user']->refresh();
if($_SESSION['user']->specific_permission_from_db){
//Perform the special action, get the view, whatever.
}else{
//redirect to an error page
}
}
So if you already have routines written for the admins, all they need to do is set the user's privileges in the database, and when the refresh method runs on the specific, time-sensitive functions, that data will be put in the session for the user. So you're not necessarily updating another user's session, you're just determining which actions are so chronologically sensitive they require the newest permissions and issuing that command to the user object in the session.
This has proven pretty efficient for me, since reconstructing need only be performed on actions that need the most up to date permissions. Again, I'm not sure how useful it may be in the context of CI and your individual application, but I figured I'd share. I'm assuming you've already done all the necessary session security measures and started the session - most frameworks like CI will handle this for you through their native means.
Add a column in the session table that can hold the primary key of the user object. Set it upon login and use it later to update the session.
Edit: If you don't want to extend the session table, make an additional lookup table where you have the user object id and the session key link.
If your're storing the session as a native php session I'd tend to leave it alone, and allow them to get some kind of notice that they need to login/out to refresh the setting. I've also had sites where the session data is stored in the db and then its much more trivial to just write the new setting in.
In my PHP Web-App I use sessions to store the user's data. For exmaple, if a user logs in, then an instance of the User class is generated and stored in a Session.
I have access levels associated with each user to determine their privileges.
Store the user in a session by:
$_SESSION['currentUser'] = new User($_POST['username']);
For example:
if($_SESSION['currentUser'] -> getAccessLevel() == 1)
{
//allow administration functions
}
where getAccessLevel() is simply a get method in the User class that returns the _accesslevel member variable.
Is this secure? Or can the client somehow modify their access level through session manipulation of some sort?
No, the client cannot modify their access level. The only thing stored on the client is the session key which is either propagated via cookie or GET parameter. The session key ties to a corresponding session record which is a file stored on the server side (usually in a temp directory) which contains the 'punch'.
What you don't want, is for a session key to get leaked to a third party:
A leaked session id enables the third
party to access all resources which
are associated with a specific id.
Take a look at this: http://www.php.net/manual/en/session.security.php
The session information is stored on the server and the user only has access to a key. In practice I have used something of this sort, with extra steps. After validating the user details and storing the User object, I would have a query that is run when viewing any of your protected pages to validate what is in the session is okay with what they're trying to view.
In the top of your page.php
if(!validUser($user)){
// Relocate the user
}
where
validUser(User $user)
{
// Some query to verify the information in the session
// Return the results of verification
}
I thought the only way for the user to manipulate something like that was if it was stored in a cookie on the users computer.
Is the getaccesslevel stored to a cookie or is it called from the server only after checking the login cookie and not stored on the users computer?
I would assume that if it is called on the server only after the user is logged in then they would not be able to easily manipulate that other than through other means of security holes.
Just my guess tho, im not that great with security myself yet. I will keep an eye on this to see what others have to say and maybe I can learn something.