Login Facilitado

Olá Leitor(a), hoje eu vou escrever e mostrar como fazer o sistema de login usando MVC e Entity Framework. Diferentemente das outras partes,  vou utilizar o SELECT normal com o banco de dados em vez de usar LINQ. Veja as ferramentas utilizadas.

Lembro a todos que é bom ler primeiramente as partes anteriores antes de começar a ler este; todo o projeto é uma continuação.


Ferramentas:

Banco de dados SQL Server
Desenvolvimento com a ferramenta Visual Studio 2012
Linguagem utilizada: C#
Plataforma MVC tipo Web

O primeiro passo para a criação do sistema de login é criar a classe na pasta Model chamada Account.cs. Dentro da classe é necessário colocar apenas as propriedades de usuário e senha. Listagem 1.1.

Listagem 1.1 ‚Äď Classe Account

using System;

using System.Collections.Generic;

using System.ComponentModel.DataAnnotations;

using System.Linq;

using System.Web;

 

namespace MVCSAC.Models

{

    public class Account

    {

        [Required]

        [DataType(DataType.Text)]

        [Display(Name="Usuário")]

        public string Usuario { get; set; }

 

        [Required]

        [DataType(DataType.Password)]

        [Display(Name="Senha")]

        public string Senha { get; set; }

    _}

}


        Note que as propriedades são obrigatórias com o comando [Required]. O tipo da propriedade Usuario é o Text e o dado é o password.  Depois existe apenas o get e set em cada um.

O pr√≥ximo passo √© criar a classe Controller chamada AccountController.cs dentro da pasta Controller. ¬†Nela eu vou ter o formul√°rio e as a√ß√Ķes de usu√°rios quando clicar no bot√£o para logar. Funciona da mesma maneira que as outras p√°ginas, tem o m√©todo Index e outros m√©todos.
        O processo de criar a Controller é o mesmo informado nas partes anteriores, ou seja, nos outros artigos publicados. Clicar com o botão direito em cima da pasta e adicionar uma nova classe do tipo Controller. Figura 1.1


Figura 1.1 ‚Äď Adicionando controller.

Dentro dessa Controller existem alguns métodos importantes, como: 

- Index(): com o objetivo de visualizar a primeira p√°gina.
- LogOut(): retira a autenticação do usuário e depois retorná-lo a página home.
- LogOn(Account model, string returnUrl): consulta o usu√°rio e o perfil
- consultaPerfil: verifica qual é o perfil do usuário
- consultaLogOn: verifica se a senha e o usu√°rio s√£o iguais aos gravados no banco de dados

A listagem 1.2 mostra que o contexto foi adicionado no início da classe.
Listagem 1.2 ‚Äď Contexto adicionado

public class AccountController : Controller

    {

        private iSACContext db = new iSACContext();

       ….

    }


      O método LogOut() faz com que a autenticação do usuário seja terminada e a sessão abandonada. Depois disso retorna a página principal. Listagem 1.3.

Listagem 1.3 ‚Äď M√©todo LogOut()

        public_ ActionResult_ LogOut()

_        {

            FormsAuthentication.SignOut();

            Session.Abandon();

 

            return RedirectToAction("Index", "Home");

        _}

Os métodos de consultar perfil e consultar logOn são do tipo privado e retornam uma lista cada um. Um retorna a lista de string e o outro uma lista de int. Aqui consultamos diretamente no banco de dados através do comando select. Listagem 1.4.

Listagem 1.4 ‚Äď Consultas de perfil e logon

private_ List_<string_> consultaPerfil(List_<int_> resposta)

