WEB API - 在控制器或操作级别授权(无身份验证)

时间:2016-08-03 18:27:08

标签: c# authentication asp.net-web-api authorization

我有一个没有身份验证的现有API。它是一个公共Web API,几个客户通过提出简单的请求来使用它。

现在,需要授权访问某种方法。

有没有办法做到这一点,为已经使用此Web API的客户端保持其他控制器和各自的方法“打开”?

如何识别请求是否有权访问此“受保护”方法?

5 个答案:

答案 0 :(得分:19)

您需要做的是为您要保护的方法添加[Authorize]属性,可选地使用接受调用用户必须接受的一个或多个角色名称的重载。

然后,您必须实现的是确保调用者的身份验证数据转换为Principal对象的方法。设置Principal通常是你自己不做的事情,而是让框架适合你。

如果您确实想提供自己的界面,可以使用实现System.Web.Http.Filters.IAuthenticationFilter界面的身份验证过滤器。

所以你会得到的是:

[MyAuthentication]
[Authorize]
public SomeClass MyProtectedMethod() {
    return new SomeClass();
}

然后实现MyAuthentication属性。下面是一个示例,重要的是您使用传入请求的上下文并最终使用新的Principal设置context.Principal属性

public class MyAuthentication : ActionFilterAttribute, System.Web.Http.Filters.IAuthenticationFilter {

    public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
    {
        // 1. Look for credentials in the request.
        HttpRequestMessage request = context.Request;
        AuthenticationHeaderValue authorization = request.Headers.Authorization;

        // 2. If there are no credentials, do nothing.
        if (authorization == null)
        {
            return;
        }

        // 3. If there are credentials but the filter does not recognize the 
        //    authentication scheme, do nothing.
        if (authorization.Scheme != "Basic")
        {
            return;
        }

        // 4. If there are credentials that the filter understands, try to validate them.
        // 5. If the credentials are bad, set the error result.
        if (String.IsNullOrEmpty(authorization.Parameter))
        {
            context.ErrorResult = new AuthenticationFailureResult("Missing credentials", request);
            return;
        }

        Tuple<string, string> userNameAndPasword = ExtractUserNameAndPassword(authorization.Parameter);
        if (userNameAndPasword == null)
        {
            context.ErrorResult = new AuthenticationFailureResult("Invalid credentials", request);
        }

        string userName = userNameAndPasword.Item1;
        string password = userNameAndPasword.Item2;

        IPrincipal principal = await AuthenticateAsync(userName, password, cancellationToken);
        if (principal == null)
        {
            context.ErrorResult = new AuthenticationFailureResult("Invalid username or password", request);
        }

        // 6. If the credentials are valid, set principal.
        else
        {
            context.Principal = principal;
        }

    }


    ... other interface methods here
}

我希望这可以帮助你走上正确的轨道。有关更多信息,请查看此帖子: http://www.asp.net/web-api/overview/security/authentication-filters

答案 1 :(得分:9)

您可以在特定的API方法和控制器级别使用private bool RunVisualCheck(string screen, string resultsPath, string baseline = "baseline.jpeg", string screenshot = "screenshot.jpeg") { GetScreenshot(resultsPath + screenshot); var baselineImage = Image.FromFile(resultsPath + baseline); var actualImage = Image.FromFile(resultsPath + screenshot); Image diffImage; int ignoreTop = 64; var compareArea = new List<ToleranceRectangle> { new ToleranceRectangle() { Rectangle = new Rectangle(0,ignoreTop,baselineImage.Width, baselineImage.Height - ignoreTop), Difference = new ColorDifference() } }; bool goodCompare = ImageComparer.Compare(actualImage, baselineImage, compareArea, out diffImage); if (!goodCompare) { diffImage.Save(resultsPath + "diffImage.jpeg"); } return goodCompare; } private void GetScreenshot(string pathFile) { System.Threading.Thread.Sleep(2000); // Temp fix to wait until page loads var srcFiler = ((ITakesScreenshot)mobileDriver).GetScreenshot(); srcFiler.SaveAsFile(pathFile, ImageFormat.Jpeg); } 属性。如果您将[Authorize]属性放在控制器级别,那么您可以使用[Authorize]属性来获取要在不进行身份验证的情况下访问的API方法。

答案 2 :(得分:5)

默认情况下,在应用程序上全局禁用授权。您可以通过添加操作过滤器[授权]来强制您的控制器仅允许授权请求。

[Authorize]  // This will enforce all methods inside should be authorized
public class AuthorizeController : ApiController
{
      //this method will only be called if user is authorized
      public IHttpActionResult GetList()
      {
         return Ok();
      }
}

您也可以强制仅授权某些方法:

public class AuthorizeController : ApiController
{
      [Authorize] //this method will only be called if user is authorized
      public IHttpActionResult GetList()
      {
         return Ok();
      }

      // This method can still be called even if user is not authorized
      public IHttpActionResult GetListUnauthorized()
      {
         return Ok();
      }
}

或者只是禁用需要授权的控制器内某些方法的授权:

[Authorize]
public class AuthorizeController : ApiController
{
      //this method will only be called if user is authorized
      public IHttpActionResult GetList()
      {
         return Ok();
      }

      [AllowAnonymous]// This method can be called even if user is not authorized due the AllowAnonymous attribute
      public IHttpActionResult GetListUnauthorized()
      {
         return Ok();
      }
}

您还可以使用以下方式设置允许访问您方法的人员:

[Authorize(Users="Joey,Billy")]

或使用规则:

[Authorize(Roles="Administrator,Manager")]

甚至可以构建一个更复杂的Authorize属性,就像在这个答案中一样(基于声明):Authorization Attribute by Claims

答案 3 :(得分:0)

我们使用[AllowAnonymous]在我们不希望通过身份验证但经过授权的方法上进行了解决,从而覆盖了授权。

答案 4 :(得分:0)

执行流程将进入方法级别,然后进入控制器级别。因此,如果您提及“ AllowAnonymous”,则将执行不带授权检查的内容。