J'essaie d'ajouter simple Authentification et autorisation à une application ASP.NET MVC.
J'essaie simplement de mettre en valeur certaines fonctionnalités ajoutées à l'authentification de base des formulaires (en raison de la simplicité et de la structure de base de données personnalisée)
En supposant que c'est la structure de ma base de données: Utilisateur: rôle de mot de passe du nom d'utilisateur (idéalement une énumération. Des chaînes si besoin est. Actuellement, l'utilisateur n'a qu'un rôle, mais cela pourrait changer)
Problème de haut niveau: Compte tenu de la structure de la base de données ci-dessus, je voudrais pouvoir faire ce qui suit:
Actuellement, tout ce dont je suis vraiment sûr est de savoir comment s'authentifier. Après ça, je suis perdu. Je ne sais pas à quel moment dois-je saisir le rôle d'utilisateur (connexion, chaque autorisation?). Étant donné que mes rôles peuvent ne pas être des chaînes, je ne sais pas comment ils s'intégreront avec User.IsInRole ().
Maintenant, je demande ici parce que je n'ai pas trouvé un "simple" accomplir ce dont j'ai besoin. J'ai vu plusieurs exemples.
Pour l'authentification:
Pour l'autorisation, j'ai vu:
Toute assistance sera grandement appréciée. Cependant, je crains d'avoir besoin de beaucoup de détails, car rien de ce que j'ai googlé ne semble correspondre à ce que je dois faire.
Créez un AuthorizeAttribute
personnalisé qui peut utiliser vos énumérations plutôt que des chaînes. Lorsque vous devez autoriser, convertissez les énumérations en chaînes en ajoutant le nom du type d'énumération + la valeur d'énumération et utilisez le IsInRole
à partir de là.
Pour ajouter des rôles à un utilisateur autorisé, vous devez attacher à l'événement HttpApplication
AuthenticateRequest
quelque chose comme le premier code dans http://www.eggheadcafe.com/articles/20020906. asp (mais inversez les instructions if massivement imbriquées dans des clauses de garde!).
Vous pouvez effectuer un aller-retour entre les rôles des utilisateurs dans le cookie d'authentification par formulaire ou les récupérer à chaque fois dans la base de données.
Je pense que j'ai mis en œuvre quelque chose de similaire.
Ma solution, basée sur NerdDinnertutorial , suit.
Lorsque vous connectez l'utilisateur , ajoutez du code comme ceci:
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);
System.Web.HttpContext.Current.Response.Cookies.Add(authCookie);
Ajoutez le code suivant à 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);
}
Après cela, vous pouvez utiliser [Authorize]
attribut dans le code d'action de votre contrôleur:
[Authorize(Roles="Admin")]
public ActionResult AdminIndex ()
S'il vous plaît laissez-moi savoir si vous avez d'autres questions.
J'ai fait quelque chose comme ça:
Attribuez l'attribut [Authorize] à vos contrôleurs, vous voulez demander une autorisation pour
[Authorize(Roles = "Admin,Tech")]
ou pour autoriser l'accès, par exemple les contrôleurs Login et ValidateUser utilisent l'attribut ci-dessous
[AllowAnonymous]
Mon formulaire de connexion
<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>
Login Controller et ValidateUser controller invoqués depuis le post du formulaire
L'utilisateur de validation est l'authentification par l'intermédiaire d'un service WCF qui valide contre le contexte de Windows AD local au service, mais vous pouvez le changer à votre propre mécanisme d'authentification
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;
}
}
}
L'utilisateur est authentifié maintenant créez la nouvelle identité
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(';'));
}
}
Sur mon site en haut de mon _Layout.cshtml j'ai quelque chose comme ça
{
bool authedUser = false;
if (User != null && User.Identity.AuthenticationType == "MyCustomAuthTypeName" && User.Identity.IsAuthenticated)
{
authedUser = true;
}
}
Puis dans le corps
@{
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>
}
}
Ajoutez vos utilisateurs au tableau "utilisateurs dans les rôles". Utilisez la procédure stockée "addusertorole" (quelque chose comme ça) dans votre code pour ajouter à différents rôles. Vous pouvez créer les rôles très simplement dans le tableau "rôles".
Vos tables à utiliser: User, UsersInRole, Roles
Utilisez les processus stockés intégrés pour manipuler ces tables. Ensuite, tout ce que vous avez à faire est d'ajouter l'attribut.
Par exemple, vous pouvez avoir un attribut "Admin" dans une vue qui sélectionne un utilisateur et les ajoute à un rôle. Vous pouvez utiliser le proc stocké pour ajouter cet utilisateur au rôle.