MVC5 中无法访问自定义 IPrincipal
Custom IPrincipal Not Accessible in MVC5
我已经阅读了很多关于这个主题的问题和答案,但是 none 帮助我解决了这个问题。
我遇到的问题是 HttpContext.Current.User
或只是 User
属性 是 RolePrincipal
类型而不是我的自定义主体。
这是一个使用 Windows 身份验证的 MVC 5 网络应用程序(仅限 Intranet 应用程序)。我的自定义主体是 WindowsPrincipal
的子类,我确实实现了自己的 RoleProvider
用于授权属性标签。
当我尝试通过在当前 HttpContext 上将其从 IPrincipal
强制转换为我的自定义主体来使用该主体时,我收到一条错误消息,指出它是 RolePrincipal 类型,显然无法将其强制转换为我的自定义主体。我在 Application_PostAuthenticationRequest
事件中设置我的自定义委托人:
protected void Application_PostAuthenticationRequest(object sender, EventArgs e)
{
if (User == null)
return;
using(EntityContext db = new EntityContext ())
{
var user = db.Users.SingleOrDefault(u => u.ADName.Equals(User.Identity.Name));
HttpContext.Current.User = new PcsPrincipal((WindowsIdentity)User.Identity, user);
}
}
当我在那个方法中放置一个断点时,它似乎永远不会被调用,这可以解释为什么它没有被设置为我的自定义主体。
我已查看以下质量检查,但他们未能解决问题:
- using custom IPrincipal and IIdentity in MVC3 - 在Global.asax.cs的Init方法中添加了事件处理器的注册。似乎没有什么不同。此外,
_application
变量在 MVC5 中似乎无效。
- RoleProvider dosn't work with custom IIdentity and IPrincipal on server - 在 web.config 文件中进行了更改,但这在运行时导致了各种错误,错误表明 ASP.NET 管道配置不正确。
没有设置 Principal 是我做错了什么?让我知道是否需要发布更多代码。
编辑: 在 WindowsAuthentication.OnAuthenticate 事件中将 HttpContext.Current.User 设置为我的自定义主体并不能解决此问题。使用该方法表现出完全相同的行为。
您应该在应用程序验证当前请求时发生的 WindowsAuthentication_OnAuthenticate 事件中设置自定义主体。
protected void WindowsAuthentication_OnAuthenticate(object source, WindowsAuthenticationEventArgs e)
{
using(EntityContext db = new EntityContext ())
{
var user = db.Users.SingleOrDefault(u => u.ADName.Equals(e.Identity.Name));
HttpContext.Current.User = new PcsPrincipal(e.Identity, user);
}
}
在不断研究这个问题后,我终于通过另一个 SO 问题找到了答案,使我的问题有点重复:MVC3 Windows Authentication override User.Identity
下面是@Toby Jones 发布的答案(作为对他原始问题的编辑)导致我解决了我的问题,但他的答案实际上是@Erik Funkenbusch 和@Darin Dimitrov 发布的两个答案的集合.编辑了答案以修复一些语法并删除一些多余的信息。
选项 1:覆盖 Global.asax
中的授权请求
不应使用 Application_AuthenticateRequest 事件,因为(HttpContext.Current.User
为空,即使 Windows 身份验证已打开)用户尚未在 Windows 身份验证中填充过程,因此我无法使用任何东西来获取用户信息。
Application_AuthorizeRequest
是链中的下一个,发生在 Windows 身份被引入之后。
protected void Application_AuthorizeRequest(object sender, EventArgs e)
{
if (User.Identity.IsAuthenticated && Roles.Enabled)
{
Context.User = new CustomPrincipal((WindowsIdentity)User.Identity);
}
}
选项 2:覆盖 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;
}
}
然后将所有AuthorizeAttributes替换为自定义版本。
选项 1 全局处理所有内容,而选项 2 使用过滤器在更个性化的级别处理所有内容。
就我个人而言,我选择使用 global.asax 方法,这样我的自定义委托人就可以在全球范围内使用。这是解决我的问题的实际代码:
protected void Application_AuthorizeRequest(object source, EventArgs e)
{
if(User.Identity.IsAuthenticated && Roles.Enabled)
{
using (EntityContext db = new EntityContext ())
{
var user = db.Users.Include("Roles").SingleOrDefault(u => u.ADName.Equals(User.Identity.Name));
if (user == null)
return;
PcsPrincipal principal = new PcsPrincipal((WindowsIdentity)User.Identity, user);
Context.User = principal;
}
}
}
我已经阅读了很多关于这个主题的问题和答案,但是 none 帮助我解决了这个问题。
我遇到的问题是 HttpContext.Current.User
或只是 User
属性 是 RolePrincipal
类型而不是我的自定义主体。
这是一个使用 Windows 身份验证的 MVC 5 网络应用程序(仅限 Intranet 应用程序)。我的自定义主体是 WindowsPrincipal
的子类,我确实实现了自己的 RoleProvider
用于授权属性标签。
当我尝试通过在当前 HttpContext 上将其从 IPrincipal
强制转换为我的自定义主体来使用该主体时,我收到一条错误消息,指出它是 RolePrincipal 类型,显然无法将其强制转换为我的自定义主体。我在 Application_PostAuthenticationRequest
事件中设置我的自定义委托人:
protected void Application_PostAuthenticationRequest(object sender, EventArgs e)
{
if (User == null)
return;
using(EntityContext db = new EntityContext ())
{
var user = db.Users.SingleOrDefault(u => u.ADName.Equals(User.Identity.Name));
HttpContext.Current.User = new PcsPrincipal((WindowsIdentity)User.Identity, user);
}
}
当我在那个方法中放置一个断点时,它似乎永远不会被调用,这可以解释为什么它没有被设置为我的自定义主体。
我已查看以下质量检查,但他们未能解决问题:
- using custom IPrincipal and IIdentity in MVC3 - 在Global.asax.cs的Init方法中添加了事件处理器的注册。似乎没有什么不同。此外,
_application
变量在 MVC5 中似乎无效。 - RoleProvider dosn't work with custom IIdentity and IPrincipal on server - 在 web.config 文件中进行了更改,但这在运行时导致了各种错误,错误表明 ASP.NET 管道配置不正确。
没有设置 Principal 是我做错了什么?让我知道是否需要发布更多代码。
编辑: 在 WindowsAuthentication.OnAuthenticate 事件中将 HttpContext.Current.User 设置为我的自定义主体并不能解决此问题。使用该方法表现出完全相同的行为。
您应该在应用程序验证当前请求时发生的 WindowsAuthentication_OnAuthenticate 事件中设置自定义主体。
protected void WindowsAuthentication_OnAuthenticate(object source, WindowsAuthenticationEventArgs e)
{
using(EntityContext db = new EntityContext ())
{
var user = db.Users.SingleOrDefault(u => u.ADName.Equals(e.Identity.Name));
HttpContext.Current.User = new PcsPrincipal(e.Identity, user);
}
}
在不断研究这个问题后,我终于通过另一个 SO 问题找到了答案,使我的问题有点重复:MVC3 Windows Authentication override User.Identity
下面是@Toby Jones 发布的答案(作为对他原始问题的编辑)导致我解决了我的问题,但他的答案实际上是@Erik Funkenbusch 和@Darin Dimitrov 发布的两个答案的集合.编辑了答案以修复一些语法并删除一些多余的信息。
选项 1:覆盖 Global.asax
中的授权请求不应使用 Application_AuthenticateRequest 事件,因为(HttpContext.Current.User
为空,即使 Windows 身份验证已打开)用户尚未在 Windows 身份验证中填充过程,因此我无法使用任何东西来获取用户信息。
Application_AuthorizeRequest
是链中的下一个,发生在 Windows 身份被引入之后。
protected void Application_AuthorizeRequest(object sender, EventArgs e)
{
if (User.Identity.IsAuthenticated && Roles.Enabled)
{
Context.User = new CustomPrincipal((WindowsIdentity)User.Identity);
}
}
选项 2:覆盖 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;
}
}
然后将所有AuthorizeAttributes替换为自定义版本。
选项 1 全局处理所有内容,而选项 2 使用过滤器在更个性化的级别处理所有内容。
就我个人而言,我选择使用 global.asax 方法,这样我的自定义委托人就可以在全球范围内使用。这是解决我的问题的实际代码:
protected void Application_AuthorizeRequest(object source, EventArgs e)
{
if(User.Identity.IsAuthenticated && Roles.Enabled)
{
using (EntityContext db = new EntityContext ())
{
var user = db.Users.Include("Roles").SingleOrDefault(u => u.ADName.Equals(User.Identity.Name));
if (user == null)
return;
PcsPrincipal principal = new PcsPrincipal((WindowsIdentity)User.Identity, user);
Context.User = principal;
}
}
}