asp.net - 如何自定义 ASP.NET Web API AuthorizeAttribute 以满足异常需求

标签 asp.net asp.net-mvc security asp.net-web-api

我继承了System.Web.Http.AuthorizeAttribute来创建自定义授权/身份验证例程,以满足使用 ASP.NET MVC 4 开发的 Web 应用程序的一些不寻常的要求。这增加了安全性用于从 Web 客户端进行 Ajax 调用的 Web API。要求是:

  1. 用户每次执行交易时都必须登录以进行验证 在有人到达工作站后,其他人还没有走到工作站 登录并离开。
  2. 无法在程序时将角色分配给 Web 服务方法。 它们必须在运行时分配,以便管理员可以 配置这个。该信息存储在系统数据库中。

网络客户端是 single page application (SPA)因此,典型的表单例份验证效果不太好,但我正在尝试尽可能多地重用 ASP.NET 安全框架来满足要求。定制的 AuthorizeAttribute 非常适合确定与 Web 服务方法关联的角色的要求 2。我接受三个参数:应用程序名称、资源名称和操作,以确定哪些角色与方法关联。

public class DoThisController : ApiController
{
    [Authorize(Application = "MyApp", Resource = "DoThis", Operation = "read")]
    public string GetData()
    {
        return "We did this.";
    }
}

我重写OnAuthorization方法来获取角色并对用户进行身份验证。由于每笔交易都必须对用户进行身份验证,因此我通过在同一步骤中执行身份验证和授权来减少来回的麻烦。我使用基本身份验证从 Web 客户端获取用户凭据,该身份验证在 HTTP header 中传递加密凭据。所以我的 OnAuthorization 方法如下所示:

public override void OnAuthorization(HttpActionContext actionContext)
{

     string username;
     string password;
     if (GetUserNameAndPassword(actionContext, out username, out password))
     {
         if (Membership.ValidateUser(username, password))
         {
             FormsAuthentication.SetAuthCookie(username, false);
             base.Roles = GetResourceOperationRoles();
         }
         else
         {
             FormsAuthentication.SignOut();
             base.Roles = "";
         }
     }
     else
     {
         FormsAuthentication.SignOut();
         base.Roles = "";
     }
     base.OnAuthorization(actionContext);
 }

GetUserNameAndPassword 从 HTTP header 检索凭据。然后,我使用 Membership.ValidateUser 来验证凭据。我插入了一个自定义成员(member)资格提供程序和角色提供程序来访问自定义数据库。如果用户通过身份验证,我就会检索资源和操作的角色。从那里我使用基本的 OnAuthorization 来完成授权过程。这就是它崩溃的地方。

如果用户通过身份验证,我将使用标准表单例份验证方法来登录用户 (FormsAuthentication.SetAuthCookie),如果失败,我将其注销 (FormsAuthentication.SignOut)。但问题似乎是基础 OnAuthorization 类无法访问已更新的 Principal ,以便将 IsAuthenticated 设置为正确的值。总是落后一步。我的猜测是,它正在使用一些缓存值,这些值在与 Web 客户端进行往返之前不会更新。

因此,所有这些都引出了我的具体问题,即是否有另一种方法可以在不使用 cookie 的情况下将 IsAuthenticated 设置为当前 Principal 的正确值?在我看来,cookie 并不真正适用于我每次都必须进行身份验证的特定场景。我知道 IsAuthenticated 未设置为正确值的原因是我还将 HandleUnauthorizedRequest 方法重写为:

 protected override void HandleUnauthorizedRequest(HttpActionContext filterContext)
 {
     if (((System.Web.HttpContext.Current.User).Identity).IsAuthenticated)
     {
         filterContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden);
     }
     else
     {
         base.HandleUnauthorizedRequest(filterContext);
     }
 }

如果失败是因为授权而不是身份验证,这允许我向 Web 客户端返回 Forbidden 状态代码,并且它可以做出相应的响应。

那么在这种情况下,为当前原则设置IsAuthenticated的正确方法是什么?

最佳答案

适合我的场景的最佳解决方案似乎是完全绕过基本的OnAuthorization。由于我每次都必须进行身份验证,因此 cookie 和缓存的原理没有多大用处。所以这是我想出的解决方案:

public override void OnAuthorization(HttpActionContext actionContext)
{
    string username;
    string password;

    if (GetUserNameAndPassword(actionContext, out username, out password))
    {
        if (Membership.ValidateUser(username, password))
        {
            if (!isUserAuthorized(username))
                actionContext.Response = 
                    new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden);
        }
        else
        {
            actionContext.Response = 
                new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized);
        }
    }
    else
    {
        actionContext.Response = 
            new HttpResponseMessage(System.Net.HttpStatusCode.BadRequest);
    }
}

我开发了自己的方法来验证名为 isUserAuthorized 的角色,并且我不再使用基本 OnAuthorization ,因为它会检查当前的原则> 查看它是否经过身份验证IsAuthenticated 只允许获取,所以我不确定如何设置它,而且我似乎不需要当前的原则。测试了一下,效果很好。

如果有人有更好的解决方案或者可以看到这个问题,仍然感兴趣。

关于asp.net - 如何自定义 ASP.NET Web API AuthorizeAttribute 以满足异常需求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12629530/

相关文章:

asp.net-mvc - MVC 可以在 3.5 IIS6 上运行吗?非 SP1

c# - 如何在 MVC 调用返回模型之前显示加载图像?

security - Tomcat 7 - 保护 webapps 文件夹下的文件夹

c# - 这两种返回 JSON 对象的方式有什么区别?

Chrome 中的 ASP.NET 边距问题

c# - asp.net 中的转发器项目命令

c# - 基于 HttpModule 的安全性是否足以保证 asp.net 应用程序的安全性?

asp.net - DropDownList 中的 ListItems 属性在回发时丢失?

JavaScript 加载 MVC ASP .NET MVC

security - 用于宏分发的签名证书