I've created a registering form, and I'd like to validate user input, for security purposes.
I've created some functions, shown below.
I am just unsure on how to implement them correctly. Do I nest if statements? Do I just keep it like I have it now?
How do I stop my script when something isn't right? To prevent an insert from even being tried when something isn't right.
Any help is greatly appreciated.
function validateLength($stringToValidate, $minimumLength) {
if(strlen($stringToValidate) < $minimumLength) {
return [
'error' => 'Minimum length is 8 charachters',
'class' => 'alert alert-danger',
];
} else {
return true;
}
}
function validateEmail($emailToVerify) {
if(filter_var($emailToVerify, FILTER_VALIDATE_EMAIL)) {
return true
} else {
return [
'error' => '<strong>Error:</strong> That is not a valid email address',
'class' => 'alert alert-danger'
];
}
}
function formIsFilledIn(array $formInputs = []) {
foreach ($formInput as $inputField) {
if(empty($inputField)) {
return [
'error' => '<strong>Error: </strong> Fill in all fields.',
'class' => 'alert alert-danger',
];
}
}
return null;
}
Now, I'm using every function like so.
$formErrors = formIsFilledIn($_POST);
if($formErrors !== null) {
// Something is not filled in
}
$formErrors = validateLength($_POST['username'], 8);
if($formErrors !== true) {
// Username doesn't have enough characters
}
$formErrors = validateLength($_POST['password'], 8);
if($formErrors !== true) {
// Password doesn't have enough characters
}
For completeness, this is the insert part (it works properly)
$stmt = $connect->prepare('INSERT INTO `users` (user_name, user_password, user_email, user_perms, user_created_at) VALUES (?, ?, ?, ?, ?)');
if($stmt) {
$username = $_POST['username'];
$password = hashPassword($_POST['password']);
$email = $_POST['email'];
$date = date('Y-m-d H:i:s');
$perms = "Gebruiker";
$stmt->bind_param('sssss', $username, $password, $email, $perms, $date);
if($stmt->execute()) {
$err = "<strong>Success: </strong> The account has been created";
$class = "alert alert-success";
} else {
$err = "<strong>Error:</strong> Something went wrong";
$class = "alert alert-danger";
}
}
You could indeed chain the if's together using elseif. I would however suggest some changes to the functions. Instead of letting them validate and return an array containing some errors, you'd need to only let them validate and return either true or false
It would look somewhat like this:
function validateLength($stringToValidate, $minimumLength) {
if(strlen($stringToValidate) < $minimumLength) {
return false;
} else {
return true;
}
}
function validateEmail($emailToVerify) {
if(filter_var($emailToVerify, FILTER_VALIDATE_EMAIL)) {
return true;
} else {
return false;
}
}
function formIsFilledIn(array $formInputs = []) {
foreach ($formInputs as $inputField) {
if(empty($inputField)) {
return false;
}
}
return true;
}
This means that you can do the following:
if(!formIsFilledIn($_POST)) {
$error = [
'error' => '<strong>Error: </strong> Fill in all fields.',
'class' => 'alert alert-danger',
];
} elseif(!validateLength($_POST['username'], 8) || !validateLength($_POST['password'], 8)) {
$error = [
'error' => 'Minimum length is 8 charachters',
'class' => 'alert alert-danger',
];
}
elseif(!validateEmail($_POST['email'])) {
$error = [
'error' => '<strong>Error:</strong> That is not a valid email address',
'class' => 'alert alert-danger'
];
}
else {
// now you can call a function that starts to insert stuff, everything has been validated
}
Of course, this would becomes longer the longer the form will get. An other option would be to iterate over the post and check if all fields have a valid length. When that is done you can check the email and all other special fields
Related
I made a captcha login it is working so far but there is two problem and that problem is that first, when your username or password is wrong the page went to blank. Second, when both of the username,password and captcha are wrong the page went blank
but when your username and password are correct and the captcha is wrong it will call the echo'captcha is not correct';
function aksi_login(){
$data = array('username' => $this->input->post('username', TRUE),
'password' => md5($this->input->post('password', TRUE))
);
$this->load->model('m_model'); // load model_user
$hasil = $this->m_model->cek_user($data);
if ($hasil->num_rows() == 1 && $this->input->post('submit')){
$inputCaptcha = $this->input->post('captcha');
$sessCaptcha = $this->session->userdata('captchaCode');
if($inputCaptcha === $sessCaptcha){
foreach ($hasil->result() as $sess) {
$sess_data['logged_in'] = 'Sudah Login';
$sess_data['id_user'] = $sess->uid;
$sess_data['username'] = $sess->username;
$sess_data['level'] = $sess->level;
$this->session->set_userdata($sess_data);
}
if ($this->session->userdata('level')=='1') {
redirect('admin');
}
elseif ($this->session->userdata('level')=='2') {
redirect('guru');
}
elseif ($this->session->userdata('level')=='3') {
redirect('siswa');
}
else {
echo'username or password is wrong'
}
}
else{
echo "captcha code is not correct";
}
}
}
I think so far is because of the controller code and i have made some changes I tried putting another elseif like
elseif ($this->session->userdata('username')== FALSE && $this->session->userdata('password')==FALSE){
echo'username or password is wrong';
}
else {
echo'username or password is wrong';
}
but unfortunately is not working
Its better to check for captcha first in a separate condition then check for validation, so if you got everything right and your post values are all ok then you should do it like this:
if (this->captcha_validation($this->input->post('captcha')))
{
$this->form_validation->set_rules($this->rules);
if ($this->form_validation->run() === TRUE)
{
$username = $this->input->post('username');
$password = $this->input->post('password');
// your magic
}
else
{
// array of validation errors
validation_errors = $this->form_validation->error_array();
}
}
else
{
// wrong captcha
$this->recaptcha();
}
Now you have isolated the two checks and made it way easier for recaptcha, but more importantly you don't need to make form validation if the captcha is wrong in the first place.
...
Not sure how your code works but in // your magic up there put your logic like this:
$this->load->model('m_model'); // load model_user
$hasil = $this->m_model->cek_user($data);
if ($hasil->num_rows() > 0)
{
foreach ($hasil->result() as $sess)
{
$sess_data['logged_in'] = 'Sudah Login';
$sess_data['id_user'] = $sess->uid;
$sess_data['username'] = $sess->username;
$sess_data['level'] = $sess->level;
$this->session->set_userdata($sess_data);
}
if ($this->session->userdata('level') == '1')
{
redirect('admin');
}
elseif ($this->session->userdata('level') == '2')
{
redirect('guru');
}
elseif ($this->session->userdata('level')=='3')
{
redirect('siswa');
}
}
My suggestion to to rewrite your controller and use Form Validation as it is also codeigniter standard library
Check the official documentation here
https://www.codeigniter.com/userguide3/libraries/form_validation.html
//your validation config should be something like this
public function login() {
$form_rules = [
[
'field' => 'username',
'label' => 'Username',
'rules' => 'required',
],
[
'field' => 'password',
'label' => 'Password',
'rules' => 'required',
],
[
'field' => 'captcha',
'label' => 'No HP',
'rules' => 'rules' => 'required|callback_check_captcha'
],
];
$this->form_validation->set_rules($this->form_rules);
if ($this->form_validation->run() == TRUE) {
//check username & password
//if you're sure that username is unique, you can directly get 1 data with ->row()
$check = $this->m_model->cek_user($data)->row();
if($check) {
switch($check->level) {
case '1' :
break;
case '2' :
......
......
}
} else {
//wrong username / password
}
} else {
//show login form with view
}
}
/*callback fro form validation*/
public function check_captcha($str) {
if(!empty($this->session->cap_word)) {
$expiration = time() - $this->config->item('captcha_expiration');
if($this->session->cap_time > $expiration) {
if($this->session->cap_word == $str) {
return TRUE;
} else {
$this->form_validation->set_message('check_captcha', 'Wrong captcha.');
return FALSE;
}
} else {
$this->form_validation->set_message('check_captcha', 'Session captcha expired.');
return FALSE;
}
} else {
$this->form_validation->set_message('check_captcha', 'KWrong captcha.');
return FALSE;
}
}
I'm create a function to insert and update with many conditional and I want to find out all that conditional both false and true and return it as array to client for checking if some data is missing or can't update or insert.
I've used $return to find out which one conditional is work or not.
public function trans_issue_till() {
if (Request::ajax()) {
$return = [];
$rule = [
'till_account_id' => 'required',
'from_account' => 'required',
];
$fromacc = Request::input('from_account');
if ($this->CheckPermId_from_session(90) == true) {
$fromacc = Request::input('coa_name');
}
$data = [
'till_account_id' => Request::input('till_account_id'),
'from_account' => $fromacc,
];
$v = Validator::make($data, $rule);
if ($v->fails()) {
$return['form'] = false;
} else {
$update = Teller::where('id', '=', $data['till_account_id'])->update(array('balance' => $data['balance']));
$insert = DB::table('till_transaction')->insert($data);
if(!$update) {
$return['upd_bl'] = false;
} if(!$insert){
$return['ins_trans'] = false;
}else{
$return;
}
}
} else {
$return['ins_trans'] = 'login';
return redirect()->route('login');
}
foreach($return as $items){
var_dump($items);
}
return $...........
}
as the final sentence I used foreach for check all the array index which one is true and false after that return to browser.
<?php
class CustomerLocation{
public function checkPhone($phone) {
if(isset($phone) && (strlen($phone) == 10 || strlen($phone) == 12))
{
return $phone;
}
else
{
$aResponse = array(
"error" => "400",
"message" => array(
"code" => "Invalid_phone",
"dev_msg" => "The phone must be at least 10 characters.",
"user_msg" => "Please enter valid phone number."
),
);
return $aResponse;
}
}
}
class test {
public function test()
{
$loc = new CustomerLocation();
$query = array("phone" => $loc->checkPhone('123456'));
// some more code be executed
}
}
I want to return from the test function with the response message written in checkPhone method of CustomerLocation class if the phone number does not match the specific condition. But the problem is that I want to check the field of the array which is either by post or request method. How to go about any help will be grateful. Thanks.
Check this,
<?php
class CustomerLocation{
public function checkPhone($phone = NULL) {
if(isset($phone) && (strlen($phone) == 10 || strlen($phone) == 12))
{
return $phone;
}
else
{
$aResponse = array(
"error" => "400",
"message" => array(
"code" => "Invalid_phone",
"dev_msg" => "The phone must be at least 10 characters.",
"user_msg" => "Please enter valid phone number."
),
);
return $aResponse;
}
}
}
class test {
public function testnew($phone1)
{
$loc = new CustomerLocation();
$checkphone = $loc->checkPhone($phone1);
$error = isset($checkphone['error']) ? $checkphone['error'] : '';
if($error == 400){
$query = array("phone" => $checkphone);
return $query;
}
else{
// do some thing
}
}
}
echo "<pre>";
$test = new test();
$phone1 = '0123456789';//$_POST['phone'];
$output = $test->testnew($phone1);
print_r($output);
May be solve your problem
I am not sure if this question has been answered in round about ways through other questions but...
I am creating a web page for my job which has multiple entry fields (all of which have the same validation code). The following is a small section of my php code:
if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (empty($_POST["bottomair"])) {
$bottomairerror = "Maketable bottom air temp is required";
} else {
$bottomair = test_input($_POST["bottomair"]);
if (!filter_var($bottomair, FILTER_VALIDATE_INT, array("options" => array("min_range"=>$coldmin, "max_range"=>$coldmax)))) {
$bottomairerror = $errormsg;
}
}
if (empty($_POST["topair"])) {
$topairerror = "Maketable top air temp is required";
} else {
$topair = test_input($_POST["topair"]);
if (!filter_var($topair, FILTER_VALIDATE_INT, array("options" => array("min_range"=>$coldmin, "max_range"=>$coldmax)))) {
$topairerror = $errormsg;
}
}
if (empty($_POST["meat"])) {
$meaterror = "Maketable meat temp is required";
} else {
$meat = test_input($_POST["meat"]);
if (!filter_var($meat, FILTER_VALIDATE_INT, array("options" => array("min_range"=>$coldmin, "max_range"=>$coldmax)))) {
$meaterror = $errormsg;
}
}
if (empty($_POST["cheese"])) {
$cheeseerror = "Maketable cheese temp is required";
} else {
$cheese = test_input($_POST["cheese"]);
if (!filter_var($cheese, FILTER_VALIDATE_INT, array("options" => array("min_range"=>$coldmin, "max_range"=>$coldmax)))) {
$cheeseerror = $errormsg;
}
}
if (empty($_POST["walkin"])) {
$walkinerror = "Walk-In temp is required";
} else {
$walkin = test_input($_POST["walkin"]);
if (!filter_var($walkin, FILTER_VALIDATE_INT, array("options" => array("min_range"=>$coldmin, "max_range"=>$coldmax)))) {
$walkinerror = $errormsg;
}
}
if (empty($_POST["refrig1"])) {
$refrig1error = "Refrigerator #1 temp is required";
} else {
$refrig1 = test_input($_POST["refrig1"]);
if (!filter_var($refrig1, FILTER_VALIDATE_INT, array("options" => array("min_range"=>$coldmin, "max_range"=>$coldmax)))) {
$refrig1error = $errormsg;
}
}
if (empty($_POST["refrig2"])) {
$refrig2error = "Refrigerator #2 temp is required";
} else {
$refrig2 = test_input($_POST["refrig2"]);
if (!filter_var($refrig2, FILTER_VALIDATE_INT, array("options" => array("min_range"=>$coldmin, "max_range"=>$coldmax)))) {
$refrig2error = $errormsg;
}
}
if (empty($_POST["refrig3"])) {
$refrig3error = "Refrigerator #3 temp is required";
} else {
$refrig3 = test_input($_POST["refrig3"]);
if (!filter_var($refrig3, FILTER_VALIDATE_INT, array("options" => array("min_range"=>$coldmin, "max_range"=>$coldmax)))) {
$refrig3error = $errormsg;
}
}
}
Is there a function which I can use to "tidy up" my php code so that I do not have as many lines to debug when things go sideways with the coding?
I think you only have three options here:
Write perfect code so that your code never goes sideways (highly unlikely for any developer :)
Change from an if structure to a switch structure
Evolve your debugging procedure/tools to make debugging less painful in general.
Create an array with the names of the required fields as a key, and an error message as a value. Then loop through this array. Use the keys in the $_POST superglobal to see if it's been set. If it's not set, throw the error message you defined as the value. Something along the lines of:
$required_parameters = array(
"bottomair" => "Maketable bottom air temp is required",
"topair" => "Maketable top air temp is required",
// etc
);
$errorslist = array();
foreach($required_parameters as $key => $error)
{
if(empty($_POST[$key]))
{
$errorslist[] = $error; // append to list
}
else
{
$test = test_input($_POST[$key]);
if (!filter_var($test, FILTER_VALIDATE_INT, array("options" => array("min_range"=>$coldmin, "max_range"=>$coldmax))))
{
$errorslist[] = $errormsg; // <-- I don't know where you define errormsg, though
}
}
}
You can then loop through the $errorslist array as well to display all errors in a list.
I want the auth component to allow user to login entrying either username or email.
In my users table, both fields - userName and userEmail are unique.
At time of registration, the password is generated like:
sha1($username.$password);
The problem is that user is not able to login using email.
App Controller
var $components = array('Auth');
public function beforeFilter(){
if(isset($this->params['prefix']) && $this->params['prefix'] == 'webadmin') {
$this->Auth->userModel = 'Admin';
$this->Auth->logoutRedirect = $this->Auth->loginAction = array('prefix' => 'webadmin', 'controller' => 'login', 'action' => 'index');
$this->Auth->loginError = 'Invalid Username/Password Combination!';
$this->Auth->authError = 'Please login to proceed further!';
$this->Auth->flashElement = "auth.front.message";
$this->Auth->loginRedirect = array('prefix'=>'webadmin', 'controller'=>'dashboard', 'action'=>'index');
}
else{
$this->layout="front";
//$this->Auth->autoRedirect = false;
// $this->Auth->logoutRedirect = $this->Auth->loginAction = array('controller' => 'users', 'action' => 'login');
// $this->Auth->loginRedirect = array('controller'=>'blogs', 'action'=>'index');
$this->Auth->fields = array(
'username' => 'userName',
'password' => 'password'
);
$this->Auth->userScope = array('User.status'=>1);
$this->Auth->loginError = "The username/email and password you entered doesn't match our records.";
$this->Auth->authError = 'Please login to view this page!';
$this->Auth->flashElement = "auth.front.message";
$this->Auth->loginRedirect = array('controller'=>'profiles', 'action'=>'index');
}
Users Controller: the login function goes like:
if(!empty($this->data))
{
// Try to login with Email
if (!empty($this->Auth->data)) {
// save username entered in the login form
$username = $this->Auth->data['User']['userName'];
// find a user by e-mail
$find_by_email = $this->User->find('first', array(
'conditions' => array('userEmail' => $this->Auth->data['User']['userName']),
'fields' => 'userName'));
// found
if (!empty($find_by_email))
{
$this->Auth->data['User']['userName'] = $find_by_email['User']['userName'];
$this->data['User']['password']=$this->Auth->data['User']['password'];
if (!$this->Auth->login($this->data)) {
// login failed
// bring back the username entered in the login form
$this->Auth->data['User']['username'] = $username;
} else {
$this->Session->delete('Message.auth');
// redirect
if ($this->Auth->autoRedirect) {
$this->redirect($this->Auth->redirect(), null, true);
}
}
}
}
}
Auth.php:(I have made some changes here in the way password is generated as I am using the cakephp session to auto-login to SMF forum.)
function login($data = null) {
$data['User.password'] = sha1(strtolower($data['User.userName']) . $_POST['data']['User']['password']);
$this->__setDefaults();
$this->_loggedIn = false;
if (empty($data)) {
$data = $this->data;
}
if ($user = $this->identify($data)) {
$this->Session->write($this->sessionKey, $user);
$this->_loggedIn = true;
}
return $this->_loggedIn;
}
I took help from this link, but I am not getting username in $data['User.userName'] in auth.php, I getting email here, so the password goes wrong and results in login failure.
Please help.
You have error in the conditions, it should be:
'conditions' => array('userEmail' => $this->Auth->data['User']['email']),
You are checking the username .
The only way I could make it work is by modifying auth.php in cake.
App Controller
I added this to the code in before filter:
$this->Auth->fields = array(
'username' => 'userName',
'email'=>'userEmail',
'password' => 'password'
);
Users Controller I removed all the extra code.
Auth.php
I made changes to the identify function to check email after encrypting the password in //the way I wanted.
function identify($user = null, $conditions = null) {
if ($conditions === false) {
$conditions = array();
} elseif (is_array($conditions)) {
$conditions = array_merge((array)$this->userScope, $conditions);
} else {
$conditions = $this->userScope;
}
$model =& $this->getModel();
if (empty($user)) {
$user = $this->user();
if (empty($user)) {
return null;
}
} elseif (is_object($user) && is_a($user, 'Model')) {
if (!$user->exists()) {
return null;
}
$user = $user->read();
$user = $user[$model->alias];
} elseif (is_array($user) && isset($user[$model->alias])) {
$user = $user[$model->alias];
}
if (is_array($user) && (isset($user[$this->fields['username']]) || isset($user[$model->alias . '.' . $this->fields['username']]))) {
if (isset($user[$this->fields['username']]) && !empty($user[$this->fields['username']]) && !empty($user[$this->fields['password']])) {
if (trim($user[$this->fields['username']]) == '=' || trim($user[$this->fields['password']]) == '=') {
return false;
}
$find = array(
$model->alias.'.'.$this->fields['username'] => $user[$this->fields['username']],
$model->alias.'.'.$this->fields['password'] => $user[$this->fields['password']]
);
} elseif (isset($user[$model->alias . '.' . $this->fields['username']]) && !empty($user[$model->alias . '.' . $this->fields['username']])) {
if (trim($user[$model->alias . '.' . $this->fields['username']]) == '=' || trim($user[$model->alias . '.' . $this->fields['password']]) == '=') {
return false;
}
// my code starts
$user['User.userEmail']=$user['User.userName'];
//find username using email
$find_by_email= $model->find('first', array(
'fields' => array('User.userName','User.realpass'),
'conditions' => array($model->alias.'.'.$this->fields['email'] => $user[$model->alias . '.' . $this->fields['email']]),
'recursive' => 0
));
if(!empty($find_by_email))
{
$uname=strtolower($find_by_email['User']['userName']);
$pwd=$user[$model->alias . '.' . $this->fields['password']];
}
else
{
$uname=strtolower($user[$model->alias . '.' . $this->fields['username']]);
$pwd=$user[$model->alias . '.' . $this->fields['password']];
}
$thepassword = sha1($uname.$pwd); // encrypt password
// find user where username or email equals to the username passed
$find = array(
'OR' => array($model->alias.'.'.$this->fields['username'] => $user[$model->alias . '.' . $this->fields['username']], $model->alias.'.'.$this->fields['email'] => $user[$model->alias . '.' . $this->fields['username']]),
$model->alias.'.'.$this->fields['password'] => $thepassword
);
} else {
return false;
}
$cond=array_merge($find, $conditions);
$data = $model->find('first', array(
'conditions' => $cond,
'recursive' => 0
));
// my code ends here
if (empty($data) || empty($data[$model->alias])) {
return null;
}
} elseif (!empty($user) && is_string($user)) {
$data = $model->find('first', array(
'conditions' => array_merge(array($model->escapeField() => $user), $conditions),
));
if (empty($data) || empty($data[$model->alias])) {
return null;
}
}
if (!empty($data)) {
if (!empty($data[$model->alias][$this->fields['password']])) {
unset($data[$model->alias][$this->fields['password']]);
}
return $data[$model->alias];
}
return null;
}
Lastly, I commented the password encrypt code to return the simple password so that I can encrypt it the wat I needed in the above function.
function password($password) {
//return Security::hash($password, null, true);
return $password;
}