_        {

            StringBuilder str = new StringBuilder();

            str.Append(@"SELECT PerfilUsu FROM Usuarios WHERE CHUsu = @CHUsu");

 

            IDataParameter parameter = new SqlParameter();

            parameter.DbType = DbType.String;

            parameter.ParameterName = "@CHUsu";

            parameter.Value = resposta[0];

 

            var perfil = db.Database.SqlQuery<String>(str.ToString(), parameter).ToList();

            return perfil;

        }

 

        private List<int> consultaLogOn(Account model)

        {

            StringBuilder str = new StringBuilder();

            str.Append(@"SELECT CHUsu FROM Usuarios WHERE EMUsu = @EMUsu AND PWUsu = @PWUsu");

 

            IDataParameter parameter = new SqlParameter();

            parameter.DbType = DbType.String;

            parameter.ParameterName = "@EMUsu";

            parameter.Value = model.Usuario;

 

            IDataParameter parameter1 = new SqlParameter();

            parameter1.DbType = DbType.String;

            _parameter1.ParameterName = "@PWUsu"_;

_            parameter1.Value = model.Senha;

_ 

_            var_ resposta = db.Database.SqlQuery<Int32_>(str.ToString(), parameter, parameter1).ToList();

_            return_ resposta;

        }


¬† ¬† ¬† ¬† ¬† Analistando o primeiro m√©todo, consultaPerfil. Note que ele recebe uma lista de Int como entrada. Logo em seguida ele faz o select com a chave do usu√°rio (CHUsu). O par√Ęmetro √© adicionado e depois o contexto √© utilizado com o comando db.DataBase.SqlQuery. No final do comando existe o ToList() que retorna a lista de perfil.

¬† ¬† ¬† ¬† ¬† Analisando o segundo m√©todo, consultaLogOn. Note que ele recebe apenas a pr√≥pria model e consulta a tabela de usuarios com os par√Ęmetros nome e a senha, informados pelo pr√≥prio usu√°rio. Os par√Ęmetros s√£o adicionados, cada um com seu valor, depois o comando SqlQuery √© utilizado da mesma forma que o primeiro m√©todo. A √ļnica diferen√ßa √© que a lista retorna √© do tipo Int32 em vez de String.

         O método que faz o logOn é o principal dessa classe. Os valores são trafegados do formulário web para que o método autentique o usuário e depois o perfil. Nesse meu exemplo, é necessário verificar qual é o perfil do usuário, administrador ou usuário normal. O perfil está gravado na tabela de Usuários e no campo PerfilUsu dentro do banco de dados (Figura 1.7). A listagem 1.5 mostra o método.

Listagem 1.5 ‚Äď M√©todo de logOn

public_ ActionResult_ LogOn()

_        {

            return View();

        }

 

        [HttpPost]

        public ActionResult LogOn(Account model, string returnUrl)

        _{

_            var_ resposta = consultaLogOn(model);

_            if_ (resposta.Count == 0)

_            {

_                ViewBag.Mensagem = "Usuário ou senha inválida, tente novamente!"_;

_                return_ View();

_            }

_            else_

_            {

_                //consulta perfil_

_                var_ perfil = consultaPerfil(resposta);

_ 

_                if (perfil != null)

                    Session.Add("PerfilUsu", perfil[0]);

 

                FormsAuthentication.SetAuthCookie(model.Usuario, false /* createPersistentCookie */);

 

                Session.Add("Usuario", model.Usuario);

                _Session.Add("ChaveUsuario"_, resposta[0].ToString());

_ 

_ 

_                if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")

                        && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))

                {

                    return Redirect(returnUrl);

                }

                else

                {

                    return RedirectToAction("Index", "Home");

                _}

_            }

_        }

O primeiro método não faz nada e mostra apenas a View da página. O segundo método já começa com comando HttpPost; ele indica que os valores serão postados do formulário. Note que nem todos os métodos possuem essa linha antes do método. 

A primeira linha dentro do m√©todo chama outro m√©todo passando a pr√≥pria model como par√Ęmetro. Caso o retorno for igual a zero, quer dizer que as informa√ß√Ķes passadas pelo usu√°rio n√£o est√£o gravadas no banco de dados, assim, uma mensagem retorna para a tela falando que a senha ou o usu√°rio s√£o inv√°lidos. Caso contr√°rio, ou seja, se o usu√°rio for autenticado, √© necess√°rio verificar o perfil.¬†

