我对ASP.NET MVC 5中的身份验证和授权感到困惑。
我正在使用现有网站,我需要在其中添加安全性。安全性我指的是身份验证(登录)和授权(角色)。虽然我可以访问实体(用户,角色等),但我可以访问Web服务,但不能直接访问数据库。
成员资格提供程序似乎有点旧,所以我看了一下Identity,但实现现有项目看起来很复杂,特别是当我无法直接访问数据库时。
什么是好的解决方案?什么是最佳做法? 你能告诉我任何好的资源,以便能满足我的需求吗?
谢谢。
答案 0 :(得分:2)
如果有人感到像我一样迷失,这是一个使用声明的潜在解决方案。最后,您将了解如何处理身份验证,授权和角色。 希望这可以提供帮助。
在我的项目的根文件夹中,我创建了一个文件startup.cs。她包含一个部分类,我们将使用它来配置应用程序以使用存储已签名用户的cookie。
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
}
}
然后,在App_Start中我有一个文件,Startup.Auth.cs
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login")
});
}
}
首先,我创建了一个属性类型为IAuthenticationManager的AcountController.cs。此属性获取当前请求中可用的身份验证中间件功能。
public class CompteController : Controller
{
private IAuthenticationManager AuthenticationManager
{
get
{
return HttpContext.GetOwinContext().Authentication;
}
}
}
然后,我有一个名为Login with GET和POST的经典视图。如果用户可以登录,我会在帖子中检查我的Web服务。如果他能,我称之为神奇功能进行身份验证。在此代码中,类User是我在Webservice中获得的自定义用户。他没有实施IUser。
private void AuthentifyUser(User user, bool isPersistent)
{
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
CustomIdentity identity = new CustomIdentity(user);
CustomPrincipal principal = new CustomPrincipal(identity);
Thread.CurrentPrincipal = principal;
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
}
我的Controller中的最后一个重要方法允许用户注销。
public ActionResult Deconnexion()
{
AuthenticationManager.SignOut();
return RedirectToAction("Login", "Account");
}
CustomIdentity和CustomPrincipal是我用于Claims系统的两个自定义类。他们间接实施了IIdentity和IPrincipal。我把它们放在一个单独的新文件夹中。
- 请记住,主体对象代表代表其运行的用户的安全上下文,包括该用户的身份(IIdentity)以及它们所属的任何角色。
- 标识对象代表代表其运行的用户。
public class HosteamIdentity : ClaimsIdentity
{
public HosteamIdentity(User user)
: base(DefaultAuthenticationTypes.ApplicationCookie)
{
AddClaim(new Claim("IdUser", user.Id.ToString()));
AddClaim(new Claim(ClaimTypes.Name, user.Name));
AddClaim(new Claim(ClaimTypes.Role, user.Role));
}
public int IdUser
{
get
{
return Convert.ToInt32(FindFirst("IdUser").Value);
}
}
//Other Getters to facilitate acces to the Claims.
}
校长让我们可以访问身份。
public class HosteamPrincipal : ClaimsPrincipal
{
private readonly HosteamIdentity _identity;
public new HosteamIdentity Identity
{
get { return _identity; }
}
public HosteamPrincipal(HosteamIdentity identity)
{
_identity = identity;
}
public override bool IsInRole(string role)
{
return _identity.Role == role;
}
}
现在,我将转到gGlobal.asax,这里我们将覆盖Application_PostAuthenticateRequest事件。当安全模块已建立用户身份时,将触发此事件。
我们将使用Thread.CurrentPrincipal,这个静态对象获取或设置线程的当前主体(用于基于角色的安全性),因此它非常适合我们的情况!
您可能需要在此处调整代码。我个人不得不要求我的Web服务,这可能不是你的情况。
简单谈谈我们的构造函数。拳头是空的,我们将在不关心角色时使用它
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
Thread.CurrentPrincipal = new HosteamPrincipal(
new HosteamIdentity(
WebService.GetUser(
HttpContext.Current.User.Identity.Name)));
}
}
在大多数情况下,通过名称检索用户不是一个好习惯。请将上述代码改编为您的解决方案。
现在,如果我们能够轻松地告知经过身份验证的用户可以访问哪个Controller或Action,那将会很棒。为此,我们将使用过滤器。
过滤器是自定义类,它提供声明式和编程式方法,以便为控制器操作方法添加操作前和操作后行为。我们将它们用作注释,例如[Authorize]是一个过滤器。
由于需要解释许多事情,我会让你阅读评论,它们非常明确。
简单谈谈我们的构造函数。 - 第一个是空的,当我们不关心角色时我们会使用它。我们通过编写注释[CustomAuthorize]来使用Controller或Action。来访问它 - 第二个,采用一系列角色,我们将通过编写注释[CustomAuthorize(" Role1"," Role2"等)]来使用它。或行动。他将定义哪些角色访问控制器或操作
public class CustomAuthorize : AuthorizeAttribute
{
private new string[] Roles { get; set; }
public CustomAuthorize() { }
public CustomAuthorize(params string[] roles)
{
this.Roles = roles[0].Split(',');
}
/// <summary>
/// Check for Authorizations (Authenticated, Roles etc.)
/// </summary>
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (httpContext.Request.IsAuthenticated)
if (Roles != null)
{
foreach (string role in Roles)
if (((HosteamPrincipal)Thread.CurrentPrincipal).IsInRole(role))
return true;
return false;
}
else
return true;
return false;
}
/// <summary>
/// Defines actions to do when Authorizations are given or declined
/// </summary>
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (!AuthorizeCore(filterContext.HttpContext))
HandleUnauthorizedRequest(filterContext);
}
/// <summary>
/// Manage when an Authorization is declined
/// </summary>
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (filterContext.HttpContext.Request.IsAuthenticated)
filterContext.Result = new HttpStatusCodeResult(HttpStatusCode.Forbidden);
else
base.HandleUnauthorizedRequest(filterContext);
}
}