gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 15:50:55 25 4
gpt4 key购买 nike

我继承了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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com