Secciones

Entradas del blog


Login Codeigniter 4.1.1 & Bootstrap 5 & XAMPP 8

Sin comentarios

Introducción

En éste post, se describirá cómo crear el proceso de login y registro, ésta vez lo haremos paso a paso, así que será un proceso un tanto largo, pero como siempre, al final dejaré el link de descarga del proyecto desde github.

Requerimientos

  • Fedora 33 x86_64 (no probado en otros SO)
  • XAMPP 8.0.1
  • Codeigniter 4.1.0
  • Bootstrap 5 beta.1

Paso 1: Instalar y configurar XAMPP

Se dará por hecho que éste paso ya se tiene, en caso de que no, aquí el link de cómo realizar la configuración e instalación del xampp https://blog.linuxitos.com/instalar-xampp-8-0-0-fedora-33

Paso 2: Creación de la base de datos:

Para la creación de la base de datos, abrimos http://localhost/phpmyadmin/ y clic en base de datos, crear una base de datos que se llame civ_auth_one, una vez seleccionada del panel lateral izquierdo, abrir sql en la pestaña de opciones, copiar, pegar y ejecutar la siguiente instrucción:

CREATE TABLE users(
     user_id INT PRIMARY KEY AUTO_INCREMENT,
     user_name VARCHAR(100),
     user_email VARCHAR(100),
     user_password VARCHAR(200),
     user_created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
 ) ENGINE=INNODB;

Con eso se ha creado la base de datos, y la tabla a utilizar

Paso 3: Configurar Codeigniter 4.1.0

Descargar codeigniter 4.1.10, desde https://www.codeigniter.com/

Una vez descargado, mover la carpeta a /opt/lampp/htdocs, cambiar de nombre el archivo env a .env. Y eliminar los archivos que no se utilizaran, dejar únicamente los siguientes archivos y directorios.

Para mover el directorio descargado, recomiendo primero cambiarle el nombre a civ-auth-one luego moverlo a la ruta /opt/lampp/htdocs/

cd ~ /Descargas
mv CodeIgniter4-4.1.0 civ-auth-one
sudo mv civ-auth-one /opt/lampp/htdocs

En lo personal y para entornos de desarrollo, prefiero utilizar las url directamente, en lugar lanzarlo con spark.

--- personal

Modificar index.

Copiar el archivo index.php que se encuentra en el directorio public/index.php y pegarlo en la raíz del proyecto, con las siguientes modificaciones:

<?php
 // Valid PHP Version?
 $minPHPVersion = '7.2';
 if (version_compare(PHP_VERSION, $minPHPVersion, '<'))
 {
     die("Your PHP version must be {$minPHPVersion} or higher to run CodeIgniter. Current version: " . PHP_VERSION);
 }
 unset($minPHPVersion);
 // Path to the front controller (this file)
 define('FCPATH', DIR . DIRECTORY_SEPARATOR);
 /*
  *---------------------------------------------------------------
 BOOTSTRAP THE APPLICATION
 *---------------------------------------------------------------
 This process sets up the path constants, loads and registers
 our autoloader, along with Composer's, loads our constants
 and fires up an environment-specific bootstrapping.
 */ 
 // Ensure the current directory is pointing to the front controller's directory
 chdir(DIR);
 // Load our paths config file
 // This is the line that might need to be changed, depending on your folder structure.
 require realpath(FCPATH . 'app/Config/Paths.php') ?: FCPATH . 'app/Config/Paths.php';
 // ^^^ Change this if you move your application folder
 $paths = new Config\Paths();
 // Location of the framework bootstrap file.
 $bootstrap = rtrim($paths->systemDirectory, '\/ ') . DIRECTORY_SEPARATOR . 'bootstrap.php';
 $app       = require realpath($bootstrap) ?: $bootstrap;
 /*
  *---------------------------------------------------------------
 LAUNCH THE APPLICATION
 *---------------------------------------------------------------
 Now that everything is setup, it's time to actually fire
 up the engines and make this app do its thang.
 */
 $app->run(); 

