Además, haremos uso de la base de datos de Microsoft SQL Server 2017 para la creación del procedimiento almacenado (implementación - Transact-SQL); mencionar que hará uso de la tabla Usuario creado en el proyecto ASP.NET Core - Implementando CRUD en MVC con C#.
Requisitos:
- Microsoft Visual Studio Community 2019
- Microsoft .NET Core, ASP.NET Core 3.1
- Microsoft SQL Server 2017 (RTM-GDR) - Express Edition (64-bit)
- Framework Bootstrap (para mejorar el diseño de nuestra aplicación)
- Framework jQuery Validation (para la validación de lado del cliente)
Lo que veremos en este articulo:
Paso 1: Crear el procedimiento almacenado - Transact-SQL.
CREATE PROCEDURE [dbo].[GET_SEG_USUARIO]
@usuario VARCHAR (50),
@contrasena VARCHAR (250)
AS
BEGIN
SELECT usuario, contrasena
FROM Usuario
WHERE usuario = @usuario AND contrasena = @contrasena
END
El procedimiento almacenado cuenta con 2 parámetros (@us8uario y @contrasena) de entrada con el fin de retornar el usuario y contraseña de acuerdo a los datos ingresado desde la aplicación que se restringe desde el Script de Transact-SQL con la sentencia básica del Where (WHERE usuario = @usuario AND contrasena = @contrasena).
Paso 2: Implementar cadena de conexión a la base de datos.
Clic en Agregar |
{
"ConnectionStrings": {
"DefaultConnection": "Data Source=HPAREDES\\SQLEXPRESS;Database=BD_SEGURIDAD;UID=usuario_para_acceder_al_server;Password=contraseña_para_acceder_al_server"
}
}
Paso 3: Agregar los paquetes de dependencia desde NuGet.
Microsoft.Data.SqlClient es la creación de un nuevo SqlClient, es un nuevo espacio de nombre que permite la convivencia del antiguo System.Data.SqlClient.
Paso 4: Implementar el método de validación.
using
Microsoft.AspNetCore.Mvc.ModelBinding.Validation;//Iniciamos el namespace ModelBinding Validation
namespace DEMO03_LOGIN.CustomValidation
{
public class ContrasenaValidate : Attribute,
IModelValidator//Acceder a la interfaz
IModelValidator
{
public string ErrorMessage {
get; set; }
/// <summary>
/// Función para la retornar validación - función con inyección de dependencia
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public
IEnumerable<ModelValidationResult> Validate(ModelValidationContext
context)
{
return new
List<ModelValidationResult>
{
new ModelValidationResult("",
ErrorMessage)
};
}
}
}
Paso 5: Crear la entidad usuario y agregar atributos.
public class ClsUsuario
{
public int id { get; set; }
[Required]
public string usuario { get; set; }
[Required]
[ContrasenaValidate(ErrorMessage = "Contraseña no valida")]
public string contrasena { get; set; }
public int intentos { get; set; }
public decimal nivelSeg { get; set; }
public DateTime?
fechaReg { get; set; }
}
Descripción de cada atributos:
Paso 6: Modificar la Configuración del Startup.
using
Microsoft.AspNetCore.Builder;
using
Microsoft.Extensions.DependencyInjection;
namespace DEMO03_LOGIN
{
public class Startup
{
public void
ConfigureServices(IServiceCollection services)
{
services.AddMvc(option => option.EnableEndpointRouting = false);
services.AddSession();
}
public void
Configure(IApplicationBuilder app)
{
app.UseSession();
app.UseMvc(router =>
{
router.MapRoute(
name: "default",
template: "{controller=Login}/{action=Login}/{id?}");
});
}
}
Paso 7: Agregar el controlador e implementar los ActionResults.
using
System.Collections.Generic;//Lista
de colecciones genericas
using
System.Data;//Identificar
el tipo de objeto a manipular en base de datos
using
Microsoft.Data.SqlClient;//Controlador
de acceso a datos
using System.Linq;//Para hacer macth entre lista del dataReader y los antributos del modelo (usuario y contrasena)
using
DEMO03_LOGIN.Models;//Para
instanciar los atributos de la entidad usuario
using
Microsoft.Extensions.Configuration;//Para acceder al archivo de configuración appsettings.json
using Microsoft.AspNetCore.Http;//Para el manejo de solicitudes y
respuestas HTTP
/// <summary>
/// Constante para Inicializar la Sesión _User
/// </summary>
const string SessionUser = "_User";
public IConfiguration
Configuration { get; }
/// <summary>
/// Interfaz para acceder a los valores del archivo de configuración
/// </summary>
/// <param name="configuration"></param>
public LoginController(IConfiguration configuration)
{
Configuration =
configuration;
}
/// <summary>
/// Action para inicializar la carga de la vista del Login en base a los
atributos de modelo usuario
/// </summary>
/// <returns></returns>
public ActionResult
Login()
{
//ViewBag.ReturnUrl = returnUrl;
return View(new ClsUsuario());
}
/// <summary>
/// Action de tipo POST para para
inicializar el proceso de validación e iniciar sesión en base a los datos del modelo
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
[HttpPost]
//[ValidateAntiForgeryToken]
public ActionResult
Login(ClsUsuario model)
{
//Conexión a la base de datos
string
connectionString = Configuration["ConnectionStrings:DefaultConnection"];
//Estoy usando uso de ADO.Net para
interactuar con la base de datos
using (SqlConnection
connection = new SqlConnection(connectionString))
{
var list_users = new
List<ClsUsuario>();
//@1Inicio: Validar los controladores
if (model.usuario == null || model.usuario.Equals("") ||
model.contrasena == null || model.contrasena.Equals(""))
{
ModelState.AddModelError("", "Ingresar los datos solictiados");
}//@1Final
else
{
connection.Open();//Abrir la
conexión a la base de datos
SqlCommand com = new SqlCommand("GET_SEG_USUARIO", connection);//Referencia al
procedimiento almacenado
com.CommandType =
CommandType.StoredProcedure;//Se
define el tipo de comando a utilizar
//Paso los parámetros de acuerdo
a los datos cargados segun el modelo usario
com.Parameters.AddWithValue("@usuario",
model.usuario);
com.Parameters.AddWithValue("@contrasena", model.contrasena);
SqlDataReader dr = com.ExecuteReader();//Ejecuto el comando a través de un DataReader
//@2Inicio: Recorro los datos y
adiciono en la lista list_users los valores usuario y contrasena
while (dr.Read())
{
ClsUsuario clsUsuario = new ClsUsuario();
clsUsuario.usuario = Convert.ToString(dr["Usuario"]);
clsUsuario.contrasena = Convert.ToString(dr["Contrasena"]);
list_users.Add(clsUsuario);//Adicionar en la lista
}
//@2Final
//@3Inicio: Match entre los
valores ingresados y la lista
if (list_users.Any(p => p.usuario == model.usuario &&
p.contrasena == model.contrasena))
{
HttpContext.Session.SetString(SessionUser,
model.usuario);//Iniciamos
la sesión pasando el valor (nombre del usuario)
return RedirectToAction("Usuario", "Home");//Redireccionar a la vista usario (Lista
de Usuarios)
}
else
{
ModelState.AddModelError("", "Datos ingresado no válido.");//Error
personalizado
}
}
return View(model);
}
}
/// <summary>
/// Action para limpiar y cerrar la sesión de la aplicación
/// </summary>
/// <returns></returns>
[HttpPost]
//[ValidateAntiForgeryToken]
public ActionResult LogOff()
{
HttpContext.Session.Clear();//Limpiar la sesión
return RedirectToAction("Login", "Login");//Redireccionar a la vista login
}
Paso 8: Agregar la vista Login e implementar el cshtml.
<!--@@1 Inicio: Importamos el modelo usuario y
definimos un titulo-->
@model DEMO03_LOGIN.Models.ClsUsuario
@{
var title = "Acceso
al Sistema";
ViewData["Title"] = title;
Layout = null;
}
<!--@@1 Final-->
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>@title</title>
<!--@@2 Inicio: Importamos la
librería js jQuery, el css bootstrap y asimismo posicionamos el
formulario-->
<link href="/lib/bootstrap-4.3.1/dist/css/bootstrap.css" rel="stylesheet" />
<script src="/lib/jquery/dist/jquery.min.js"></script>
<style><
.form-signin {
margin: 0 auto;
max-width: 330px;
padding: 15px;
}
.form-signin h4 {
text-align: center;
}
</style>
<!--@@2 Final-->
</head>
<body>
<div class="container">
<div class="row justify-content-center">
<h3>LOGIN MVC ASP.Net Core 3.1</h3><!--Definimos una cabecera en la página-->
</div>
</div>
<div class="container body-content">
<!--@@3 Inicio: Método de tipo post
para validar o iniciar el acceso a la aplicación-->
@using
(Html.BeginForm("Login", "Login", FormMethod.Post, new { @class = "form-signin", role = "form" }))
{
@Html.AntiForgeryToken()
<h4>@title</h4>
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
@Html.TextBoxFor(m =>
m.usuario, new { @class = "form-control", placeholder = "Usuario" })
@Html.ValidationMessageFor(m
=> m.usuario, "", new { @class = "text-danger" })
<br />
@Html.PasswordFor(m =>
m.contrasena, new { @class = "form-control", placeholder = "Contraseña" })
@Html.ValidationMessageFor(m => m.contrasena, "", new { @class = "text-danger" })
<br />8
<input type="submit" value="Iniciar sesión" class="btn btn-lg btn-primary btn-block" />
}
<!--@@3 Final-->
</div>
</body>
</html>
Paso 9: Modificar la vista _Layout.cshtml.
<!--@@1 Inicio: Importamos el name para la
comnicación http y capturamos el valor de sesión-->
@using Microsoft.AspNetCore.Http
@{
var vUser = Context.Session.GetString("_User");<!--Capturar la sesión en la
variable vUser-->
}
<!--@@1 Final-->
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>@ViewData["Title"]</title><!--Capturamos el titulo
definido en el vista que corresponda (en este caso sera de la vista Index -
LISTAR USUARIO)-->
<!--@@2 Inicio: Importamos la
librería js jQuery y el css bootstrap-->
<link href="/lib/bootstrap-4.3.1/dist/css/bootstrap.css" rel="stylesheet" />
<script src="/lib/jquery/dist/jquery.min.js"></script>
<!--@@2 Final-->
</head>
<body>
<div class="container">
<div class="row justify-content-lg-center">
<div class="row">
<div class="col-12 badge-info">
<h3>LOGIN MVC ASP.Net Core 3.1</h3><!--Cabera de la página-->
</div>
</div>
</div>
<div class="row justify-content-lg-end">
<div class="row">
<!--@@3 Inicio: Pasar el valor de
la variable vUser (sessión) a al parráfo; además invocamos al Action LogOff
para cerrar la sesión-->
<div class="col">
<p>USUARIO: @vUser</p><!--valor de la sesión-->
</div>
<div class="col">
@using (Html.BeginForm("LogOff", "Login", FormMethod.Post, new { id = "logoutForm", @class
= "form-css" }))
{
<a href="javascript:document.getElementById('logoutForm').submit()"><i class="fa fa-fw
fa-power-off"></i> Cerrar Sesión</a>
}
</div>
<!--@@3 Final-->
</div>
</div>
</div>
<div class="container body-content">
@RenderBody()
<hr />
<footer class="row justify-content-center">
<p>
© 2017 - @DateTime.Now.Year
<a href="http://www.hadsonpar.com/" target="_blank">HadsonPar</a> |
My LOGIN
Application MVC ASP.Net Core 3.1
</p>
</footer>
</div>
</body>
</html>
Paso 10: Pantalla del demo desarrollado.
El segundo mensaje de "Contraseña no valida" es un tipo de mensaje personalizado haciendo uso de un función de inyección de dependencia (mayor detalle en el paso4). |
Ingresar los datos correctos y acceder a la aplicación. |
En la vista index se muestra la lista de Usuario y la opción Cerrar Sesión se encuentra en la vista compartido _Layout.cshtml . |
3 Comentarios
Gracias por el excelente artículo en .NET core, si alguien quiere consultarlo en .NET MVC revise aquí
ResponderBorrarLogin and register in ASP.NET MVC
Hola Miguel, gracias por el comentarios y aporte. Saludos.
BorrarHola, gracias por el comentario - déjame revisar el demo y te comento como me va. Saludos.
ResponderBorrar