如何绕过System.Web.Http.AuthorizeAttribute.IsAuthorized

时间:2014-05-20 08:04:17

标签: c# ajax asp.net-mvc cors

在我们的服务器中,CORS已经启用,因此像ajax这样的脚本可以在我们的API中进行通信。但这仅对没有SecureAttribute

的API有效

这个工作正常:

[CorsPreflightEnabled]
public class DevicesController : ApiController
{
    [CorsEnabled]
    [HttpPost]
    public bool Register(DTO::ClientInfo info)

虽然这个总是被拒绝:

[CorsPreflightEnabled]
[Http::Secure]
public class UserController : ApiController
{
    [CorsEnabled]
    [HttpPost]
    public bool AddClaims(Domain::DTO.UserClaim claim)  

这是SecureAttribute的代码:

public class SecureAttribute : AuthorizeAttribute
{
    protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        var calltoken = HttpContext.Current.Request.Headers["Device"] ?? "";
        var token = JsonConvert.DeserializeObject<DeviceCallToken>(calltoken) ?? new DeviceCallToken();

        var cachetoken = new ClientAuthentication().VerifyDevice(token);

        if (cachetoken != null)
        {
            // if a cachetoken was successfully extracted from our records,
            // then store the information into the principal for possible reuse

            var principal = AppPrincipal.Current;
            var identity = principal.Identity as AppIdentity;

            identity.ServiceHeader.SessionId = token.SessionId;
            identity.ServiceHeader.ClientKey = cachetoken.ClientKey;
            identity.ServiceHeader.DeviceCode = cachetoken.DeviceCode;
            identity.ServiceHeader.Merchant = cachetoken.Merchant;

            Thread.CurrentPrincipal = principal;
            HttpContext.Current.User = principal;
        }

        return cachetoken != null && !string.IsNullOrWhiteSpace(cachetoken.Salt);
    }
}  

当我使用ajax调用API时,Method设置为OPTIONScalltoken的值始终为null

现在我的问题是,当方法为OPTIONS时,如何绕过检查安全性?

我发现,如果我尝试通过断点在calltoken中放置值,则最后一次会再次调用IsAuthorized,并且Device标头现在具有值。

我真的希望我能很好地解释自己。如果没有,我可能需要显示一些图像。

编辑:工作代码

public class SecureAttribute : AuthorizeAttribute
{
    protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        var calltoken = HttpContext.Current.Request.Headers["Device"] ?? "";
        var token = JsonConvert.DeserializeObject<DeviceCallToken>(calltoken) ?? new DeviceCallToken();

        var cachetoken = new ClientAuthentication().VerifyDevice(token);

        if (cachetoken != null)
        {
            // if a cachetoken was successfully extracted from our records,
            // then store the information into the principal for possible reuse

            var principal = AppPrincipal.Current;
            var identity = principal.Identity as AppIdentity;

            identity.ServiceHeader.SessionId = token.SessionId;
            identity.ServiceHeader.ClientKey = cachetoken.ClientKey;
            identity.ServiceHeader.DeviceCode = cachetoken.DeviceCode;
            identity.ServiceHeader.Merchant = cachetoken.Merchant;

            Thread.CurrentPrincipal = principal;
            HttpContext.Current.User = principal;
        }
        else
        {
            var originalRequest = actionContext.Request;
            var isCorsRequest = originalRequest.Headers.Contains("Origin");

            if (originalRequest.Method == HttpMethod.Options && isCorsRequest)
            {
                // Allow to penetrate
                return true;
            }
        }

        return cachetoken != null && !string.IsNullOrWhiteSpace(cachetoken.Salt);
    }
}

1 个答案:

答案 0 :(得分:0)

没有办法绕过授权属性,如果可能的话,这将是非常不安全的。您的选择是:

  1. 从需要调用的方法中删除属性。
  2. 在ajax调用中传递正确的安全标头。
  3. 修改SecureAttribute类以允许OPTIONS方法(但这听起来也很不安全)
  4. 为没有附加属性的ajax创建新方法。
  5. 我建议选项2。