【发布时间】:2012-09-16 02:43:00
【问题描述】:
我正在使用带有 MSSQL 后端的 MVC3 构建 Intranet 应用程序。我的身份验证和角色(通过自定义角色提供程序)正常工作。我现在要做的是覆盖 User.Identity 以允许像 User.Identity.FirstName 这样的项目。但我找不到任何代码可以告诉我如何在 WindowsIdentity 中执行此操作
我尝试过编写自定义提供程序:
public class CPrincipal : WindowsPrincipal
{
UserDAL userDAL = new UserDAL();
public CPrincipal(WindowsIdentity identity)
: base(identity)
{
userInfo = userDAL.GetUserProfile(identity.Name.Split('\\')[1]);
this.identity = identity;
}
public UserInfo userInfo { get; private set; }
public WindowsIdentity identity { get; private set; }
}
并覆盖 WindowsAuthentication 以填充自定义主体。
void WindowsAuthentication_OnAuthenticate(object sender, WindowsAuthenticationEventArgs e)
{
if (e.Identity != null && e.Identity.IsAuthenticated)
{
CPrincipal cPrincipal = new CPrincipal(e.Identity);
HttpContext.Current.User = cPrincipal;
}
}
我在身份验证函数中有一个断点,并且正在填充主体;但是,当我在控制器中放置断点时,用户只是其正常的 RolePrincipal,而不是我的自定义主体。我做错了什么?
编辑:
我在 global.asax 中注释掉了上面的代码。 我已经使用 C# 覆盖了 AuthorizeAttribute:
public class CAuthorize : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
bool authorized = base.AuthorizeCore(httpContext);
if (!authorized)
{
return false;
}
IIdentity user = httpContext.User.Identity;
CPrincipal cPrincipal = new CPrincipal(user);
httpContext.User = cPrincipal;
return true;
}
}
并将我的委托人调整为以下内容:
public class CPrincipal : IPrincipal
{
private UserDAL userDAL = new UserDAL();
public CPrincipal(IIdentity identity)
{
userInfo = userDAL.GetUserProfile(identity.Name.Split('\\')[1]);
this.Identity = identity;
}
public UserInfo userInfo { get; private set; }
public IIdentity Identity { get; private set; }
public bool IsInRole(string role)
{
throw new NotImplementedException();
}
}
现在我在输入断点时,手表会在用户中显示以下内容:
- 用户
- [CSupport.Model.CPrincipal]
- 身份
身份是可访问的;但是,它仍然是 WindowsIdentity CPrincipal 只能在手表中访问,不能直接访问。
编辑: 感谢为此做出贡献的所有人。您大大扩展了我对各个部分如何工作的理解。
我有两种工作方式,所以我想我会分享。
选项 1:覆盖 Global.asax 中的授权请求
这是我要去的那个。
我没有使用 Application_AuthenticateRequest,因为(据此:HttpContext.Current.User is null even though Windows Authentication is on)用户尚未在 Windows 身份验证过程中填充,因此我无法使用任何东西来获取用户信息。
Application_AuthorizeRequest 是链中的下一个,在引入 windows 身份之后发生。
protected void Application_AuthorizeRequest(object sender, EventArgs e)
{
if (User.Identity.IsAuthenticated && Roles.Enabled)
{
Context.User = new FBPrincipal(HttpContext.Current.User.Identity);
}
}
这是 Principal 的覆盖
public class CPrincipal : IPrincipal
{
private UserDAL userDAL = new UserDAL();
public CPrincipal(IIdentity identity)
{
userInfo = userDAL.GetUserProfile(identity.Name.Split('\\')[1]);
this.Identity = identity;
}
public UserInfo userInfo { get; private set; }
public IIdentity Identity { get; private set; }
public bool IsInRole(string role)
{
return userDAL.IsUserInRole(userInfo.UserName, role);
}
}
这是您在新创建的 Principal 中访问更新信息的方式。
[Authorize(Roles = "super admin")]
public ActionResult Dashboard()
{
string firstname = (User as CPrincipal).userInfo.FirstName; // <--
DashboardModel dModel = reportDAL.GetChartData();
return View(dModel);
}
选项 2:覆盖 AuthorizeAttribute
这是被覆盖的Principal(和上面一样)
public class CPrincipal : IPrincipal
{
private UserDAL userDAL = new UserDAL();
public CPrincipal(IIdentity identity)
{
userInfo = userDAL.GetUserProfile(identity.Name.Split('\\')[1]);
this.Identity = identity;
}
public UserInfo userInfo { get; private set; }
public IIdentity Identity { get; private set; }
public bool IsInRole(string role)
{
return userDAL.IsUserInRole(userInfo.UserName, role);
}
}
这里是授权属性的覆盖
public class CAuthorize : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
bool authorized = base.AuthorizeCore(httpContext);
if (!authorized)
{
return false;
}
IIdentity user = httpContext.User.Identity;
CPrincipal cPrincipal = new CPrincipal(user);
httpContext.User = cPrincipal;
return true;
}
}
您可以在此处更改要使用的 AuthorizeAttribute 并利用新信息。
[CAuthorize(Roles = "super admin")] // <--
public ActionResult Dashboard()
{
string firstname = (User as CPrincipal).userInfo.FirstName; // <--
DashboardModel dModel = reportDAL.GetChartData();
return View(dModel);
}
选项 1 在全局范围内处理所有事情,选项 2 在个人级别处理所有事情。
【问题讨论】:
-
等等...那个事件处理程序是什么?您不是在尝试使用 ASP.NET 登录控件吗?此活动位于何处以及与哪个活动相关?
-
我在 Intranet 站点上使用 Windows 身份验证。此事件处理程序位于 global.asax
-
global.asax 中没有 OnAuthenticate 处理程序。这可能就是您遇到问题的原因。
-
使用时必须将其转换为 WindowsIdentity。或者,使用我在下面制作的扩展方法。
-
如果我将身份转换为 CPrincipal 中的 WindowsIdentity,则会出现以下错误:“CSupport.Models.CPrincipal.Identity”无法实现“System.Security.Principal.IPrincipal.Identity”,因为它确实实现了没有“System.Security.Principal.IIdentity”的匹配返回类型如果我将覆盖更改为 WindowsPrincipal,我会收到此错误:“System.Security.Principal.WindowsPrincipal”不包含采用 0 个参数的构造函数
标签: asp.net-mvc-3 windows-authentication intranet windows-identity windows-principal