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!

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

  1. Of course, there will always be people who won't get vaccinated no matter what. About half of America's unvaccinated adult population say they'll never get a vaccine. The key is to convince the other half who aren't vaccinated yet to get it. Fear does seem to be working with them.
    카지노사이트

  2. I always like finding a site that gives you very good ideas because I like learning new stuff. Happy that I found your site because I greatly liked it and I anticipate your following post. A fantastic blog and i’ll come back again for more useful content. https://www.yadong.biz

  3. "You know, we can look back in a time in history where people were told to wear a gold star and they were definitely treated like second-class citizens — so much so that they were put in trains and taken to gas chambers in Nazi Germany, and this is exactly the type of abuse that Nancy Pelosi is talking about," Greene told Brody.
    카지노사이트

  4. “Marjorie is wrong, and her intentional decision to compare the horrors of the Holocaust with wearing masks is appalling," House Minority Leader Kevin McCarthy said in a statement. "The Holocaust is the greatest atrocity committed in history. The fact that this needs to be stated today is deeply troubling."
    카지노사이트

Leave a Reply

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

This blog is kept spam free by WP-SpamFree.