Modificando el archivo .env

Se va establecer el acceso a la base de datos, establecer que es un proyecto development, y la url del proyecto, de tal modo que las secciones a modificadas quedarán de la siguiente manera:

--------------------------------------------------------------------
 ENVIRONMENT
 --------------------------------------------------------------------
 CI_ENVIRONMENT = development
 --------------------------------------------------------------------
 APP
 --------------------------------------------------------------------
 app.baseURL = 'http://localhost/civ-auth-one/'
 app.forceGlobalSecureRequests = false

--------------------------------------------------------------------
 DATABASE
 --------------------------------------------------------------------
 database.default.hostname =localhost
 database.default.database =auth_civ_one
 database.default.username =root
 database.default.password =
 database.default.DBDriver =MySQLi
 database.default.port =3307

En caso de que la configuración específica de su XAMPP, usuario root, puerto, contraseña, nombre de bd, etc., se haya personalizado, entonces aquí se debe especificar exactamente tal cual lo tienen, o no se podrá acceder.

El proyecto en este ejemplo se llama civ-auth-one, por lo tanto la url incluye ese nombre, es decir, el nombre del directorio que se encuentra en al ruta /opt/lampp/htdocs/

Asignar permiso al proyecto

Para el correcto funcionamiento, es necesario asignar permisos correctamente al proyecto, éstos permisos son necesario para que se pueden crear logs de archivos, modificar o subir archivos desde la interfaz web.

cd /opt/lampp/htdocs
sudo chmod 775 -R civ-auth-one
sudo chown -R daemon:tu-usuario civ-auth-one
sudo chmod 777 -R civ-auth-one/writable

**tu-usuario: aquí se debe reemplazar por el nombre del usuario

Accediendo desde la url

Con éstos cambios, ahora al acceder desde la url http://localhost/civ-auth-one/, debe visualizarse la página de inicio de codeginiter 4.1.0. Aún sin modificar nada.

Paso 4: Creando modelos y vistas

Crear modelo UserModel

Se crea un archivo de nombre UserModel.php dentro del directorio app/Models y pegar el siguiente contenido dentro del mismo:

<?php
namespace App\Models;

use CodeIgniter\Model;

class UserModel extends Model{
	protected $table 			= 'users';
	protected $primaryKey 		= 'user_id';
	protected $allowedFields 	= ['user_id', 'user_name', 'user_email', 'user_password', 'user_created_at'];
}

Crear el controlador Register

Se crea un archivo php con el nombre de Register.php dentro del directorio de app/Controllers y pegar el siguiente contenido.

<?php
namespace App\Controllers;
use App\Models\UserModel;

class Register extends BaseController{
	protected $helpers = [];
	protected $db;

	public function index(){
		//include helper form
		helper(['form']);
		$data = [];
		$data['title'] = 'Registro';
		//echo view('register', $data);
		return view('register', $data);
	}
 
	public function save(){
		//include helper form
		helper(['form']);
		//set rules validation form
		$rules = [
			'name'          => 'required|min_length[3]|max_length[20]',
			'email'         => 'required|min_length[6]|max_length[50]|valid_email|is_unique[users.user_email]',
			'password'      => 'required|min_length[6]|max_length[200]',
			'confpassword'  => 'matches[password]'
		];
		 
		if($this->validate($rules)){
			$model = new UserModel();
			$data = [
				'user_name'     => $this->request->getVar('name'),
				'user_email'    => $this->request->getVar('email'),
				'user_password' => password_hash($this->request->getVar('password'), PASSWORD_DEFAULT)
			];
			$model->save($data);
			return redirect()->to('/dashboard');
		}else{
			$data['validation'] = $this->validator;
			//echo view('register', $data);
			return view('register', $data);
		}
	}
}

Crear la vista de register

