tag route page net for data asp all asp.net-mvc forms-authentication authorization

asp.net-mvc - route - tag helpers asp net core



Autenticación de formularios MVC de ASP.NET+Autorizar atributo+Roles simples (5)

Intento agregar Autenticación y Autorización simples a una aplicación ASP.NET MVC.

Solo intento agregar algunas funciones adicionales a la Autenticación de formularios básica (debido a la simplicidad y la estructura de la base de datos personalizada)

Asumiendo que esta es la estructura de mi base de datos: Usuario: nombre de usuario contraseña (idealmente algunas cadenas enum. Si es necesario. Actualmente, el usuario solo tiene UNA función, pero esto podría cambiar)

Problema de alto nivel: dada la estructura de la base de datos anterior, me gustaría poder hacer lo siguiente:

  • Inicio de sesión simple mediante la autenticación de formularios
  • Decora mis acciones con: [Authorize (Roles = {MyRoles.Admin, MyRoles.Member})]
  • Usar roles en mis Vistas (para determinar enlaces para mostrar en algunos parciales)

Actualmente, de lo único que estoy realmente seguro es de cómo autenticar. Después de eso estoy perdido. No estoy seguro de en qué punto tomo el rol de usuario (inicio de sesión, ¿cada autorización?). Dado que mis roles pueden no ser cadenas, no estoy seguro de cómo encajarán con el User.IsInRole ().

Ahora, estoy preguntando aquí porque no he encontrado un "simple" lograr lo que necesito. He visto múltiples ejemplos.

Para la autenticación:

  • Tenemos una validación de usuario simple que verifica la base de datos y "SetAuthCookie"
  • O anulamos el proveedor de membresía y hacemos esto dentro de ValidateUser. En cualquiera de estos casos, no estoy seguro de cómo agregar mis Roles de usuario simple, para que funcionen con: HttpContext.Current.User.IsInRole ("Administrator") Además, no estoy seguro de cómo modificar esto para trabajar con mis valores enum.

Para la autorización, he visto:

  • ¿Derivando AuthorizeAttribute e implementando AuthorizeCore O OnAuthorization para manejar roles?
  • ¿Implementando IPrincipal?

Cualquier ayuda sería muy apreciada. Sin embargo, me temo que podría necesitar muchos detalles, porque nada de lo que he buscado en Google parece encajar con lo que tengo que hacer.


Agregue sus usuarios a la tabla "usuarios en roles". Use el procedimiento almacenado "addusertorole" (algo así) en su código para agregar a varios roles. Puede crear los roles muy simplemente en la tabla de "roles".

Tus tablas para usar: User, UsersInRole, Roles

Usa los Procs almacenados integrados para manipular esas tablas. Entonces todo lo que tienes que hacer es agregar el atributo.

Por ejemplo, puede tener un atributo "Admin" en una vista que selecciona un usuario y lo agrega a un rol. Puede usar el proceso almacenado para agregar ese usuario a la función.


Creo que he implementado algo similar.
Mi solución, basada en el tutorial NerdDinner , es la siguiente.

Cuando firmes al usuario , agrega un código como este:

