Usuário com melhor resposta
usando membership provider personalizado

Pergunta
-
Respostas
-
Júnior,
A pasta onde os arquivos das ActionFilter (classes) ficam não faz muita diferença, o importante é o namespace que deve corresponder ao da sua aplicação.
Quanto à modificar a view login para utilizar a sua basta apagar todas as Action e inserir as suas.
No meu caso utilizo assim:
public class AccountController : Controller { private Domain _domain; public HomeController() { _domain = new Domain(); } public ActionResult Index() { if (User.Identity.IsAuthenticated) return RedirectToAction("Index", "Menu"); else return View(); } [HttpPost] public ActionResult Index([Bind(Exclude = "Id")]User user) { if (ModelState.IsValid) { if (_domain.ValidateUser(user.Login, user.Password)) { FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, "Administrador", DateTime.Now, DateTime.Now.AddMinutes(30), false, "admin", FormsAuthentication.FormsCookiePath); //For security reasons we may hash the cookies string hashCookies = FormsAuthentication.Encrypt(ticket); HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, hashCookies); // add the cookie to user browser Response.Cookies.Add(cookie); return RedirectToAction("Index", "Menu"); } else { ModelState.AddModelError("login", "Dados de login incorretos!"); return View(); } } else { return View(); } } }
- Marcado como Resposta Junior_luiz quarta-feira, 11 de maio de 2011 11:45
-
Ok, entendi o que você está fazendo. Como você pode ver não utilizo o MembershipProvider para buscar o usuário dentro do método RoleProvider.GetRolesForUsers, tenho uma camada de acesso a dados que retorna o usuário. No seu método GetRolesForUsers utilize um objeto de acesso a dados ou faça:
db.usuarios.FirstOrDefault(u => u.Nome = username) que retorna seu usuário (db.usuarios).
Atenciosamente, Paulo R. Pereira de Souza
http://paulosouza.net
E-mail: paulorpereirasouza@hotmail.com.- Marcado como Resposta Junior_luiz quarta-feira, 11 de maio de 2011 11:44
Todas as Respostas
-
Junior você deve criar um CustomMembershipProvider que extende de MembershipProvider e um CustomRoleProvider que extende CustomRoleProvider, o método RoleProvider.GetRolesForUser(string username) sempre é chamado quando você utiliza o atributo Authorize ou chama Context.User.IsInRole("Admin") por exemplo. Deve fazer as modificações necessárias no arquivo de configuração para utilizar a sua customização por ex:
<membership defaultProvider="CustomMembership"> <providers> <clear/> <add name="CustomMembership" applicationName="SuaEmpresa.SuaAplpication.Web" type="SuaEmpresa.Web.Security.CustomMembershipProvider, SuaEmpresa.Web"/> </providers> </membership> <roleManager enabled="true" defaultProvider="CustomRoles"> <providers> <clear/> <add name="CustomRoles" applicationName="SuaEmpresa.SuaAplpication.Web" type="SuaEmpresa.Web.Security.CustomRoleProvider, SuaEmpresa.Web"/> </providers> </roleManager>
Atenciosamente, Paulo R. Pereira de Souza
http://paulosouza.net
E-mail: paulorpereirasouza@hotmail.com.- Sugerido como Resposta Vinicius Gama segunda-feira, 9 de maio de 2011 16:08
- Editado Paulo Renato Pereira de Souza segunda-feira, 9 de maio de 2011 18:27
-
Paulo, obrigado por responder, estou estudando mvc e em webforms tenho uma tabela com usuario, permissoes e acesso, mais não está na estrutura do ASPNETDB, preciso ter a mesma estrutura ? e no caso, tenho uma extranet que já está em produção feita em webforms e estou fazendo a mesma em mvc, e gostaria de usar o banco existente pois já tenho todos os usuários cadastrados, e achei muito interessante a parte do authorize nas páginas mvc, para ter acesso a essa facilidade do authorize nas páginas preciso ter a mesma esturtura do ASPNETDB ?
Junior -
Não precisa ter a mesma estrutura. Só corrigingo o post anterior o método é IsInRole, estava HasPermission.
Atenciosamente, Paulo R. Pereira de Souza
http://paulosouza.net
E-mail: paulorpereirasouza@hotmail.com. -
-
Na epoca que estudei autorização com asp .net utilizei diversas fontes, o livro Pro ASP .NET 4, no msdn tem muita documentação também foi uma de minhas fontes, de forma geral a uma infinidade de fontes na internet sobre o assunto.
Atenciosamente, Paulo R. Pereira de Souza
http://paulosouza.net
E-mail: paulorpereirasouza@hotmail.com. -
Júnior,
A melhor maneira para implementar uma autenticação customizada no MVC é usando uma ActionFilterAttribute em conjunto com a "decoration" dos controllers.
Segue abaixo um exemplo:
Arquivo 1: Classe que implementa o ActionFilter
Classe 2: Implementar a ActionFilter para as roles (permissões)using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Security; namespace xxxxxxxxxxx { public class RequiresAuthenticationAttribute : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { //redirect if not authenticated if (!filterContext.HttpContext.User.Identity.IsAuthenticated) { //use the current url for the redirect string redirectOnSuccess = filterContext.HttpContext.Request.Url.AbsolutePath; //send them off to the login page string redirectUrl = string.Format("?ReturnUrl={0}", redirectOnSuccess); string loginUrl = FormsAuthentication.LoginUrl + redirectUrl; filterContext.HttpContext.Response.Redirect(loginUrl, true); } } } }
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Security; namespace xxxxxxxxxxxxxxx { public class RequireRolesAttribute : ActionFilterAttribute { public string RoleToCheckFor { get; set; } public override void OnActionExecuting(ActionExecutingContext filterContext) { //redirect if the user is not authenticated if (!String.IsNullOrEmpty(RoleToCheckFor)) { if (!filterContext.HttpContext.User.Identity.IsAuthenticated) { //use the current url for the redirect string redirectOnSuccess = filterContext.HttpContext.Request.Url.AbsolutePath; //send them off to the login page string redirectUrl = string.Format("?ReturnUrl={0}", redirectOnSuccess); string loginUrl = FormsAuthentication.LoginUrl + redirectUrl; filterContext.HttpContext.Response.Redirect(loginUrl, true); } else { FormsIdentity identity = (FormsIdentity)filterContext.HttpContext.User.Identity; FormsAuthenticationTicket ticket = identity.Ticket; string actualRole = ticket.UserData; //bool isAuthorized = actualRole == this.RoleToCheckFor ? true : false;// filterContext.HttpContext.User.IsInRole(this.RoleToCheckFor); bool isAuthorized = false; string[] roles = RoleToCheckFor.Split(','); for (int i = 0; i < roles.Length; i++) { if(filterContext.HttpContext.User.IsInRole(this.RoleToCheckFor)) isAuthorized = true; } if (!isAuthorized) throw new UnauthorizedAccessException("Você não está autorizado a acessar esta página!"); } } else { throw new InvalidOperationException("No Role Specified"); } } } }
3: View que recebe os dados de login e autentica o usuário:
[AcceptVerbs(HttpVerbs.Post)] public ActionResult LogOn(string userName, string password) { //A AUTENTICAÇÃO ESTÁ EM UMA CAMADA SEPARADA USUARIOS usu = _service.AutenticaUsuario(userName, password); if (usu != null) { FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, userName, DateTime.Now, DateTime.Now.AddMinutes(30), false, usu.PERFIL.NOMECODIGO, FormsAuthentication.FormsCookiePath); //For security reasons we may hash the cookies string hashCookies = FormsAuthentication.Encrypt(ticket); HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, hashCookies); // add the cookie to user browser Response.Cookies.Add(cookie); return RedirectToAction("Index", "Home"); } return View(); }
4: Decore os seus controllers (global):
[RequiresAuthentication] [RequireRoles(RoleToCheckFor = "master")] public class ControleController : Controller { //... }
4.1: Ou decore uma view específica:
Usando esta técnica fica fácil usar suas próprias tabelas sem ter que usar o membership.public class SegmentoController : Controller { // // GET: /Segmento/ [RequiresAuthentication] [RequireRoles(RoleToCheckFor = "master,secretaria")] public ActionResult Index() { return View(_service.ListSegmentos()); } }
-
-
João, Junior,
Concordo que criar uma implemetação de ActionFilterAttribute é a forma mais adequada de intervir na requisição no MVC. Agora no seu exemplo você utiliza filterContext.HttpContext.User.IsInRole(this.RoleToCheckFor)), se você não possui um RoleProvider neste caso como ele irá lidar com essa instrução?
Possua uma implementação de MembershipProvider, RoleProvider, mas como na maioria dos cenários preciso de algo mais flexivel, criei um Extension Method string HasPermission(this IPrincipal principal, string permission), onde permissao pode ser qualquer coisa/recurso/regra de negocio dentro do sistema. Como é um método que extende as funcionalidades de HttpContext.User posso utiliza-lo em toda aplicação web páginas/controladores. Para certificar que as requisições que precisam de permissões especiais criei uma implementação de ActionFilterAttribute semelhante a sua mas que apenas faz uma checagem em filterContext.HttpContext.User.HasPermission(permission).
Dessa forma em situações onde o esquema tradicional de autorização do .NET me atende faço uso de Authorize nas outras faço uso de minha implementação AuthorizePermission.
Atenciosamente, Paulo R. Pereira de Souza
http://paulosouza.net
E-mail: paulorpereirasouza@hotmail.com. -
Paulo, como falei anteriormente estou estudando mvc e estou tentando migrar uma página já existente em web forms para mvc, já consegui implementar o membership por esse tutorial
http://kitsula.com/Article/Custom-Membership-Provider-for-MVC
Fiz uma adaptação apenas no MembershipProvider(validateuser) para ele ir no meu entity framework e testar se o usuario e senha existem no banco e funcionou perfeito, agora vou ver a implementação do provider.
Se vc pudesse exemplificar ou dizer um tutorial onde posso ver esse seu exemplo ajudaria bastante.
Junior -
Júnior,
A pasta onde os arquivos das ActionFilter (classes) ficam não faz muita diferença, o importante é o namespace que deve corresponder ao da sua aplicação.
Quanto à modificar a view login para utilizar a sua basta apagar todas as Action e inserir as suas.
No meu caso utilizo assim:
public class AccountController : Controller { private Domain _domain; public HomeController() { _domain = new Domain(); } public ActionResult Index() { if (User.Identity.IsAuthenticated) return RedirectToAction("Index", "Menu"); else return View(); } [HttpPost] public ActionResult Index([Bind(Exclude = "Id")]User user) { if (ModelState.IsValid) { if (_domain.ValidateUser(user.Login, user.Password)) { FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, "Administrador", DateTime.Now, DateTime.Now.AddMinutes(30), false, "admin", FormsAuthentication.FormsCookiePath); //For security reasons we may hash the cookies string hashCookies = FormsAuthentication.Encrypt(ticket); HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, hashCookies); // add the cookie to user browser Response.Cookies.Add(cookie); return RedirectToAction("Index", "Menu"); } else { ModelState.AddModelError("login", "Dados de login incorretos!"); return View(); } } else { return View(); } } }
- Marcado como Resposta Junior_luiz quarta-feira, 11 de maio de 2011 11:45
-
Sim você basicamente vai precisar implementar apenas oum método no role provider.
Ok, dessa forma você conseguirá utilizar o Atributo Authorize do MVC com o seu esquema customizado, caso precise de algo mais personalizado você pode pensar a respeito do que falei no ultimo post.
Um exemplo de implementação de GetRolesForUser seria:
public override string[] GetRolesForUser(string username) {
IUserDao userDao = DaoFactory.GetUserDao(); User user = userDao.GetUserByLogin(username); var roles = user.Roles.Select(r => r.Name).ToArray(); return roles;
}
Atenciosamente, Paulo R. Pereira de Souza
http://paulosouza.net
E-mail: paulorpereirasouza@hotmail.com.- Editado Paulo Renato Pereira de Souza terça-feira, 10 de maio de 2011 18:50
-
Paulo tenho 3 tabelas : usuario,permissao e usuariopermissao,estou tentando assim no GetUsersInRole e no GetRolesForUsers mais está dando erro dizendo que o roles está vazio ou seja o linq não trás nada
public override string[] GetRolesForUser(string username) { using (MembershipEntities db = new MembershipEntities()) { usuario user = db.usuarios.FirstOrDefault(u => u.Nome.Equals(username, StringComparison.CurrentCultureIgnoreCase)); var roles = from p in user.permissaos from r in db.permissaos where p.idpermissao == r.idpermissao select r.descricao; if (roles != null) return roles.ToArray(); else return new string[] { }; ; } }
Junior -
Junior,
Mudei o exemplo anterior para ficar mais simples. Me diz uma coisa, por que você fez a query dessa forma? Você não podeira fazer assim:
user.permissaos.Select(p => p.descricao).ToArray();
Uma pergunta, o que permissão significa no seu sistema? Significa um Role (Papél do Usuário) ou outra coisa?
Atenciosamente, Paulo R. Pereira de Souza
http://paulosouza.net
E-mail: paulorpereirasouza@hotmail.com. -
permissao é como um grupo onde um usuario pode pertencer a varios grupos, Paulo mudei a lógica e não dá mais erro na entrada mais depois de logado que tento acessar uma pagina que tem permissao ele dá erro aqui
usuario user = db.usuarios.FirstOrDefault(u => u.Nome.Equals(username, StringComparison.CurrentCultureIgnoreCase));
Mais passa no login
Junior -
Qual o erro?
Atenciosamente, Paulo R. Pereira de Souza
http://paulosouza.net
E-mail: paulorpereirasouza@hotmail.com. -
qdo ele executa o linq user está vazio,
olhei o seu exemplo me diz uma coisa, como vc implementou o getUserByLogin o que vc trás no return dele, estou tentando fazer aqui mais não sei o return dele, tentei true não aceita, fiz assim.
public override MembershipUser GetUserByLogin(string username) { using (MembershipEntities db = new MembershipEntities()) { var result = from u in db.usuarios where (u.Nome == username) select u; } return true; }
vc fez isso no seu exemplo
User user = userDao.GetUserByLogin(username);
Junior -
Ok, entendi o que você está fazendo. Como você pode ver não utilizo o MembershipProvider para buscar o usuário dentro do método RoleProvider.GetRolesForUsers, tenho uma camada de acesso a dados que retorna o usuário. No seu método GetRolesForUsers utilize um objeto de acesso a dados ou faça:
db.usuarios.FirstOrDefault(u => u.Nome = username) que retorna seu usuário (db.usuarios).
Atenciosamente, Paulo R. Pereira de Souza
http://paulosouza.net
E-mail: paulorpereirasouza@hotmail.com.- Marcado como Resposta Junior_luiz quarta-feira, 11 de maio de 2011 11:44
-
Paulo deu certo não só colocando simplesmente isso mais fiz assim e deu certo
Muito obrigado pela ajudapublic override string[] GetRolesForUser(string username) { using (MembershipEntities db = new MembershipEntities()) { if (HttpContext.Current.User != null) { usuario user = db.usuarios.FirstOrDefault(u => u.Login == username); var roles = user.permissaos.Select(r => r.descricao).ToArray(); return roles; } else { usuario user = db.usuarios.FirstOrDefault(u => u.Nome.Equals(username, StringComparison.CurrentCultureIgnoreCase)); var roles = user.permissaos.Select(r => r.descricao).ToArray(); return roles; } } }
Junior