【问题标题】:Authorize attribute not working with Windows Authentication application授权属性不适用于 Windows 身份验证应用程序
【发布时间】:2013-11-29 10:32:34
【问题描述】:

我有一个 MVC4 应用程序,我使用自定义角色提供程序为我的用户分配了角色,这样当我根据我的 User 表检查 User.IsInRole 时,它​​会确定在我的 _Layout.cshtml 页面的屏幕上显示哪些链接等。这在“布局”页面上有效,因为出现了正确的链接。

但是,当我使用

保护我的管理控制器时
[Authorize(Roles = "Admin")]

我从未设置为对象错误实例的对象中获取以下堆栈跟踪:

[NullReferenceException: Object reference not set to an instance of an object.]
System.Web.Mvc.AuthorizeAttribute.AuthorizeCore(HttpContextBase httpContext) +39
System.Web.Mvc.AuthorizeAttribute.OnAuthorization(AuthorizationContext filterContext) +159
System.Web.Mvc.ControllerActionInvoker.InvokeAuthorizationFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor) +96
System.Web.Mvc.Async.<>c__DisplayClass25.<BeginInvokeAction>b__1e(AsyncCallback asyncCallback, Object asyncState) +446
System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +130
System.Web.Mvc.Async.AsyncControllerActionInvoker.BeginInvokeAction(ControllerContext controllerContext, String actionName, AsyncCallback callback, Object state) +302
System.Web.Mvc.<>c__DisplayClass1d.<BeginExecuteCore>b__17(AsyncCallback asyncCallback, Object asyncState) +30
System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +130
System.Web.Mvc.Controller.BeginExecuteCore(AsyncCallback callback, Object state) +382
System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +130
System.Web.Mvc.Controller.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +317
System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state) +15
System.Web.Mvc.<>c__DisplayClass8.<BeginProcessRequest>b__2(AsyncCallback asyncCallback, Object asyncState) +71
System.Web.Mvc.Async.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout) +130
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +249
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +50
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +16
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +301
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

这个过滤器上下文到底是什么?当我使用 ADFS 或基于表单的身份验证时,这无需任何进一步配置即可工作,但是当使用基于 Windows 的身份验证时,我必须执行以下操作才能使 IsInRole 方法正常工作:

this.UserName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;

if (this.UserName.Contains("\\"))
{
  string[] stringArray = this.UserName.Split(new Char[] { '\\' });
  this.UserName = stringArray[1];

  MyUser identity = userRepository.Get(u => u.Username == this.UserName).FirstOrDefault();
  HttpContext.Current.User = identity;
}

我是否需要适当配置一些其他 HttpContext 以使 Authorize 属性以与 IsInRole 方法相同的方式工作?

【问题讨论】:

  • 谁能帮我解决这个问题? 50 点赏金现在可用,谢谢
  • 你能在得到 this.UserName 之前设置一个断点吗?我猜 GetCurrent() 返回一个空值。 FilterContext 将为您提供编写过滤器所需的一切,其中包括 httpcontext 和路由字典。查看msdn.microsoft.com/en-us/library/dd381609(v=vs.100).aspx 了解不同的过滤器上下文。
  • GetCurrent 正在返回用户名,我能够正确获取用户名,但是从这里授权上下文和当前用户上下文没有像 ADFS 和 Forms 中那样设置,所有需要的是要获得我可以在这里做的用户名,我想我错过了一步

标签: asp.net-mvc-4 windows-authentication roleprovider action-filter


【解决方案1】:

在表单的情况下,它可以是任何东西,但是实现用户名密码表单并在用户表中通过用户名查找是很常见的,根据提供的代码,看起来存储库只需要一个用户名,它只是原来 windows.identity.name 返回域\用户。这就是需要额外的努力来拆分域、用户的地方。下面的例子:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MvcApplication6
{
    public class DemoAuthAttribute : AuthorizeAttribute
    {
        // create a file like auth.cs in the mvc project 
        // called 
        //    [DemoAuth("BAR")]
        // as an attibute on a controller method

    private string _role;

    public DemoAuthAttribute(string role)
    {
        _role = role; // should be exapanded to handle more than one
    }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        return httpContext.Request.IsAuthenticated &&  _role == "FOO";
        // lookup the current user in database does the user have role as specificed by the attribute?
        // if yes sucess if not fail.
    }
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        if (filterContext == null)
        {
            throw new ArgumentNullException("filterContext");
        }

        if (AuthorizeCore(filterContext.HttpContext))
        {
            // your custom logic here
            string text = string.Format("<u><h5>Auth successfull.....</h5></u></br>");
            filterContext.HttpContext.Response.Write(text);
        }
        else
        {
            // RedirectResult, etc.
            string text = string.Format("<u><h5>Auth unsuccessfull.....</h5></u></br>");
            filterContext.HttpContext.Response.Write(text);
        }
    }

}

}

【讨论】:

  • 我只获得了用户名并拆分了域部分,以便我只获得用户名,这适用于 .IsInRole 方法,但不适用于 Authorize 方法。我认为这与没有设置授权上下文有关,我想知道如何做到这一点,以便当前用户以与通过 ADFS 和表单进行身份验证时相同的方式与自定义角色提供程序相关联
  • 好的,我明白了。是您编写的自定义提供程序还是第三方/开源?
  • 它是我写的,适用于 ADFS 和 Forms 身份验证的用户我只是不确定如何根据我设置 HttpContext.Current.User 的方式为用户获取授权上下文适用于 User.IsInRole
  • 通过表单和 ADFS 身份验证,将用户详细信息输入到登录页面,然后针对数据库中名为 MyUser 的表中的现有用户对这些详细信息进行身份验证。该用户有一个角色标识,该角色标识与一个名为 Role 的表中的角色相关联,该表用于我的角色提供者。我需要验证用户是否在数据库中找到,然后进行某种身份验证,以便为他们分配一个安全上下文,可以使用 [Authorize(Roles = "blah,blah,blah")检查他们的角色>
  • HttpContext.Current.User = new System.Security.Principal.GenericPrincpa(id, 角色);其中角色是角色的字符串列表
猜你喜欢
  • 2019-10-21
  • 1970-01-01
  • 1970-01-01
  • 2017-05-28
  • 1970-01-01
  • 1970-01-01
  • 2010-11-05
  • 1970-01-01
  • 2015-05-12
相关资源
最近更新 更多