I am struggling with PHP login and user validation after they log on to the system. I know the basics but I'm not sure if I'm doing it right. I will try to explain it step by step.
I have a form for user name and password.
After users enter they login and password i'm using LDAP authentication to authorize them. And if authentication pass then i need to start new session.
New session (and this is where i'm struggling).
if ($validation->ldap_authentication())
{
$session = new session();
$session -> login($validation->getUsername(), $validation->logedAs(), $validation->getSID());
if($session->validate_login())
{
exit(header('Location:index2.php'));
}
else
{
echo 'error';
}
}
And my session class:
class session
{
public function __construct()
{
if(!isset($_SESSION))
{
session_name(SESSIONNAME);
ob_start();
session_start();
} else {
session_regenerate_id(true) ;
}
}
public function login($sessionUserName, $logedAs, $sid)
{
$_SESSION['logedUserName'] = isset($sessionUserName) ? $sessionUserName : null;
$_SESSION['logedAs'] = isset($logedAs) ? $logedAs : null;
$_SESSION['sid'] = isset($sid) ? $sid : null;
}
public function validate_login()
{
if (!isset($_SESSION['logedUserName']) || (trim($_SESSION['logedUserName']) == '') ||
!isset($_SESSION['logedAs']) || (trim($_SESSION['logedAs']) == '') ||
!isset($_SESSION['sid']) || (trim($_SESSION['sid']) == '')
)
{
return false;
} else {
return true;
}
}
}
So in the another pages i need to start a class session (again) and validate validate_login()?
For me it looks really poor authentication.
What do I need to add and improve?
I already searched online but couldn't find an answer and don't know what exactly I need to improve.
I'm a beginer in PHP, so my answer might be worthless.
I think you can trust the variable stored in $_SESSION as only the server can access them. So you could have a boolean $_SESSION['loggedIn'] that let you know that the user have gone through the login process successfully, and this variable would be accessible from any page.
Related
I'm having some issues with a request from my boss.
I'm using the http://www.html-form-guide.com/ Registration forms he has created for use (I've attached the link just in case anyone want to use or look at it)
So I'm pretty new to PHP, but I've been gaining a crazy amount of knowledge.
Here is my problem - I need to make this form Register the user than Login Automatically. (This form has a Email confirmation system)
So I've managed to bypass the Email Confirmation and get the user to register, but I can't seem to figure out how to get auto login.
Here is what I've traced in the code:
function RegisterUser()
{
if(!isset($_POST['submitted']))
{
return false;
}
$formvars = array();
if(!$this->ValidateRegistrationSubmission())
{
return false;
}
$this->CollectRegistrationSubmission($formvars);
if(!$this->SaveToDatabase($formvars))
{
return false;
}
/*if(!$this->SendUserConfirmationEmail($formvars))
{
return false;
}*/
$this->SendAdminIntimationEmail($formvars);
$this->AutoLogin($formvars);// My call
return true;
}
This will pull in the name, email and password - put them in an array then send it off for validation and sanitation. I've placed a call function here.
After which I'll need to manually login with:
function Login()
{
if(empty($_POST['email']))
{
$this->HandleError("Email is empty!");
return false;
}
if(empty($_POST['password']))
{
$this->HandleError("Password is empty!");
return false;
}
$email = trim($_POST['email']);
$password = trim($_POST['password']);
if(!isset($_SESSION)){ session_start(); }
if(!$this->CheckLoginInDB($email,$password))
{
return false;
}
$_SESSION[$this->GetLoginSessionVar()] = $email;
return true;
}
So I took the last portion of the login function and made:
function AutoLogin(&$formvars)
{
$email = trim($formvars['email']);
$password = trim($formvars['password']);
if(!isset($_SESSION)){ session_start(); }
if(!$this->CheckLoginInDB($email,$password))
{
return false;
}
$_SESSION[$this->GetLoginSessionVar()] = $email;
return true;
}
I did an echo $email; echo $password; exit; test and I can see that the email and password are appearing. But the "Session" (I think) is not starting or the Check Login is not getting the data.
function CheckLogin()
{
if(!isset($_SESSION)){ session_start(); }
$sessionvar = $this->GetLoginSessionVar();
if(empty($_SESSION[$sessionvar]))
{
return false;
}
return true;
}
Now I see the is a CheckLoginInDB which is:
function CheckLoginInDB($email,$password)
{
if(!$this->DBLogin())
{
$this->HandleError("Database login failed!");
return false;
}
$email = $this->SanitizeForSQL($email);
$pwdmd5 = md5($password);
$qry = "Select name, email, pagecode, welcome from $this->tablename where email='$email' and password='$pwdmd5' and confirmcode='y'";
$result = mysql_query($qry,$this->connection);
if(!$result || mysql_num_rows($result) <= 0)
{
$this->HandleError("Error logging in. The email or password does not match");
return false;
}
$row = mysql_fetch_assoc($result);
$_SESSION['name_of_user'] = $row['name'];
$_SESSION['email_of_user'] = $row['email'];
$_SESSION['pagecode_of_user'] = $row['pagecode'];
$_SESSION['welcome_user'] = $row['welcome'];
return true;
}
What I can gather from this, its just a standard checking the database to see if this user exists and returning the results.
I've searching through stackoverflow and can't seem to see an answer to my problem.
I looked into Cookies, but I don't think that is something I really need here.
My questions are:
How can I make this bad boy start the session on registration?
Is my thinking on calling the AutoLogin(&$formvars) the right idea?
Have I gone wrong with this AutoLogin function syntax?
Just in case here is the GetLoginSessionVar():
function GetLoginSessionVar()
{
$retvar = md5($this->rand_key);
$retvar = 'usr_'.substr($retvar,0,10);
return $retvar;
}
It's a pity I can't attached the file I'm working on, but if you need any further code snippets let me know and I'll be sure to Edit this straight away!
But the "Session" (I think) is not starting or the Check Login is not
getting the data.
Is my thinking on calling the AutoLogin(&$formvars) the right idea?
Have I gone wrong with this AutoLogin function syntax?
It's not something wrong with the syntax, otherwise the code wouldn't even be compiled. Nevertheless I believe it's not the right idea.
You need to understand what's the problem before trying to fix it.
Debug the code. Use xdebug. If it's installed and active, you can use IDEs (e.g.: Visual Studio Code) to easily debug the code. Add breakpoints where you suspect there's something wrong.
If you don't want to use xdebug, you can add temporarily echoes or var_dumps to check if some areas of the code are processed and check some relevant values.
Also enable all errors reports and use a logger.
If the session is started after any output, there should be some warning.
Handle the errors and throw exceptions.
http://php.net/manual/en/function.error-log.php
http://php.net/manual/en/function.syslog.php
https://jtreminio.com/2012/07/xdebug-and-you-why-you-should-be-using-a-real-debugger/
session_start() works after output being sent
http://php.net/manual/en/function.error-reporting.php
You don't need to use the & in AutoLogin(&$formvars) if you're not changing the argument $formvars (you're just reading it).
You don't need to set session variables with all the user data. Create some structure (a class, an array, ...) with the user data outside those function and change those. AutoLogin should update that structure, something like this:
<?php
if (!$_SESSION) {
session_start();
}
$currentUser = array();
function getUserFromID($userID)
{
//TODO implement function
return $user;
}
function AutoLogin()
{
global $currentUser;
if(!empty($_SESSION['userID'])) {
return false;
}
$user = getUserFromID($_SESSION['userID']);
if (empty($user)) {
return false;
}
$currentUser = $user;
return true;
}
Maybe the session is not initialised before CheckLoginInDB is invoked (make var_dump($_SESSION); to check it). Use the $_SESSION only to save the user ID (or email) and read it to retrieve the user data.
I was wondering, what's the best way to store messages for the user in PHP. With messages i mean something like
Authentication successful
or
Please enter a valid e-mail address
Currently I'm working on a project where they are stored in the $_SESSION variable, but I don't think this is a good solution.
Short explanation how I do it at the moment (The class Message was created by me)
$_SESSION["msg"][] = new Message("...");
and
foreach ( $_SESSION ["msg"] as $msg ) :
echo $msg->getText();
endforeach;
unset ( $_SESSION ["msg"] );
This is just a simplified version of the complete code, but you should get the idea.
EDIT: Forgot to say, that I'm working with an MVC framework and want to speperate the logic from the output.
One can only speculate on the nature/contents of your Message Class. However, here; attempt was made to simulate a mock-up of a class called Message; also the Usage in your View Script was shown below the Class. Be sure that $_SESSION is active on both Scripts.... Perhaps, this may shed some new light on how to go about your unique case:
<?php
//FIRST CHECK IF SESSION EXIST BEFORE STARTING IT:
if (session_status() == PHP_SESSION_NONE || session_id() == '') {
session_start();
}
class Message {
protected $msg;
public function __construct() {
if(!isset($_SESSION['msg'])){
$_SESSION['msg'] = array();
}
}
public function setText($message){
if(!in_array($message, $_SESSION['msg'])){
$_SESSION['msg'][] = $message;
}
}
public function getText(){
return "Some Logic for getting Message";
}
}
?>
<?php
// INSIDE OF YOUR VIEW SCRIPT; AT THE VERY TOP, ENABLE SESSION AS WELL:
//FIRST CHECK IF SESSION EXIST BEFORE STARTING IT:
if (session_status() == PHP_SESSION_NONE || session_id() == '') {
session_start();
}
// THEN LOOP THROUGH THE SESSION DATA FOR MESSAGES TO BE DISPLAYED
$msg = new Message();
if(isset($_SESSION['msg'])) {
foreach ($_SESSION ["msg"] as $msg) :
echo $msg->getText();
endforeach;
unset ($_SESSION ["msg"]);
}
I had to do a basic login system to protect a page, and I have no access to database so i store the username and password hard coded in php page.
My question is, can this login system hold againts an attack? I need it to hold about 1 month.
Any sugestions to improve will be helpefull.
The code is not in laravel, even if it might look like.
The username and password, will be changed to something stronger of course.
Thank you in advance.
<?php
class UserController {
private $username;
private $password;
private $isLoggedIn = false;
// Credentials
public function credentials() {
$credentials = array(
array(
"username" => "telekom",
"password" => "1234"
),
array(
"username" => "telekom2",
"password" => "1234"
)
);
return $credentials;
}
// Basic login
public function login() {
foreach ($this->credentials() as $credential) {
if ($this->username == $credential['username'] && $this->password == $credential['password']) {
Session::put('username', $this->username);
Session::put('password', $this->password);
$this->isLoggedIn = true;
}
}
}
// Get login status
public function isLoggedIn() {
return $this->isLoggedIn;
}
// Logout
public function logout() {
// Delete all sessions
Session::all();
redirect('/telekom/');
}
// Telekom
public function telekom() {
$form = new Form();
if (Input::get('logout') == 1) {
$this->logout();
}
// Post Data from login form
if (Input::has('username') || Input::has('password')) {
if (!$form->isCsrfValid()) {
$form->errors['CSRF'] = "CSRF Token";
} // CSRF protection is on, comment to disable
if (empty($form->errors)) {
$this->username = Input::get('username');
$this->password = Input::get('password');
// Check Login
$this->login();
if (!$this->isLoggedIn()) {
Session::put('login', 'Username and password do not match.');
} else {
redirect('/telekom/');
}
} else {
Session::put('login', '<p class="color-dark-red"><strong>Errors:</strong></p>
<p>' . $form->displayErrors($form->errors) . '</p>');
}
// Check if session has username and password
} elseif (Session::has('username') && Session::has('password')) {
$this->username = Session::get('username', false);
$this->password = Session::get('password', false);
// Check Login
$this->login();
}
}
}// EOF Class User
// Outside class
$user = new UserController();
// Outside class
if (!$user->isLoggedIn()) {
// display login form
} else {
// display protected content
}
?>
My comments are getting lengthy, so I'll just move them here. I would not recommend you put the username and password in the same file. If PHP ever fails to process the page, it will be dumped as plain text to the user. Even for database connections (where the un/pwd almost have to be stored plain text), most people don't put the information in the same file.
You have a couple options:
Make a separate PHP file that sets your UN/PWD variables, put it somewhere that isn't accessible from outside your server, and include it in index.php. In this case, I wouldn't include the file until right when you're going to compare the variables and let the local scope dump it as soon as possible.
Since this is such basic authentication, you could use Apache's built in password authentication module.
in my opinion, this solution is safe enough when you don't plan to use it forever.
What would I check is setting of your web server - some text editors makes backup copies of edited files, like index.php~, index.php.bkp or so. Make sure whether your web server do not serve those files, if any.
The problem with temporary solutions is that they've never temporary.
Never hard code passwords. Some of the reasons are:
It is harder to keep source code secret than it is a key.
Any vulnerabilities in your site that allow reading of source code may reveal the password.
Passwords from development will end up in production.
It is impossible to change passwords without redeploying.
Is this function good for a quick login function with only one user?
function auth($post, $session)
{
if(isset($post["username"]) && isset($post["password"]))
{
$session["user"] = new stdClass();
$session["user"]->username = $post["username"];
$session["user"]->password = $post["password"];
}
if(isset($session["user"]))
if(is_object($session["user"]))
if($session["user"]->username == "admin" && $session["user"]->password == "test")
return true;
return false;
}
It works but, must it be improved?
Use the session to track whether the user is logged in or not. For example, in the login page, only set the username in the session if the user authenticates properly. Logout page clears it. Then your other pages can check if the username is set in the session or not. No need to store entered password (recommend against).
Is it secure to use
If ($_SESSION['authenticated'] == true) {
/////Show secure page
}
Can someone just go and change where the session variable is stored to make their $_SESSION['autheticated'] = to true?
Same thing with a user having $_SESSION['id'] = to their index id. How would I be able to make this securer?
Could someone just go and change the id value and impersonate another user?
Would the below method be the right way to make something securer?
$_SESSION['random_check'] = (random number)
and also store this in a column in my database and each time I would
If ($_SESSION['authenticated'] == true && $_SESSION['random_check'] == random_number ) {
/////Then show secure page
}
Thanks,
I'm pretty sure Session in most hosting is just an interface to your filesystem, i.e. all Session data is stored in the server's hard disk, if you look at phpinfo() output, you can have a look at where the actual path of Session data is.
With that said, unless you chmod your session path to 777 and the attacker happens to know where you are hosting your app and has the login, then I don't think it's much of an issue.
The bigger issue here is securing your cookie as it's the piece of information that's going back and forth through your server and client, which attackers can use to impersonate legit users.
Yes,Is it secure to use. I use this.
I do this:
-check login,if is an valid login , set $_SESSION['logged'] = 'yes' and generate um token $_SESSION['token'] = 'the token'
this token, I save in an input html element and check in each action.
something like:
<?php
class token {
public function generateToken() {
return $_SESSION['token'] = md5( microtime() );
}
function generateField($name = "token"){
return "<input type='hidden' value='{$_SESSION['token']}' name='{$name}'>";
}
public function getToken() {
return $_SESSION['token'];
}
public function getTokenFromFields($method = "GET") {
return strtoupper($method) == "GET" ? $_GET['token'] : $_POST['token'];
}
public function checkToken() {
return $this -> getToken() == $this -> getTokenFromFields();
}
public function updateToken() {
$_SESSION['token'] = md5( microtime() );
}
}
?>
<?php
//orther file
require 'class.token.php';
$token = new token();
$Atoken = $token -> generateToken();
echo "<script>
var data = {};
data['token'] = '{$Atoken}';
data['foo'] = 'baa';
</script>";
$token -> generateField();
?>
<script>
$.ajax({type:"GET", url:"process.php", "data=foo=baa&token=" + data.token, success:function(response) { } })
</script>
In process.php:
<?php
if($_SESSION['token'] == $_GET['token']) {
//do something
} else die('bad token');
?>