Crear un archivo de nombre register.php dentro del directorio app/Views y pegar el siguiente contenido:

<!doctype html>
<html lang="en">
	<head>
		<!-- Required meta tags -->
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1">
		<link rel="icon" href="<?=base_url('assets/custom/images/fav.png');?>">
		<!-- Bootstrap CSS -->
		<link href="<?=base_url('assets/vendor/bootstrap/css/bootstrap.min.css');?>" rel="stylesheet">
		<link href="<?=base_url('assets/vendor/bootstrap/css/animate.css');?>" rel="stylesheet">
		<link href="<?=base_url('assets/vendor/bootstrap/css/animation.css');?>" rel="stylesheet">
		<title><?=$title;?></title>
	</head>
	<body>
		<?php
		include('common/navbar.php');
		?>
		<div class="container mt-5">
			<div class="row justify-content-md-center">
				<div class="col-6">
					<div class="card rounded p-2 mt-5">
						<h1>Registro</h1>
						<?php if(isset($validation)):?>
							<div class="alert alert-danger"><?= $validation->listErrors() ?></div>
						<?php endif;?>
						<form action="<?=base_url('save');?>" method="post">
							<div class="mb-3">
								<label for="name" class="form-label">Nombre</label>
								<input type="text" name="name" class="form-control" id="name" value="<?= set_value('name') ?>" autocomplete="off">
							</div>
							<div class="mb-3">
								<label for="email" class="form-label">Email</label>
								<input type="email" name="email" class="form-control" id="email" value="<?= set_value('email') ?>" autocomplete="off">
							</div>
							<div class="mb-3">
								<label for="password" class="form-label">Contraseña</label>
								<input type="password" name="password" class="form-control" id="password" autocomplete="off">
							</div>
							<div class="mb-3">
								<label for="confpassword" class="form-label">Confirmar contraseña</label>
								<input type="password" name="confpassword" class="form-control" id="confpassword" autocomplete="off">
							</div>
							<button type="submit" class="btn btn-primary float-end">
								Registro
							</button>
						</form>
					</div>
				</div>
			</div>
		</div>
	 
		<!-- Popper.js first, then Bootstrap JS -->
		<script>
			window.jQuery || document.write('<script src="<?=base_url('assets/vendor/jquery/jquery-3.5.1.min.js');?>"><\/script>')
		</script>
		<script src="<?=base_url('assets/vendor/bootstrap/js/popper.min.js');?>"></script>
		<script src="<?=base_url('assets/vendor/bootstrap/js/bootstrap.min.js');?>"></script>
	</body>
</html>

Controlador Login

Crear archivo Login.php en directorio app/Controllers

<?php
namespace App\Controllers;
use App\Models\UserModel;

class Login extends BaseController{
	protected $helpers = [];
	protected $db;

	public function index(){
		helper(['form']);
		$data['title'] = 'Login';
		return view('login', $data);
	} 
 
	public function auth(){
		$session 	= session();
		$model 		= new UserModel();
		$email 		= $this->request->getVar('email');
		$password 	= $this->request->getVar('password');
		$data 		= $model->where('user_email', $email)->first();
		if($data){
			$pass 			= $data['user_password'];
			$verify_pass 	= password_verify($password, $pass);
			if($verify_pass){
				$ses_data = [
					'user_id'       => $data['user_id'],
					'user_name'     => $data['user_name'],
					'user_email'    => $data['user_email'],
					'logged_in'     => TRUE
				];
				$session->set($ses_data);
				return redirect()->to('/dashboard');
			}else{
				$session->setFlashdata('msg', 'Wrong Password');
				return redirect()->to('/login');
			}
		}else{
			$session->setFlashdata('msg', 'Email not Found');
			return redirect()->to('/login');
		}
	}
 
	public function logout(){
		$session = session();
		$session->destroy();
		return redirect()->to('login');
	}
}

Crear vista login.ph