var authTicket = new FormsAuthenticationTicket( 1, // version userName, // user name DateTime.Now, // created DateTime.Now.AddMinutes(20), // expires rememberMe, // persistent? "Moderator;Admin" // can be used to store roles ); string encryptedTicket = FormsAuthentication.Encrypt(authTicket); var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket); HttpContext.Current.Response.Cookies.Add(authCookie);

Agregue el siguiente código a Global.asax.cs :

protected void Application_AuthenticateRequest(Object sender, EventArgs e) { HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName]; if (authCookie == null || authCookie.Value == "") return; FormsAuthenticationTicket authTicket; try { authTicket = FormsAuthentication.Decrypt(authCookie.Value); } catch { return; } // retrieve roles from UserData string[] roles = authTicket.UserData.Split('';''); if (Context.User != null) Context.User = new GenericPrincipal(Context.User.Identity, roles); }

Después de hacer esto, puede usar el atributo [Authorize] en su código de acción del controlador:

[Authorize(Roles="Admin")] public ActionResult AdminIndex ()

Por favor, hágamelo saber si tiene más preguntas.


Hice algo como esto:

  • Utilice Global.asax.cs para cargar los roles que desea comparar en sesión, caché o estado de aplicación, o cárguelos sobre la marcha en el controlador ValidateUser

Asigne el atributo [Autorizar] a sus controladores, desea solicitar autorización para

[Authorize(Roles = "Admin,Tech")]

o para permitir el acceso, por ejemplo, los controladores Login y ValidateUser usan el siguiente atributo

[AllowAnonymous]

Mi formulario de acceso

<form id="formLogin" name="formLogin" method="post" action="ValidateUser"> <table> <tr> <td> <label for="txtUserName">Username: (AD username) </label> </td> <td> <input id="txtUserName" name="txtUserName" role="textbox" type="text" /> </td> </tr> <tr> <td> <label for="txtPassword">Password: </label> </td> <td> <input id="txtPassword" name="txtPassword" role="textbox" type="password" /> </td> </tr> <tr> <td> <p> <input id="btnLogin" type="submit" value="LogIn" class="formbutton" /> </p> </td> </tr> </table> @Html.Raw("<span id=''lblLoginError''>" + @errMessage + "</span>") </form>

Regulador de inicio de sesión y controlador ValidateUser invocados desde la publicación Formulario

El usuario de validación es la autenticación a través de un servicio WCF que valida con el contexto de Windows AD local al servicio, pero puede cambiar esto a su propio mecanismo de autenticación

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Security; using System.Security.Principal; using MyMVCProject.Extensions; namespace MyMVCProject.Controllers { public class SecurityController : Controller { [AllowAnonymous] public ActionResult Login(string returnUrl) { Session["LoginReturnURL"] = returnUrl; Session["PageName"] = "Login"; return View("Login"); } [AllowAnonymous] public ActionResult ValidateUser() { Session["PageName"] = "Login"; ViewResult retVal = null; string loginError = string.Empty; HttpContext.User = null; var adClient = HttpContext.Application.GetApplicationStateWCFServiceProxyBase.ServiceProxyBase<UserOperationsReference.IUserOperations>>("ADService").Channel; var username = Request.Form["txtUserName"]; var password = Request.Form["txtPassword"]; //check for ad domain name prefix if (username.Contains(@"/")) username = username.Split(''//')[1]; //check for the existence of the account var acctReq = new UserOperationsReference.DoesAccountExistRequest(); acctReq.userName = username; //account existence result var accountExist = adClient.DoesAccountExist(acctReq); if (!accountExist.DoesAccountExistResult) { //no account; inform the user return View("Login", new object[] { "NO_ACCOUNT", accountExist.errorMessage }); } //authenticate var authReq = new UserOperationsReference.AuthenticateRequest(); authReq.userName = username; authReq.passWord = password; var authResponse = adClient.Authenticate(authReq); String verifiedRoles = string.Empty; //check to make sure the login was as success against the ad service endpoint if (authResponse.AuthenticateResult == UserOperationsReference.DirectoryServicesEnumsUserProperties.SUCCESS) { Dictionary<string, string[]> siteRoles = null; //get the role types and roles if (HttpContext.Application["UISiteRoles"] != null) siteRoles = HttpContext.Application.GetApplicationState<Dictionary<string, string[]>>("UISiteRoles"); string groupResponseError = string.Empty; if (siteRoles != null && siteRoles.Count > 0) { //get the user roles from the AD service var groupsReq = new UserOperationsReference.GetUsersGroupsRequest(); groupsReq.userName = username; //execute the service method for getting the roles/groups var groupsResponse = adClient.GetUsersGroups(groupsReq); //retrieve the results if (groupsResponse != null) { groupResponseError = groupsResponse.errorMessage; var adRoles = groupsResponse.GetUsersGroupsResult; if (adRoles != null) { //loop through the roles returned from the server foreach (var adRole in adRoles) { //look for an admin role first foreach (var roleName in siteRoles.Keys) { var roles = siteRoles[roleName].ToList(); foreach (var role in roles) { if (adRole.Equals(role, StringComparison.InvariantCultureIgnoreCase)) { //we found a role, stop looking verifiedRoles += roleName + ";"; break; } } } } } } } if (String.IsNullOrEmpty(verifiedRoles)) { //no valid role we need to inform the user return View("Login", new object[] { "NO_ACCESS_ROLE", groupResponseError }); } if (verifiedRoles.EndsWith(";")) verifiedRoles = verifiedRoles.Remove(verifiedRoles.Length - 1, 1); //all is authenticated not build the auth ticket var authTicket = new FormsAuthenticationTicket( 1, // version username, // user name DateTime.Now, // created DateTime.Now.AddMinutes(20), // expires true, // persistent? verifiedRoles // can be used to store roles ); //encrypt the ticket before adding it to the http response string encryptedTicket = FormsAuthentication.Encrypt(authTicket); var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket); Response.Cookies.Add(authCookie); Session["UserRoles"] = verifiedRoles.Split('';''); //redirect to calling page Response.Redirect(Session["LoginReturnURL"].ToString()); } else { retVal = View("Login", new object[] { authResponse.AuthenticateResult.ToString(), authResponse.errorMessage }); } return retVal; } }

}

El usuario está autenticado ahora crea la nueva identidad

protected void FormsAuthentication_OnAuthenticate(Object sender, FormsAuthenticationEventArgs e) { if (FormsAuthentication.CookiesSupported == true) { HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName]; if (authCookie == null || authCookie.Value == "") return; FormsAuthenticationTicket authTicket = null; try { authTicket = FormsAuthentication.Decrypt(authCookie.Value); } catch { return; } // retrieve roles from UserData if (authTicket.UserData == null) return; //get username from ticket string username = authTicket.Name; Context.User = new GenericPrincipal( new System.Security.Principal.GenericIdentity(username, "MyCustomAuthTypeName"), authTicket.UserData.Split('';'')); } }

En mi sitio en la parte superior de mi _Layout.cshtml tengo algo como esto

{ bool authedUser = false; if (User != null && User.Identity.AuthenticationType == "MyCustomAuthTypeName" && User.Identity.IsAuthenticated) { authedUser = true; } }

Entonces en el cuerpo

@{ if (authedUser) { <span id="loggedIn_userName"> <label>User Logged In: </label>@User.Identity.Name.ToUpper() </span> } else { <span id="loggedIn_userName_none"> <label>No User Logged In</label> </span> } }


Cree un AuthorizeAttribute personalizado que pueda usar sus enumeraciones en lugar de cadenas. Cuando necesite autorizar, convierta las enumeraciones en cadenas agregando el nombre de tipo de enumeración + el valor de la enumeración y utilice el IsInRole desde allí.

Para agregar roles en un usuario autorizado, debe adjuntar al evento HttpApplication AuthenticateRequest algo así como el primer código en http://www.eggheadcafe.com/articles/20020906.asp (¡pero invierta las declaraciones if anidadas masivamente en cláusulas de guardia!) .

Puede redondear las funciones de los usuarios en la cookie de autenticación de formularios o tomarlos de la base de datos cada vez.


using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Security; using SISWEBBSI.Models.Model; using SISWEBBSI.Models.Model.Entities; using SISWEBBSI.Models.ViewModel; namespace SISWEBBSI.Controllers.ActionFilter { [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)] public sealed class RequerAutorizacao : ActionFilterAttribute { public Grupo.Papeis[] Papeis = {} ; public string ViewName { get; set; } public ViewDataDictionary ViewDataDictionary { get; set; } public AcessoNegadoViewModel AcessoNegadoViewModel { get; set; } public override void OnActionExecuting(ActionExecutingContext FilterContext) { if (!FilterContext.HttpContext.User.Identity.IsAuthenticated) { string UrlSucesso = FilterContext.HttpContext.Request.Url.AbsolutePath; string UrlRedirecionar = string.Format("?ReturnUrl={0}", UrlSucesso); string UrlLogin = FormsAuthentication.LoginUrl + UrlRedirecionar; FilterContext.HttpContext.Response.Redirect(UrlLogin, true); } else { if (Papeis.Length > 0) { //Papel ADMINISTRADOR sempre terá acesso quando alguma restrição de papeis for colocada. int NovoTamanho = Papeis.Count() + 1; Array.Resize(ref Papeis, NovoTamanho); Papeis[NovoTamanho - 1] = Grupo.Papeis.ADMINISTRADOR; UsuarioModel Model = new UsuarioModel(); if (!Model.UsuarioExecutaPapel(FilterContext.HttpContext.User.Identity.Name, Papeis)) { ViewName = "AcessoNegado"; String Mensagem = "Você não possui privilégios suficientes para essa operação. Você deve estar nos grupos que possuem"; if(Papeis.Length == 1) { Mensagem = Mensagem + " o papel: <BR/>"; } else if (Papeis.Length > 1) { Mensagem = Mensagem + " os papéis: <BR/>"; } foreach (var papel in Papeis) { Mensagem = Mensagem + papel.ToString() + "<br/>"; } AcessoNegadoViewModel = new AcessoNegadoViewModel(); AcessoNegadoViewModel.Mensagem = Mensagem; ViewDataDictionary = new ViewDataDictionary(AcessoNegadoViewModel); FilterContext.Result = new ViewResult { ViewName = ViewName, ViewData = ViewDataDictionary }; return; } } } } } }