Customizando layout de login no ASP.NET Identity

O ASP.NET Identity é perfeito para gerenciamento de usuários e pode ser customizado facilmente. O MVP Eduardo Pires tem bastante material sobre o Identity que estão me ajudando bastante com os estudos em ASP.NET. Por sinal, tive a oportunidade de fazer o curso online de ASP.NET MVC 5 com ele e recomendo a todos. Ótima didática e conteúdo muito bom.

De fato, é muito simples implementar o gerenciamento de usuários. Por padrão o Identity será configurado se você não remover o recurso de autenticação durante a criação do projeto.

O meu intuito com esse post, é criar um projeto de autenticação customizando o comportamento da aplicação pensando numa aplicação corporativa. Para isso, irei fazer algumas customizações no template de login e também na área restrita contendo painel de admin, registro de usuários e alguns CRUD's básicos.

Nesse primeiro projeto, irei utilizar apenas o Bootstrap para customização das telas de apresentação e o projeto MVC não será desacoplado, conforme sugere o DDD. A idéia é evoluir com o projeto.

Vamos lá, mão na massa...

1 - Crie um projeto ASP.NET Web Application, MVC e autenticação "Individual User Account"

2 - Após a criação do projeto, ele funcionará com o template padrão e terá rotinas de registro e login de usuário funcionais.

Capturar1

O objetivo é alterar o comportamento obrigando o usuário a efetuar login ao acessar a aplicação. Para isso, aplique o atributo AuthorizeAttribute na HomeController.cs;

[Authorize]
public class HomeController : Controller
{ ... }

3 - O próximo passo é customizar o layout da página de login. Para isso crie uma Partial View na pasta \View\Shared do projeto chamada _LoginStart.cshtml e crie o conteúdo conforme o código abaixo;
_LoginStart.cshtml

 
 <!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
</head>
<body class="login-page">
    <div class="container body-content">
        @RenderBody()
    </div>
    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    @RenderSection("scripts", required: false)
</body>
</html>

4 - Em seguida, vamos substituir o layout padrão que é carregado através da _ViewStart somente na view de Login e customizar adicionando algumas tags e decorando com algumas classes CSS/Bootstrap.
Login.cshtml

@{
    Layout = "~/Views/Shared/_LoginStart.cshtml";
}
 
@using IdentityLoginCustomizado.Models
@model LoginViewModel
<div class="modal show" tabindex="-1" role="dialog" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h2 class="text-center">Bem vindo!</h2>
                <h4 class="text-center">Por favor, digite o seu usuário e senha.</h4>
            </div>
            <div class="modal-body">
                <section id="loginForm">
                    @using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form col-md-12 center-block", role = "form" }))
                    {
                        @Html.AntiForgeryToken()
                        @Html.ValidationSummary(true, "", new { @class = "alert alert-danger" })
                        <div class="form-group">
                            @Html.TextBoxFor(m => m.Email, new { @class = "form-control input-lg", @placeholder = "Username" })
                            @Html.ValidationMessageFor(m => m.Email, "", new { @class = "text-danger" })
                        </div>
                        <div class="form-group">
                            @Html.PasswordFor(m => m.Password, new { @class = "form-control  input-lg", @placeholder = "Senha" })
                            @Html.ValidationMessageFor(m => m.Password, "", new { @class = "text-danger" })
                        </div>
                        <div class="form-group">
                            <div>
                                <div class="checkbox">
                                    @Html.CheckBoxFor(m => m.RememberMe)
                                    @Html.LabelFor(m => m.RememberMe)
                                </div>
                            </div>
                        </div>
                        <div class="form-group">
                            <div>
                                <input type="submit" value="Log in" class="btn btn-primary btn-lg btn-block" />
                            </div>
                        </div>
                        <p>
                            <span><p class="pull-right">@Html.ActionLink("Registrar uma nova conta!", "Register")</p></span>
                            <span><p>@Html.ActionLink("Esqueceu sua senha?", "ForgotPassword")</p></span>
                        </p>
                    }
                </section>
            </div>
        </div>
    </div>
</div>
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

5 - Vamos agora customizar o painel de Administração utilizando como base o template Dashboard que está disponível na página oficial do Bootstrap - Examples Bootstrap

