Mvc应用程序,Windows身份验证,授权,可见性

时间:2014-10-28 13:54:15

标签: asp.net-mvc razor asp.net-mvc-5

我有一个Windows身份验证MVC应用程序需要用户名进行查找以确定链接是否可见并设置授权。注意:我也可以使用角色进行可见性/授权。

我需要用户名,所以我目前正在使用OnAuthentification(不确定这是不是正确的地方)。我正在拼接用户名以将其放在主页上并说欢迎,用户。 (演示目的)

[Authorize]
public abstract class ApplicationController : Controller
{
    public static bool IsApprover;

    protected override void OnAuthentication(AuthenticationContext filterContext)
    {
        base.OnAuthentication(filterContext);

        if (filterContext.RequestContext.HttpContext.User.Identity.IsAuthenticated == true)
        {
            string userName = User.Identity.Name.Remove(0, 16).Replace('.', ' ').ToLower();
            HttpContext.Application["UserName"] = TitleCase(userName, "Nothing");

            //Initialize Values
            HttpContext.Application["IsApprover"] = false; //used for link visibility
            IsApprover = false; //used for Authorization

            //do db lookup and set IsApprover values
        }
    }
}

所以,我设置了上面的值。我不包括实体框架代码只是为了简短。以上工作正常,每个控制器都继承自ApplicationController。

我也有

public class CustomAuthorizationValue : AuthorizeAttribute
{
    private bool localIsAllowed;

    public CustomAuthorizationValue(bool isAllowed)
    {
        localIsAllowed = isAllowed;
    }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        if (httpContext.Request.IsLocal)
        {
            var authorized = base.AuthorizeCore(httpContext);
            if (!authorized)
            {
                // The user is not authorized => no need to go any further
                return false;
            }

            return localIsAllowed;
        }

        return false;
    }
}

对于授权,我使用:

    [CustomAuthorizationValue(IsApprover)]
    public ActionResult Approve()
    {
        //code
    }

对于Razor中的可见性,我使用

                    @if((bool)@HttpContext.Current.Application["IsApprover"] == true)
                    {
                        <li><a href="@Url.Action("Approve", "Approve")">Approve (@HttpContext.Current.Application["ApproveCount"])</a></li>
                    }

这很好但我有2个不同的变量可供使用, 一个用于可见性(HttpContext.Current.Application [&#34; IsApprover&#34;]) 和 一个用于授权(IsApprover)。

有更优雅的解决方案吗?

是否有其他地方可以放置代码而不是覆盖void OnAuthentication?

有没有办法可以设置1个变量用于可见性和授权而不是2?

这是最好的做法还是我离开了?

1 个答案:

答案 0 :(得分:1)

  

以上工作正常,每个控制器都继承自   ApplicationController中。

Hmmmm。您正在将用户特定信息信息存储在错误的范围内:

HttpContext.Application["UserName"] = TitleCase(userName, "Nothing");
HttpContext.Application["IsApprover"] = false;

在ASP.NET中,应用程序范围由您网站的所有用户共享。所以这里有一个并发问题。

您应该使用HTTP Context范围:

HttpContext.Items["UserName"] = TitleCase(userName, "Nothing");
HttpContext.Items["IsApprover"] = false;
  

有更优雅的解决方案吗?

您可以使用视图模型:

public class MyViewModel
{
    public string UserName { get; set; }
    public bool IsApprover { get; set; }
}

然后有几种扩展方法可以更轻松地工作:

public static class HttpContextExtensions
{
    private const string MyViewModelKey = "__MyViewModel__";

    public static MyViewModel GetMyViewModel(this HttpContextBase context)
    {
        return (MyViewModel)context.Items[MyViewModelKey];
    }

    public static void SetMyViewModel(this HttpContextBase context, MyViewModel model)
    {
        context.Items[MyViewModelKey] = model;
    }
}

然后使用这些扩展方法:

if (filterContext.RequestContext.HttpContext.User.Identity.IsAuthenticated)
{
    string userName = User.Identity.Name.Remove(0, 16).Replace('.', ' ').ToLower();
    bool isApprover = ... do db lookup and set IsApprover value

    var model = new MyViewModel
    {
        UserName = TitleCase(userName, "Nothing"),
        IsApprover = isApprover,
    }
    this.HttpContext.SetMyViewModel(model);
}

并在您看来:

@if(HttpContext.GetMyViewModel().IsApprover)
{
    <li>
        <a href="@Url.Action("Approve", "Approve")">
            Approve (@HttpContext.Current.Application["ApproveCount"])
        </a>
    </li>
}

注意:在此锚文本中,您似乎再次使用应用程序范围来存储用户特定信息,例如我们之前讨论过的ApproveCount

  

这是最好的做法还是我离开了?

好吧,我可能会使用基于声明的身份验证,并将此信息(IsApprover,...)存储为当前用户的声明。