所以我创建了一个自定义授权属性,我在一些地方使用了这个属性,该属性派生自一个派生自AuthorizeAttribute
的抽象基类:
CustomAuthorizeAttributeBase.cs
public abstract class CustomAuthorizeAttributeBase : AuthorizeAttribute
{
public abstract string GetUsers();
public abstract string GetRoles();
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (filterContext.IsChildAction)
{
return;
}
filterContext.Result =
new RedirectToRouteResult(new RouteValueDictionary
{
{"controller", "NotAuthorized"},
{"action", "Index"},
});
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (GetUsers().IndexOf(httpContext.User.Identity.Name, StringComparison.CurrentCultureIgnoreCase) >= 0 ||
GetRoles().Split(',').Any(s => httpContext.User.IsInRole(s)))
{
return true;
}
return false;
}
}
AreaLevelReadonly.cs
public class AreaLevelReadOnly : CustomAuthorizeAttributeBase
{
public override string GetUsers()
{
return ConfigurationManager.AppSettings["AreaReadonlyUsers"];
}
public override string GetRoles()
{
return ConfigurationManager.AppSettings["AreaReadonlyRoles"];
}
}
我还有一些非常简单的代码可以让我获得当前登录的用户:
UserIdentity.cs
public class UserIdentity : IUserIdentity
{
public string GetUserName()
{
return HttpContext.Current.User.Identity.Name.Split('\\')[1];
}
}
但是,当我将AreaLevelReadonly属性添加到控制器时,getUserName失败并返回Name
为空的异常。在将authorize属性放在那里之前,我痛苦了大约一个小时,此时它神奇地开始再次工作。那么,在我的属性派生自authorizeattribute的实现级别上有什么不同之处并不会导致Name
被填充。
注意:该区域启用了Windows身份验证,代码可以运行,但我不明白为什么Readonly属性不足以触发HttpContext.Current.User.Identity.Name
的授权和填充。< / p>
编辑:工作:
[AreaLevelReadonly]
[Authorize]
public class DeleteAreaDataController : Controller {
//etc
var username = _userIdentity.GetUserName(HttpContext);
//etc
}
名称上的例外:
[AreaLevelReadonly]
public class DeleteAreaDataController : Controller {
//etc
var username = _userIdentity.GetUserName(HttpContext);
//etc
}
答案 0 :(得分:0)
更有可能的是,您在填充User.Identity.Name
之前就已经访问了Authorize
。通过包含标准User.Identity.Name
属性,您的代码只有在用户获得授权并且已填充User.Identity.Name
后才会运行。
修改强>
抱歉,我误解了试图调用GetUserAccount(HttpContext)
的代码在哪里运行。基于您在自定义属性中发生的信念,我建议您过早尝试访问它。但是,我现在看到你在你的控制器中调用它了(虽然对User.Identity.Name
中发生的事情的解释会有所帮助。)
无论如何,您的自定义属性显然会增加用户是否获得授权的额外条件。当您返回false时,没有用户。这不是用户登录的情况&#34;但不允许看到该页面。它是存在还是不存在。因此,用户根据您的自定义属性失败授权(Authorize
为空),但当您包含User.Identity.Name
(GetUserName
有值)时,已授权。< / p>
多长时间,当用户授权失败时,您的GetUserAccount
或User.Identity.Name
或任何代码都需要考虑。或者,如果用户不应该未通过授权,则您需要查看自定义属性无法正常工作的原因。但无论如何,您仍然应该将=VLOOKUP($A20;Employees!$A:$GE;COLUMN(C:C);FALSE)
视为空。
答案 1 :(得分:0)
在您检查用户是否通过身份验证之前,您的自定义属性可能正在读取User.Identity.Name
。
换句话说,在IsAuthorized()
中,在阅读User.Identity.Name
之前,您应该执行以下操作:
if (!user.Identity.IsAuthenticated)
{
// Your custom code...
return false;
}
您之所以需要这样做,是因为Windows身份验证(至少对于NTLM而言)是客户端和服务器之间的两步协商过程(请参见https://support.citrix.com/article/CTX221693)。将有2个请求-第一个没有名称,第二个带有名称。您可以自己进行测试-here提供了AuthorizeAttribute
的源代码。将其复制/粘贴到代码中,然后在IsAuthorized
中放置一个断点-您将看到该断点被击中两次。第一次,该名称为null,第二次,该名称设置为您的用户名。
因此,我认为解决方案是在方法开始时检查user.Identity.IsAuthenticated
,如果您需要运行自定义代码(如上所示),或者仅需要return false
,只需将上面的代码替换为base.IsAuthorized()
即可,