Crie uma nova Partial View na pasta \View\Shared chamada _LayoutAdmin.cshtml. Esta partial será o layout padrão
_LayoutAdmin.cshtml

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title - My ASP.NET Application</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
 
</head>
<body>
    <nav class="navbar navbar-inverse navbar-fixed-top">
        <div class="container-fluid">
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                @Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
            </div>
            <div class="navbar-collapse collapse">
                @Html.Partial("_LoginPartial")
            </div>
        </div>
    </nav>
    <div class="container-fluid body-content">
        <div class="row">
            <div class="col-sm-3 col-md-2 sidebar">
                <ul class="nav nav-sidebar">
                    <li>@Html.ActionLink("Home", "Index", "Home")</li>
                    <li>@Html.ActionLink("About", "About", "Home")</li>
                    <li>@Html.ActionLink("Contact", "Contact", "Home")</li>
                </ul>
            </div>
            <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
                @RenderBody()
            </div>
        </div>
    </div>
 
    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    @RenderSection("scripts", required: false)
</body>
</html>

6 - Crie um arquivo dashboard.css e adicione na pasta \Content\
dashboard.css

/*
 * Base structure
 */
 
/* Move down content because we have a fixed navbar that is 50px tall */
body {
  padding-top: 50px;
}
 
 
/*
 * Global add-ons
 */
 
.sub-header {
  padding-bottom: 10px;
  border-bottom: 1px solid #eee;
}
 
/*
 * Top navigation
 * Hide default border to remove 1px line.
 */
.navbar-fixed-top {
  border: 0;
}
 
/*
 * Sidebar
 */
 
/* Hide for mobile, show later */
.sidebar {
  display: none;
}
@media (min-width: 768px) {
  .sidebar {
    position: fixed;
    top: 50px;
    bottom: 0;
    left: 0;
    z-index: 1000;
    display: block;
    padding: 20px;
    overflow-x: hidden;
    overflow-y: auto; /* Scrollable contents if viewport is shorter than content. */
    background-color: #428bca;
    border-right: 1px solid #eee;
  }
}
 
/* Sidebar navigation */
.nav-sidebar {
  margin-right: -21px; /* 20px padding + 1px border */
  margin-bottom: 20px;
  margin-left: -20px;
}
 
.nav-sidebar li a:hover,
    .nav-sidebar li a:focus {
        outline: none;
        background-color: #3671a4 !important;
}
 
.nav-sidebar &gt; li &gt; a {
  color: #fff;
  padding-right: 20px;
  padding-left: 20px;
}
.nav-sidebar &gt; .active &gt; a,
.nav-sidebar &gt; .active &gt; a:hover,
.nav-sidebar &gt; .active &gt; a:focus {
  color: #fff;
  background-color: #428bca;
}
 
 
/*
 * Main content
 */
 
.main {
  padding: 20px;
}
@media (min-width: 768px) {
  .main {
    padding-right: 40px;
    padding-left: 40px;
  }
}
.main .page-header {
  margin-top: 0;
}
 
 
/*
 * Placeholder dashboard ideas
 */
 
.placeholders {
  margin-bottom: 30px;
  text-align: center;
}
.placeholders h4 {
  margin-bottom: 0;
}
.placeholder {
  margin-bottom: 20px;
}
.placeholder img {
  display: inline-block;
  border-radius: 50%;
}

7 - Configurar o BundleConfig.cs, adicionando o arquivo dashboard.css

public class BundleConfig
{
    // For more information on bundling, visit http://go.microsoft.com/fwlink/?LinkId=301862
    public static void RegisterBundles(BundleCollection bundles)
    {
        bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                    "~/Scripts/jquery-{version}.js"));
 
        bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
                    "~/Scripts/jquery.validate*"));
 
        // Use the development version of Modernizr to develop with and learn from. Then, when you're
        // ready for production, use the build tool at http://modernizr.com to pick only the tests you need.
        bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
                    "~/Scripts/modernizr-*"));
 
        bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
                  "~/Scripts/bootstrap.js",
                  "~/Scripts/respond.js"));
 
        bundles.Add(new StyleBundle("~/Content/css").Include(
                  "~/Content/bootstrap.css",
                  "~/Content/dashboard.css", //added
                  "~/Content/site.css"));
    }
}