Se o perfil for diferente de null então uma sessão é criada e o formulário é autenticado pelo método SetAuthCookie. Autenticado, a url é verificada e retornada usando o Redirect. 

O próximo passo é gerar a View de Login. Clique com o botão direito em cima do método LogOn e escolha a opção Add View... Figura 1.2.


Figura 1.2 ‚Äď Adicionando a View de Login

A figura 1.3 mostra como voc√™ deve escolher as op√ß√Ķes na pr√≥xima tela.¬†


Figura 1.3 ‚Äď Escolhando as op√ß√Ķes para criar a View

O nome você deixa como está, depois marque a opção de Create e a strongly-type view escolha a classe da Model chamada Account. Nos templates Scaffold, escolha o tipo Create e clique no botão Add. 

Dessa forma, a view √© criada com todos os par√Ęmetros e campos para verificar o usu√°rio e senha. ¬†A mudan√ßa feita dentro da View √© o nome do bot√£o e a cria√ß√£o de uma vari√°vel de mensagem. A listagem 1.6 mostra como ficou a view de login.

Listagem 1.6 ‚Äď View de Login

@model MVCSAC.Models.Account

 

@{

    ViewBag.Title = "LogOn";

}

 

<h2>LogOnh2>

 

@using (Html.BeginForm()) {

    _@_Html.ValidationSummary(true_)

_ 

_    <fieldset>_

        <legend>Accountlegend>

 

        <div class="editor-label">

            @Html.LabelFor(model => model.Usuario)

        div>

        <div class="editor-field focus">

            @Html.EditorFor(model => model.Usuario)

            @Html.ValidationMessageFor(model => model.Usuario)

        div>

 

        <div class="editor-label">

            _@_Html.LabelFor(model => model.Senha)

_        div>

        <div class="editor-field">

            _@_Html.EditorFor(model => model.Senha)

_            _@_Html.ValidationMessageFor(model => model.Senha)

_        div>

 

        <p>

            <input type="submit" value="LogOn" />

            <br_ />_

_             <font_ color="red">_@_ViewBag.Mensagemfont>_

_        p>

    fieldset>

}

 

@section Scripts {

    @Scripts.Render("~/bundles/jqueryval")

_}_

_ 

<script_ language="javascript">_

_    //colocando o foco no botao_

_    document.getElementById("_@_Html.IdFor(model => model.Usuario)"_).focus();

script>_


No final da view, adicionei um javascript para posicionar o cursor do mouse no primeiro campo chamado usuário. Mudei o nome do botão de sumit e coloquei uma ViewBag de mensagem. 

Outra dica importante, é fazer com que as classes que não podem ser acessadas sem que o usuário logue no sistema, acrescente no topo da classe a seguinte palavra: Authorize. A listagem 1.7 mostra isso.

Listagem 1.7 ‚Äď Colocando autoriza√ß√£o.

_

_[Authorize_]

_    public_ class_ RespostaController_ : Controller_

    {}


Para finalizar a tela todo o processo de login, acesse o arquivo de configuração Web.config, acrescente o tipo de autenticação e a página. Listagem 1.8.

Listagem 1.8 ‚Äď Arquivo de configura√ß√£o.

    <authentication mode=_"Forms_">_

      <forms loginUrl=_"~/Account/LogOn_" timeout=_"2880_" />_

    authentication>


Prontinho, basta agora executar a p√°gina e tentar logar no banco de dados. Lembro que o banco de dados est√° com a senha aberta, assim n√£o estou utilizando criptografia neste primeiro momento. √Č bom que utilize sempre criptografia de dados para autentica√ß√£o de informa√ß√Ķes. ¬†Figura 1.4


Figura 1.4 ‚Äď Informa√ß√Ķes no banco de dados.

