Para que estejam ligadas as informações entre a aplicação e as informações salvas, será criado dentro do SGBD Microsoft SQL Server Management Studio um novo banco de dados, com o nome de ExemploLogin.
Neste banco de dados será criada uma tabela com o nome de Usuario, que vai conter os campos código, login e senha para uma futura autenticação do sistema. Veja o conjunto de instruções descrito na Listagem 1 para o SGBD e executar.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id =
OBJECT_ID(N'[dbo].[Usuario]') AND type in (N'U'))
BEGIN
CREATE TABLE [dbo].[Usuario](
[fun_codigo] [int] IDENTITY(1,1) NOT NULL,
[fun_login] [nvarchar](50) NULL,
[fun_senha] [nvarchar](50) NULL,
CONSTRAINT [PK_Usuario] PRIMARY KEY CLUSTERED
(
[fun_codigo] ASC
)WITH (PAD_INDEX = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
Iniciando o Projeto
Agora iremos dar o início para o projeto, tendo o ambiente de desenvolvimento Microsoft Visual Studio 2010. Com ele aberto, vá ao menu superior File → New → Project e depois selecione a opção do projeto Windows Forms Control Library. Atribua o nome da nova biblioteca de ProjetoServiceDesk e selecione o local onde a aplicação será salva. Depois é só clicar em OK.
É preciso agora criar três pastas: uma com o nome de Controller para controlar as ações, outra com o nome de DAO para a comunicação com o banco de dados e, por fim, uma com o nome de Model para que sejam tratadas e modeladas as informações.
Dentro da pasta Controller será criado um arquivo de classe com o nome FuncionarioController.cs. Já na pasta DAO serão criados dois arquivos de classe com os nomes Banco.cs e FuncionarioBD.cs. Dentro da pasta Model será criado um arquivo de classe com o nome de Funcionario.cs.
Após, será criado um novo projeto (mesmo o projeto anterior estando aberto no Solution Explorer) e os passos serão os mesmos, só que ao invés de ser uma nova biblioteca, será um ASP.NET Web Application com o nome WebExemploLogin.
Por padrão, em algumas versões, o ambiente cria automaticamente algumas pastas e arquivos, então será necessário apagar alguns deles e deixar apenas as pastas Properties (Propriedades), References (Referências de bibliotecas) e Web.config.
Agora serão criados outros três arquivos: Default.aspx (que será a página inicial da aplicação web), Principal.aspx (onde será a página de acesso caso o usuário efetuou o login) e Logout.aspx para que o usuário saia da aplicação.
A estrutura do projeto e dos arquivos criados ficará de acordo com a Figura 1.
Implementando o Projeto servicedesk
Dentro da classe Banco.cs [DAO] será implementado o código descrito na Listagem 2.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.SqlClient;
using System.Data;
namespace ProjetoServiceDesk.DAO
{
internal class Banco
{
private string _strConexao;
private SqlCommand _comandoSQL;
protected SqlCommand ComandoSQL
{
get { return _comandoSQL; }
set { _comandoSQL = value; }
}
protected Banco()
{
_strConexao = @"Data Source=USUARIO-PC;Initial
Catalog=ExemploLogin;Integrated Security=True;User
Id="";Password="";";
_conn = new SqlConnection(_strConexao);
_comandoSQL = new SqlCommand();
_comandoSQL.Connection = _conn;
}
protected Banco(string stringConexao)
{
_strConexao = stringConexao;
_conn = new SqlConnection(_strConexao);
_comandoSQL = new SqlCommand();
_comandoSQL.Connection = _conn;
}
protected bool AbreConexao(bool transacao)
{
try
{
_conn.Open();
if (transacao)
{
_transacao = _conn.BeginTransaction();
_comandoSQL.Transaction = _transacao;
}
return true;
}
catch
{
return false;
}
}
protected bool FechaConexao()
{
try
{
if (_conn.State == ConnectionState.Open)
_conn.Close();
return true;
}
catch
{
return false;
}
}
protected void FinalizaTransacao(bool commit)
{
if (commit)
_transacao.Commit();
else
_transacao.Rollback();
FechaConexao();
}
protected int ExecutaComando(bool transacao)
{
if (_comandoSQL.CommandText.Trim() == string.Empty)
throw new Exception("Não há instrução SQL a ser executada.");
int retorno;
AbreConexao(transacao);
try
{
retorno = _comandoSQL.ExecuteNonQuery();
}
catch(Exception ex)
{
retorno = -1;
throw new Exception("Erro ao executar o comando SQL:", ex);
}
finally
{
if (!transacao)
FechaConexao();
}
return retorno;
}
protected int ExecutaComando(bool transacao, out int ultimoCodigo)
{
if (_comandoSQL.CommandText.Trim() == string.Empty)
throw new Exception("Não há instrução SQL a ser executada.");
int retorno;
ultimoCodigo = 0;
AbreConexao(transacao);
try
{
ultimoCodigo = Convert.ToInt32(_comandoSQL.ExecuteScalar());
retorno = 1;
}
catch(Exception ex)
{
retorno = -1;
throw new Exception("Erro ao executar o comando SQL: ", ex);
}
finally
{
if (!transacao)
FechaConexao();
}
return retorno;
}
protected DataTable ExecutaSelect()
{
if (_comandoSQL.CommandText.Trim() == string.Empty)
throw new Exception("Não há instrução SQL a ser executada.");
AbreConexao(false);
DataTable dt = new DataTable();
try
{
dt.Load(_comandoSQL.ExecuteReader());
}
catch(Exception ex)
{
dt = null;
throw new Exception("Erro ao executar o comando SQL: ", ex);
}
finally
{
FechaConexao();
}
return dt;
}
protected double ExecutaScalar()
{
if (_comandoSQL.CommandText.Trim() == string.Empty)
throw new Exception("Não há instrução SQL a ser executada.");
AbreConexao(false);
double retorno;
try
{
retorno = Convert.ToDouble(_comandoSQL.ExecuteScalar());
}
catch(Exception ex)
{
retorno = -1;
throw new Exception("Erro ao executar o comando SQL: ", ex);
}
finally
{
FechaConexao();
}
return retorno;
}
}
}
Nessa classe existe o construtor Banco() que é responsável por conectar com o banco de dados através de uma string de conexão. Nela temos as funções AbreConexao (para abrir conexão com o banco de dados) e FechaConexao (para fechar a conexão). O método FinalizaTransacao() é responsável por finalizar alguma transação atual e o método ExecutaComando() é responsável por executar o comando SQL e retornar se houve ou não êxito na comunicação com o banco de dados. Já os métodos ExecutaSelect() e ExecutaScalar() são responsáveis por executares os comandos SQL retornando valores.
Dentro da classe Funcionario.cs [Model] será implementado o código descrito na Listagem 3.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ProjetoServiceDesk.Model
{
public class Funcionario
{
public Funcionario() { _codigo = 0; }
#region Propriedades do Funcionario
private int _codigo;
public int Codigo
{
get
{
return _codigo;
}
set
{
_codigo = value;
}
}
private string _login;
public string Login
{
get { return _login; }
set { _login = value; }
}
private string _senha;
public string Senha
{
get { return _senha; }
set { _senha = value; }
}
#endregion
}
}
São criadas propriedades para o código, login e senha, a fim de que os dados sejam tratados de acordo com o tipo de cada campo.
Agora dentro da classe FuncionarioBD.cs [Banco] será implementado o código descrito na Listagem 4.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ProjetoServiceDesk.Model;
using System.Data;
namespace ProjetoServiceDesk.DAO
{
internal class FuncionarioBD : Banco
{
internal FuncionarioBD() { }
internal Funcionario Autenticar(string login, string senha)
{
ComandoSQL.Parameters.Clear();
ComandoSQL.CommandText = @"select * from USUARIO
where fun_login = @login and fun_senha = @senha";
ComandoSQL.Parameters.AddWithValue("@login", login);
ComandoSQL.Parameters.AddWithValue("@senha", senha);
DataTable dt = ExecutaSelect();
if (dt != null && dt.Rows.Count > 0)
{
Funcionario f = new Funcionario();
f.Codigo = Convert.ToInt32(dt.Rows[0]["fun_codigo"]);
f.Login = dt.Rows[0]["fun_login"].ToString();
f.Senha = dt.Rows[0]["fun_senha"].ToString();
return f;
}
else
return null;
}
}
}
É criada uma função chamada Autenticar passando por parâmetros o login e senha, onde, através de comando SQL, verifica se ambos estão iguais. O DataTable retorna todas as informações como Código, Login e Senha e, se não tiver algo, retorna nulo.
Finalmente, dentro da classe FuncionarioController.cs [Controller] será implementado o código descrito na Listagem 5.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ProjetoServiceDesk.Model;
using ProjetoServiceDesk.DAO;
namespace ProjetoServiceDesk.Controller
{
public class FuncionarioController
{
FuncionarioBD bd = new FuncionarioBD();
public Funcionario Autenticar(string login, string senha)
{
if (login != "" && senha.Trim().Length > 0)
return new FuncionarioBD().Autenticar(login, senha);
else
return null;
}
public FuncionarioController() { }
}
}
É declarada uma instância referente à classe FuncionarioBD. Além disso, é criada uma função Autenticar, passando por parâmetros o login e a senha. Se o login for diferente de vazio e se a senha tiver tamanho maior que 0, então é executado o método Autenticar da classe FuncionarioBD, senão é retornado nulo.
Implementando a Aplicação Web
Partindo do princípio de que a ideia central desse artigo é criar um sistema de login, até agora meio caminho já foi andado, faltando agora implementar a parte visual e alguns detalhes que visam tornar operacional a aplicação.
Para adicionar aquele projeto que se refere a uma biblioteca DLL para esse projeto web, basta clicar com o botão direito em References, clicar em “Add Reference...” e localizar a pasta onde foi criado o arquivo DLL (geralmente localizado na aba Projects) e adicionar.
No arquivo Default.aspx, na parte [Source] adicione o código descrito na Listagem 6 para agilizar o processo.
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs"
Inherits="WebExemploLogin.Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="Label1" runat="server" Text="Login: "></asp:Label>
<asp:TextBox ID="txtLogin" runat="server"></asp:TextBox>
<br />
<br />
<asp:Label ID="Label2" runat="server" Text="Senha: "></asp:Label>
<asp:TextBox ID="txtSenha" runat="server"></asp:TextBox>
<br />
<br />
<asp:Button ID="btnEntrar" runat="server" onclick="btnEntrar_Click"
Text="Entrar" />
<br />
<br />
<asp:Label ID="lblMensagem" runat="server" Text="-"></asp:Label>
<br />
<br />
</div>
</form>
</body>
</html>
Nesta página existem duas caixas de texto: uma referente a entrada do login e outra para a entrada da senha. Além disso, existe um botão para que o usuário entre no sistema para autenticação e um label para que avise na tela se o usuário informou o login e/ou a senha inválida.
Agora, indo na parte [Design], basta apertar F7 ou clicar com o botão direito e ir para a opção View Code, para que os códigos descritos na Listagem 7 possam ser inseridos.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using ProjetoServiceDesk.Controller;
using ProjetoServiceDesk.Model;
namespace WebExemploLogin
{
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (Request.Cookies["Acesso"] != null && !IsPostBack)
{
txtLogin.Text = Request.Cookies["Acesso"]["funcionario"];
txtSenha.Attributes.Add("value", Request.Cookies["Acesso"]["senha"]);
}
if (Request.QueryString["msg"] != null)
lblMensagem.Text = Request.QueryString["msg"];
txtLogin.Focus();
}
protected void btnEntrar_Click(object sender, EventArgs e)
{
lblMensagem.Text = string.Empty;
if (txtLogin.Text.Trim() != "")
{
Funcionario user = new FuncionarioController()
.Autenticar(txtLogin.Text, txtSenha.Text);
if (user != null)
{
Session["autenticado"] = "OK";
Session["codigoFuncionario"] = user.Codigo;
Session["nomeFuncionario"] = user.Login;
Session["senhaFuncionario"] = user.Senha;
Server.Transfer("Principal.aspx");
}
else
lblMensagem.Text = "Usuário e/ou senha inválida.";
}
}
}
}
Dentro do Page_Load são criados dois cookies para que recebam as informações do login e da senha do usuário (funcionário). O label receberá uma mensagem caso haja algum erro na autenticação e o txtLogin receberá o foco.
No botão Entrar, o label recebe vazio, e se o login informado estiver diferente de vazio, é executado o método Autenticar da classe FuncionarioController(), passando por parâmetros o login e senha referentes a classe Funcionario do tipo user. Se o resultado for diferente de nulo, ou seja, se existir, então são criadas as sessões para armazenar os dados e depois é transferido para a página Principal.aspx; senão, aparece uma mensagem de erro.
No arquivo Principal.aspx, que será a página onde o usuário fez o login e com sucesso possa acessar a essa página, na parte [Source] será adicionado o código descrito na Listagem 8.
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Principal.aspx.cs"
Inherits="WebExemploLogin.Principal" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="lblUsuario" runat="server" Text="-"></asp:Label>
<br />
<br />
<asp:Button ID="btnSair" runat="server" onclick="btnSair_Click" Text="Sair" />
</div>
</form>
</body>
</html>
Agora, na parte do View Code dessa página será introduzida o código descrito na Listagem 9.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebExemploLogin
{
public partial class Principal : System.Web.UI.Page
{
public static void VerificaLogin()
{
if (HttpContext.Current.Session["autenticado"] == null ||
HttpContext.Current.Session["autenticado"].ToString() != "OK")
{
HttpContext.Current.Session.Abandon();
HttpContext.Current.Response.Redirect("Default.aspx?msg=Por favor,
autentique-se");
}
}
protected void Page_Load(object sender, EventArgs e)
{
VerificaLogin();
if (Session["autenticado"] != null && Session["autenticado"]
.ToString() == "OK")
{
lblUsuario.Text = string.Format("Código: {0}<br/>Nome:
{1}<br/>Senha: {2}",
Session["codigoFuncionario"].ToString(),
Session["nomeFuncionario"].ToString(),
Session["senhaFuncionario"].ToString());
}
}
protected void btnSair_Click(object sender, EventArgs e)
{
Response.Redirect("Logout.aspx");
}
}
}
A função VerificaLogin() é responsável por identificar se houve a autenticação com êxito, e se for diferente de OK, então significa que não houve e a sessão é destruída, retornando uma mensagem para que o usuário autentique-se.
No Page_Load é chamada a função VerificaLogin() e o label criado anteriormente recebe o Código, o Login e a Senha do usuário autenticado.
No botão Sair que é responsável por sair do sistema encerrando a sessão, é chamado a página de Logout.aspx.
E finalmente dentro do View Code do arquivo Logout.aspx, será implementado os códigos descritos na Listagem 9.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace ProjetoServiceDeskWeb
{
public partial class Logout : System.Web.UI.Page
{
public static void VerificaLogin()
{
if (HttpContext.Current.Session["autenticado"] == null ||
HttpContext.Current.Session["autenticado"].ToString() != "OK")
{
HttpContext.Current.Session.Abandon();
HttpContext.Current.Response
.Redirect("Default.aspx?msg=Por favor, autentique-se");
}
}
protected void Page_Load(object sender, EventArgs e)
{
VerificaLogin();
if (Request.Cookies["Acesso"] != null)
Response.Cookies["Acesso"].Expires = DateTime.Now.AddDays(-1);
Session.RemoveAll();
Session.Abandon();
Response.Redirect("Default.aspx");
}
}
}
É desenvolvida a mesma função VerificaLogin() e chamada no Page_Load. Se o cookie criado anteriormente com o nome de Acesso for diferente de nulo, então ele é expirado, e a sessão é removida e é direcionado para a página Default.aspx.
Para finalizar o sistema, basta salvar todos os projetos e executar a aplicação com um Ctrl + F5 ou clicando com o botão direito em cima do arquivo Default.aspx e depois clicar em View in Browser.
Se executado no navegador for o Mozilla Firefox, vai aparecer o mesmo que na Figura 2.
Para fazer testes, basta adicionar algumas informações na tabela Usuario, no SQL Server, como login e senha. Retorne a aplicação e clique no botão Entrar.
Logo, se os dados emitidos forem incorretos, vai aparecer uma mensagem de usuário ou senha inválida, senão a página vai redirecionar para a Principal.aspx, onde vai conter todas as informações cadastradas e também um botão para Sair que encerrará a sessão e retornará para a página Default.aspx.