8 - Altere o layout padrão na _ViewStart.cshtml

@{
    //Layout = "~/Views/Shared/_Layout.cshtml"; //removendo o layout padrão
    Layout = "~/Views/Shared/_LayoutAdmin.cshtml";
}

9 - Pra finalizar, vamos alterar o layout da página de registro de usuários, Register.cshtml e da página de recuperação de senha, ForgotPassword.cshtml.

Register.cshtml

@model IdentityLoginCustomizado.Models.RegisterViewModel
@{
    Layout = "~/Views/Shared/_LoginStart.cshtml";
    ViewBag.Title = "Registrar nova conta";
}
<div class="modal show" tabindex="-1" role="dialog" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h2 class="text-center">@ViewBag.Title</h2>
                <h4 class="text-center">Por favor, preencha os dados.</h4>
            </div>
            <div class="modal-body">
 
                @using (Html.BeginForm("Register", "Account", FormMethod.Post, new { @class = "form col-md-12 center-block", role = "form" }))
                {
                    @Html.AntiForgeryToken()
                    @Html.ValidationSummary("", new { @class = "text-danger" })
                    <div class="form-group">
                        @Html.TextBoxFor(m => m.Email, new { @class = "form-control input-lg", @placeholder = "E-mail" })
                    </div>
                    <div class="form-group">
                        @Html.PasswordFor(m => m.Password, new { @class = "form-control input-lg", @placeholder = "Senha" })
                    </div>
                    <div class="form-group">
                        @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control input-lg", @placeholder = "Confirmação da senha" })
                    </div>
                    <div class="form-group">
                        <div>
                            <input type="submit" class="btn btn-primary btn-lg btn-block" value="Registrar" />
                        </div>
                    </div>
                    <span><p>@Html.ActionLink("Agora não, obrigado!", "Login")</p></span>
                }
            </div>
        </div>
    </div>
</div>
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

ForgotPassword.cshtml

@model IdentityLoginCustomizado.Models.ForgotPasswordViewModel
@{
    Layout = "~/Views/Shared/_LoginStart.cshtml";
    ViewBag.Title = "Esqueceu sua senha?";
}
<div class="modal show" tabindex="-1" role="dialog" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h2 class="text-center">@ViewBag.Title</h2>
                <h4 class="text-center">Por favor, forneça o seu e-mail.</h4>
            </div>
            <div class="modal-body">
                @using (Html.BeginForm("ForgotPassword", "Account", FormMethod.Post, new { @class = "form col-md-12 center-block", role = "form" }))
                {
                    @Html.AntiForgeryToken()
                    @Html.ValidationSummary("", new { @class = "text-danger" })
                    <div class="form-group">
                        @Html.TextBoxFor(m => m.Email, new { @class = "form-control input-lg", @placeholder = "E-mail" })
                    </div>
                    <div class="form-group">
                        <div>
                            <input type="submit" class="btn btn-primary btn-lg btn-block" value="Enviar" />
                        </div>
                    </div>
                    <span><p>@Html.ActionLink("Retornar ao Login", "Login")</p></span>
                }
            </div>
        </div>
    </div>
</div>
@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

Finalizamos a aplicação. Após executá-la, registrar-se e efetuar login, note que o layout estará com aspecto de uma aplicação corporativa, com painel de navegação e exigindo sempre a autenticação.

Tela inicial:
login

Painel após login:
painel

No próximo post irei criar algumas melhorias, talvez com um painel de Admin mais profissional, tem alguns bem legais disponíveis na web, e também com a implementação de recuperação de senha por e-mail e cadastro gerenciado de usuários. Afinal, ninguém quer usuários se registrando aleatoriamente numa aplicação segura.

O código desse projeto está disponível aqui - Download projeto

Update!!! - Código do projeto no Github - Identity Login Customizado Github
É isso aí, até a próxima!

53 thoughts on “Customizando layout de login no ASP.NET Identity

  1. After looking into a few of the blog posts on your web page, I really like your way of blogging. I saved as a favorite it to my bookmark webpage list and will be checking back soon. Please visit my website too and let me know how you feel.https://www.btlcasino.com

Leave a Reply

Your email address will not be published. Required fields are marked *

This blog is kept spam free by WP-SpamFree.