En app/Views crear un archivo con nombre login.php.

<!doctype html>
<html lang="en">
	<head>
		<!-- Required meta tags -->
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1">
		<link rel="icon" href="<?=base_url('assets/custom/images/favicon.png');?>">
		<!-- Bootstrap CSS -->
		<link href="<?=base_url('assets/vendor/bootstrap/css/bootstrap.min.css');?>" rel="stylesheet">
		<link href="<?=base_url('assets/vendor/bootstrap/css/animate.css');?>" rel="stylesheet">
		<link href="<?=base_url('assets/vendor/bootstrap/css/animation.css');?>" rel="stylesheet">
		<title><?=$title;?></title>
	</head>
	<body>
		<?php
		include('common/navbar.php');
		?>
		<div class="container mt-5">
			<div class="row justify-content-md-center">
				<div class="col-6 mt-5">
					<div class="card rounded p-2">
						<h1>Inicio de Sesión</h1>
						<?php if(session()->getFlashdata('msg')):?>
							<div class="alert alert-danger"><?= session()->getFlashdata('msg') ?></div>
						<?php endif;?>
						<form action="<?=base_url('auth');?>" method="post">
							<div class="mb-3">
								<label for="email" class="form-label">Email</label>
								<input type="email" name="email" class="form-control" id="email" value="<?=set_value('email');?>">
							</div>
							<div class="mb-3">
								<label for="password" class="form-label">Contraseña</label>
								<input type="password" name="password" class="form-control" id="password">
							</div>
							<button type="submit" class="btn btn-primary float-end">
								Iniciar
							</button>
						</form>
					</div>
				</div>
			</div>
		</div>
	 
		<!-- Popper.js first, then Bootstrap JS -->
		<script>
			window.jQuery || document.write('<script src="<?=base_url('assets/vendor/jquery/jquery-3.5.1.min.js');?>"><\/script>')
		</script>
		<script src="<?=base_url('assets/vendor/bootstrap/js/popper.min.js');?>"></script>
		<script src="<?=base_url('assets/vendor/bootstrap/js/bootstrap.min.js');?>"></script>
	</body>
</html>

Controlador Dashboard

Crear archivo Dashboard.php en app/Controllers

<?php
namespace App\Controllers;
use App\Models\UsersModel;

class Dashboard extends BaseController{
	public function index(){
		$session = session();
		//echo "Welcome back, ".$session->get('user_name');
		$data['title'] = 'Dashboard';
		return view('dashboard', $data);
	}
}

Crear vista dashboard.php

Se un archivo con el nombre dashboard.php en app/Views. Contiene lo que se mostrará cuando el usuario haya iniciado sesión.

<!doctype html>
<html lang="en">
	<head>
		<!-- Required meta tags -->
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1">
		<link rel="icon" href="<?=base_url('assets/custom/images/fav.png');?>">
		<!-- Bootstrap CSS -->
		<link href="<?=base_url('assets/vendor/bootstrap/css/bootstrap.min.css');?>" rel="stylesheet">
		<link href="<?=base_url('assets/vendor/bootstrap/css/animate.css');?>" rel="stylesheet">
		<link href="<?=base_url('assets/vendor/bootstrap/css/animation.css');?>" rel="stylesheet">
		<title><?=$title;?></title>
	</head>
	<body>
		<?php
		include('common/navbar.php');
		?>
		<div class="container mt-5">
			<div class="row justify-content-md-center">
				<div class="col-12">
					<div class="card rounded p-2 mt-5">
						<h1>Dashboard</h1>
						<?php if(isset($validation)):?>
							<div class="alert alert-danger"><?= $validation->listErrors() ?></div>
						<?php endif;?>
						Bienvenido a tu panel de control.
					</div>
				</div>
			</div>
		</div>
	 
		<!-- Popper.js first, then Bootstrap JS -->
		<script>
			window.jQuery || document.write('<script src="<?=base_url('assets/vendor/jquery/jquery-3.5.1.min.js');?>"><\/script>')
		</script>
		<script src="<?=base_url('assets/vendor/bootstrap/js/popper.min.js');?>"></script>
		<script src="<?=base_url('assets/vendor/bootstrap/js/bootstrap.min.js');?>"></script>
	</body>
