JNY*_*ger 5 c# asp.net windows-authentication asp.net-mvc-5 asp.net-identity
我已经阅读了很多关于这个主题的问题和答案,但没有一个能帮助我解决这个问题.
我遇到的问题是,HttpContext.Current.User或者只是User属性是类型RolePrincipal而不是我的自定义主体.
这是一个使用Windows身份验证(仅限Intranet的应用程序)的MVC 5 Web应用程序.我的自定义主体是一个子类,WindowsPrincipal我确实实现了自己的RoleProvider用于Authorize属性标记.
当我尝试通过IPrincipal在当前的HttpContext上将它转换为我的自定义主体来使用主体时,我得到一个错误,指出它的类型为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);
}
}
Run Code Online (Sandbox Code Playgroud)
当我在该方法中放置一个断点时,似乎永远不会被调用,这可以解释为什么它没有被设置为我的自定义主体.
我已经审核了以下QA,但他们无法解决此问题:
_application变量似乎在MVC5中无效.如果没有设置Principal,我做错了什么?如果需要发布更多代码,请告诉我.
编辑: 在WindowsAuthentication.OnAuthenticate事件中将HttpContext.Current.User设置为我的自定义主体不能解决此问题.使用该方法表现出完全相同的行为.
在不断研究这个问题后,我终于通过另一个SO问题找到了答案,使我的问题有点重复: MVC3 Windows Authentication override User.Identity
下面是 @Toby Jones 发布的答案(作为对他原始问题的编辑),这导致我解决了我的问题,但他的答案实际上是 @Erik Funkenbusch 和 @Darin Dimitrov 发布的两个答案的汇总。答案经过编辑以修复一些语法并删除一些多余的信息。
选项 1:覆盖 Global.asax 中的授权请求
不应使用 Application_AuthenticateRequest 事件,因为 (HttpContext.Current.User即使 Windows 身份验证已打开,该事件仍为 null)用户尚未在 Windows 身份验证过程中填充,因此我无法使用任何内容来获取用户信息。
Application_AuthorizeRequest是链中的下一个,在引入 WindowsIdentity 之后发生。
protected void Application_AuthorizeRequest(object sender, EventArgs e)
{
if (User.Identity.IsAuthenticated && Roles.Enabled)
{
Context.User = new CustomPrincipal((WindowsIdentity)User.Identity);
}
}
Run Code Online (Sandbox Code Playgroud)
选项 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;
}
}
Run Code Online (Sandbox Code Playgroud)
然后将所有 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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1317 次 |
| 最近记录: |