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.
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 > li > a { color: #fff; padding-right: 20px; padding-left: 20px; } .nav-sidebar > .active > a, .nav-sidebar > .active > a:hover, .nav-sidebar > .active > 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.
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!
Hello
YOU NEED HELP TO BUILD SEO BACKLINKS FOR: alexandreomiranda.com ?
WE SELL HIGH-QUALITY DOFOLLOW POWERFUL BACKLINKS WITH HIGH DOMAIN AUTHORITY, PA, TF, CF...
► Rank Higher In Google (google backlinks, DoFollow backlinks, SEO DoFollow backlinks)
► Rank Higher Video in Youtube & Google (youtube backlinks, video backlinks, video embedded)
► Rank Higher GMB In Google Maps (Google maps backlinks, GMB maps backlinks, GMB embedded, NAP embedded)
► Rank Higher Images In Google (google images backlinks, google backlinks)
You Can Increase Traffic to your websites which will lead to a higher number of customers and much more sales for you.
CLAIM YOUR FREE TEST HERE => http://augustjrag19642.bloggerbags.com/11147276/get-quality-powerful-backlinks
Thanks, Dedra Bryce
That's a good post. The blog content is very useful and thank you for sharing. We hope our readers will find this blog useful. 카지노사이트 Here is my website. Please visit my site and send us your comments.
gambling center will transform his hometown into a national epicenter of racing.
https://www.cacenter77.com/sand
billion in net new spending in Oregon, create 2,007 net new full-time jobs, and pay $361.9 million in tax over the next 30 years https://www.cacenter77.com/merit
In a recently published economic impact study, its owner claimed the center and its racetrack will https://www.cacenter77.com/
Meanwhile, the Flying Lark plans to open this fall, regulators permitting.
https://www.mee8090.com/ 카지노사이트
Brown has previously said she would defer to the Oregon Racing Commission on the issue of the Flying Lark’s gaming terminals https://www.caxim77.com/
We are at a critical moment where the state is about to approve the largest expansion of state-regulated gambling in decades without public or legislative input
https://www.cavangers77.com/ 카지노사이트
The state’s regulatory framework has not evolved to reflect new technology or its impacts on the public,” the tribes wrote https://www.cabu88.com/
threatened, not only by historical horse racing but also by mobile sports betting, available since https://www.casanta78.com/ 카지노사이트
In Oregon, the tribes hold exclusivity on slots and casino gaming under the terms of their compacts. They feel this right is being https://www.cazla33.com/
where they are “nothing other than slot machines, from a player perspectiv
https://www.banslot88.com/
They claim the newest generation of machines have evolved beyond the pari-mutuel system to the point https://www.darsim77.com/ 카지노사이트
https://www.cavante77.com/
The machines are legal because they broadly use the pari-mutuel betting system permitted at racetracks, although the tribes dispute this.
Grants Pass is the only commercial horse racetrack currently in operation in the state. https://www.cadad88.com/
Historical horse racing machines have been legal in Oregon since 2012, but only at racetracks. Following the demise of Portland Meadows in https://www.bost11.com/ 카지노사이트
https://www.ekffo150.com 우리카지노사이트
https://www.omcyy.com/firstcasino 퍼스트카지노
QGWWP9L4VP9XTORWXF http://www.google.com
I have a small question for you
https://www.oobbg.com/yes 예스카지노
I constantly spent my half an hour to read this blog’s posts every day along with a cup of coffee.
Great post. I will be going through a few of these issues as well..
Hey I know this is off topic but I was wondering if you knew of any widgets I could add to
my blog that automatically tweet my newest twitter updates.
Hello
YOU NEED QUALITY VISITORS FOR YOUR: alexandreomiranda.com ?
We Provide Website Traffic 100% safe for your site, from Search Engines or Social Media Sites from any country you want.
With this traffic, you can boost ranking in SERP, SEO, profit from CPM
CLAIM YOUR 24 HOURS FREE TEST HERE=> http://mariosyei18529.bloggerbags.com/8099366/get-quality-visitors-for-your-site
Thanks, Odessa Ormiston
https://www.omgab.com/sands 샌즈카지노