Para melhorar um pouco a primeira tela, coloquei um link para login na primeira p√°gina. Se o perfil for de administrador, o sistema habilita algumas p√°ginas, sen√£o for o sistema n√£o habilita. A figura 1.5 mostra a tela de login.


Figura 1.5 ‚Äď Tela de login

Para facilitar, segue todo o c√≥digo da classe de AccountController.cs. Qualquer d√ļvida, pode entrar em contato pelo site www.mauriciojunior.org. Listagem 1.9.

Listagem 1.9 ‚Äď Classe AccountController.cs

using MVCSAC.DAL;

using MVCSAC.Models;

using System;

using System.Collections.Generic;

using System.Data;

using System.Data.SqlClient;

using System.Linq;

using System.Text;

using System.Web;

using System.Web.Mvc;

using System.Web.Security;

 

namespace MVCSAC.Controllers

{

    public class AccountController : Controller

    {

        private iSACContext db = new iSACContext();

 

        //

        // GET: /Account/

 

        public ActionResult Index()

        {

            return View();

        }

 

     

        //GET: /Account/LogOut

        public ActionResult LogOut()

        {

            FormsAuthentication.SignOut();

            Session.Abandon();

 

            return RedirectToAction("Index", "Home");

        }

 

 

 

        // GET: /Account/LogOn

        public ActionResult LogOn()

        {

            return View();

        }

 

        [HttpPost]

        public ActionResult LogOn(Account model, string returnUrl)

        _{

_            var_ resposta = consultaLogOn(model);

_            if_ (resposta.Count == 0)

_            {

_                ViewBag.Mensagem = "Usuário ou senha inválida, tente novamente!"_;

_                return_ View();

_            }

_            else_

_            {

_                //consulta perfil_

_                var_ perfil = consultaPerfil(resposta);

_ 

_                if (perfil != null)

                    Session.Add("PerfilUsu", perfil[0]);

 

                FormsAuthentication.SetAuthCookie(model.Usuario, false /* createPersistentCookie */);

 

                Session.Add("Usuario", model.Usuario);

                _Session.Add("ChaveUsuario"_, resposta[0].ToString());

_ 

_ 

_                if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")

                        && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))

                {

                    return Redirect(returnUrl);

                }

                else

                {

                    return RedirectToAction("Index", "Home");

                }

            }

        }

 

        private List<string> consultaPerfil(List<int> resposta)

        {

            StringBuilder str = new StringBuilder();

            str.Append(@"SELECT PerfilUsu FROM Usuarios WHERE CHUsu = @CHUsu");

 

            IDataParameter parameter = new SqlParameter();

            parameter.DbType = DbType.String;

            parameter.ParameterName = "@CHUsu";

            parameter.Value = resposta[0];

 

            var perfil = db.Database.SqlQuery<String>(str.ToString(), parameter).ToList();

            return perfil;

        }

 

        private List<int> consultaLogOn(Account model)

        {

            StringBuilder str = new StringBuilder();

            str.Append(@"SELECT CHUsu FROM Usuarios WHERE EMUsu = @EMUsu AND PWUsu = @PWUsu");

 

            IDataParameter parameter = new SqlParameter();

            parameter.DbType = DbType.String;

            parameter.ParameterName = "@EMUsu";

            parameter.Value = model.Usuario;

 

            IDataParameter parameter1 = new SqlParameter();

            parameter1.DbType = DbType.String;

            _parameter1.ParameterName = "@PWUsu"_;

_            parameter1.Value = model.Senha;

_ 

_            var resposta = db.Database.SqlQuery<Int32>(str.ToString(), parameter, parameter1).ToList();

            return resposta;

        }

 

 

        //

        // GET: /Account/Create

 

        public ActionResult Create()

        {

            return View();

        }

 

        //

        // POST: /Account/Create

 

        [HttpPost]

        public ActionResult Create(FormCollection collection)

        {

            try

            {

                // TODO: Add insert logic here

 

                return RedirectToAction("Index");

            }

            catch

            {

                return View();

            _}

_        }

_ 

_    }

_}