</html>

Paso 5: Crear Auth y NoAuth

CodeIgniter 4 proporciona una característica de filtro que funciona para manejar Before Request o After Request. Esta característica es muy útil para manejar la comprobación o validación de cada solicitud o de unas pocas solicitudes que se escriben con el mismo código.

En este caso, protegeremos la función index() en el Controlador "Dashboard.php" de los usuarios que no hayan iniciado sesión utilizando el Filtro. De esta manera, tendrás una idea general de cómo funcionan los Filtros en CodeIgniter 4.

Archivo Auth

Crear un archivo de filtro llamado "Auth.php" en la carpeta "app/Filters", luego escriba el siguiente código:

<?php
namespace App\Filters;
 
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Filters\FilterInterface;
 
class Auth implements FilterInterface
{
	public function before(RequestInterface $request, $arguments = null)
	{
		if(! session()->get('logged_in')){
			return redirect()->to('/'); 
		}
	}
 
	//--------------------------------------------------------------------
 
	public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
	{
		// Do something here
	}
}

Archivo Noauth.php en app/Filters

Éste archivo filtrará los métodos y funciones que no necesariamente deben estar logeados, con éste se podrá realizar alguna otra acción cuando el usuario entre a enlaces que no requieren inicio de sesión.

<?php
namespace App\Filters;

use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\Filters\FilterInterface;

class Noauth implements FilterInterface
{
	public function before(RequestInterface $request,  $arguments = NULL)
	{
		helper(['url', 'session', 'emai', 'upload', 'system_helper', 'database']);
		// Do something here
		if(session()->get('logged_in')){
			return redirect()->to(base_url('/dashboard'));
			//redireccionar(base_url('ptable'), 'Bienvenido de nuevo', 'success', 'fa fa-check', ' ', '#');
		}
	}

	//--------------------------------------------------------------------

	public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
	{
		// Do something here
	}
}

En el filtro "Auth.php" anterior, hay 2 funciones, a saber: function before() y function after(). En este caso, sólo vamos a utilizar la función before(). La función before, sirve para validar la petición antes de que se ejecute la propia petición. En el filtro "Auth.php" anterior, redirigimos a los usuarios a la página de inicio de sesión si acceden a una página antes de iniciar la sesión.

Esto puede aplicarse globalmente, es decir, se aplica a todas las peticiones, o puede ser sólo para algunas peticiones. En este caso, sólo lo utilizamos para proteger el controlador "Dashboard.php". Por lo tanto, no lo aplicamos globalmente, porque queremos que los controladores "Login.php" y "Register.php" sean accesibles sin necesidad de iniciar sesión.

Abrir el archivo "Filters.php" ubicado en la carpeta "app/Config", buscar el siguiente código y agregar las dos últimas líneas de auth y noauth:

public $aliases = [
		'csrf'     => CSRF::class,
		'toolbar'  => DebugToolbar::class,
		'honeypot' => Honeypot::class,
		'auth'     => \App\Filters\Auth::class,
		'noauth' => \App\Filters\Noauth::class,
	];

Paso 5: Pruebas

Ahora ya está listo el código: se puede acceder al link del proyecto desde el navegador, y probar las funciones de inicio de sesión y registro.

Descargar el proyecto completo desde:

https://github.com/jesusferm/auth-civ-mariadb

Próximante subiré el proyecto con funciones con ajax, agregar registros, modificarlos, sección de perfil de usuario, cambio de contraseña, recuperación de contraseña por email.

Comentarios:

Entradas del blog
Redes sociales
Accesos directos