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!

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

  1. Hello

    YOU NEED QUALITY ORGANIC TRAFFIC THAT BUY FROM YOU ??
    100% Safe Organic Traffic from search engines in any country for alexandreomiranda.com

    CLAIM YOUR 24 HOURS FREE TEST ==> https://www.fiverr.com/share/28Dv4

    Do not forget to read Review to convince you, is already being tested by many people who have trusted it !!

    Regards,
    AxyyKo

  2. Hi!

    You Need Leads, Sales, Conversions, Traffic for alexandreomiranda.com ? Will Findet...

    I WILL SEND 5 MILLION MESSAGES VIA WEBSITE CONTACT FORM

    Don't believe me? Since you're reading this message then you're living proof that contact form advertising works!
    We can send your ad to people via their Website Contact Form.

    IF YOU ARE INTERESTED, Contact us => lisaf2zw526@gmail.com

    Regards,
    Lemann

  3. Howdy

    ** I Will Provide A Simple SEO Strategy for 2019 **

    Looking to boost organic traffic to the pages that really matter?
    Everyone’s SEO goal is the same: To rank for keywords that drive traffic and revenue.

    Boost your Google ranking, get more traffic and more sales for alexandreomiranda.com

    COMPARE PACKAGES => http://bit.ly/Best_SEO_Strategy

  4. Good day!

    You Need Leads, Sales, Conversions, Traffic for alexandreomiranda.com ? Will Findet...

    I WILL SEND 5 MILLION MESSAGES VIA WEBSITE CONTACT FORM

    Don't believe me? Since you're reading this message then you're living proof that contact form advertising works!
    We can send your ad to people via their Website Contact Form.

    IF YOU ARE INTERESTED, Contact us => lisaf2zw526@gmail.com

    Regards,
    Welker

  5. Hello

    Tired of Waiting FOREVER to earn a profit online?

    NEW Web-App Allows You To Legally Hijack Traffic And Authority From Wikipedia AND YouTube To Earn Affiliate Commissions In 24 Hours Or Less - in ANY Niche!

    No Previous Skills Or Experience Required. You can literally be a COMPLETE Newbie and Get RESULTS with just 5 minutes of actual “work”..

    IF YOU ARE INTERESTED, CONTACT US ==> sayedasaliha748@gmail.com

    And Of Course, You Also Have A 30-DAY, YOUR-MONEY Back GUARANTEE
    Once you Join TODAY, You'll Also GET AMAZING BONUSES

    Regards,
    TrafficJacker

  6. Hello

    Tired of Waiting FOREVER to earn a profit online?

    NEW Web-App Allows You To Legally Hijack Traffic And Authority From Wikipedia AND YouTube To Earn Affiliate Commissions In 24 Hours Or Less - in ANY Niche!

    No Previous Skills Or Experience Required. You can literally be a COMPLETE Newbie and Get RESULTS with just 5 minutes of actual “work”..

    IF YOU ARE INTERESTED, CONTACT US HERE==> sayedasaliha748@gmail.com

    Regards,

    TrafficJacker

  7. Howdy

    YOU NEED QUALITY ORGANIC TRAFFIC THAT BUY FROM YOU ??
    100% Safe Organic Traffic from search engines in any country for alexandreomiranda.com

    CLAIM YOUR 24 HOURS FREE TEST ==> http://bit.ly/Quality_Organic_Traffic

    Do not forget to read Review to convince you, is already being tested by many people who have trusted it !!

    Regards,
    AxyyKo

  8. Hello

    NO MATTER WHAT YOU WANT, WE HAVE - so do not hesitate to ask even if it is not listed below !!

    I provide the following mentioned services.

    * ADWORDS $100 coupon
    * BING $100 coupon - now you can use two bing ads coupons per account.
    * AWS Amazon $150 coupons
    * Digital ocean $50 coupon
    * WINDOWS keys lifetime license -version 7,8 and 10
    * OFFICE 365 lifetime access
    * OFFICE 2016 AND 2019 Product Keys
    * NETFLIX Accounts with 6 months validity
    * GMAIL accounts
    * ADWORDS Verified account with $500 credits + VPS
    * BING verified account with $100 credits + VPS
    * AMAZON AWS RDP/VPS Free Tier accounts
    * Google CLOUD accounts with $300 credits.
    * Lynda.com Accounts
    * DOMINOS & PIZZA HUT PIZZAS available(for USA) only
    * EDU emails
    * AZURE Accounts with $200 credits
    * ADSENSE Accounts with domain and Website
    * Quality NICHE Websites/Blogs
    * CPA Accounts Approval of any company
    * PAYPAL verified accounts with NO 21 days hold
    * ANY OTHER SERVICE you are looking for

    If you are interested in the following services, please let me know here: bestservice@post.com

    Thanks

  9. Hi there

    You Need Help to Make Money Online?
    I have Secret 5 Minute 'Copy & Paste' Trick Makes It Super Simple For Anyone To Make Money Online - In The First 24h!

    - Start Today - Your First Profit in 24 Hours!
    - $1000's Per Month with little "work"
    - $20-$80 Each Time you do this
    - Copy & Paste Simple
    - 100% Newbie Friendly
    - No Websites, Domains or Hosting Needed

    Grab Full Access ==> http://bit.ly/Full_Access_Here

    Regards,
    Goldhar

    UNSUBSCRIBE or REPORT SPAM ==> Reply to an Email

  10. Howdy

    I just checked out your website alexandreomiranda.com and wanted to find out if you need help for SEO Link Building ?

    If you aren't using SEO Software then you will know the amount of work load involved in creating accounts, confirming emails and submitting your contents to thousands of websites.

    With THIS SOFTWARE the link submission process will be the easiest task and completely automated, you will be able to build unlimited number of links and increase traffic to your websites which will lead to a higher number of customers and much more sales for you.

    IF YOU ARE INTERESTED, We offer you 7 days free trial
    CONTACT US ==> seosubmitter@mail.com

    Regards,
    Fellows

  11. Hello there

    I just checked out your website alexandreomiranda.com and your site takes longer than 3 seconds to load 🙁

    If your site takes so Long Time To Load you are losing more than half your traffic & 50% of visitors won't return if they have trouble loading a page...

    That's a really expensive mistake to make, specially if you are paying for traffic. I can help you to improve that.

    Please contact me by my email for details: wp_optimiser@mail.com

    Regards,
    Hovell

  12. Why our software is the World's most powerful link building software ?

    Our Software supports UNLIMITED website platforms.
    You can submit your backlinks/content to following main platforms with support built...

    [GET FREE TRIAL] ==> http://www.moneyrobotsubmiter.club

  13. Girl Live Cams: Meet the Most Desirable Adult Models | LiveJasmin
    Find the sweetest, sexiest, hottest, flirtiest, the most versatile cam girls in the world of cybersex! Sign up for 10 free teasers with the best female models!

    CHOOSE THE MODEL ==> http://bit.ly/LiveJasmin_Cams

  14. Bacon & Butter: The Ultimate Ketogenic Diet Cookbook Now!
    Discover 148 amazing ketogenic recipes inside this special edition of our New York Times Bestseller… plus more.

    GET NoW ==>> http://bit.ly/Free_Bacon_Butter

  15. Bom dia xará, tudo bem?
    O link de download não esta mais disponível pelo OneDrive. Se não for incomodo, pode revalidar o link ou enviar por email?
    Desde já agradeço.

  16. Boa Tarde
    O link do código fonte não está funcionando..... como conseguir o código fonte ?

  17. Alexandre muito obrigado pelo seu poste e por partilhar connosco seu conhecimento, adaptei esta lista o meu projecto e funcionou muito bem.
    Quando vais publicar os outros postes tal como diz na publicação que Farias continuidade as próximas publicações.
    Quero trocar a cor da letra na página Admin.

    Obrigado

  18. Muito Bom,
    Eu fiz o curso MVC com Eduardo Pires, realmente muito bom, e esse seu material ajudou bastante !!! Abraços

Leave a Reply

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

This blog is kept spam free by WP-SpamFree.