web-dev-qa-db-fra.com

API WEB - Autoriser au niveau du contrôleur ou de l'action (pas d'authentification)

J'ai une API existante qui n'a aucune authentification. C'est une API Web publique que plusieurs clients utilisent en faisant de simples requêtes.

Maintenant, il est nécessaire d'autoriser l'accès à une certaine méthode.

Existe-t-il un moyen de garder les autres contrôleurs et méthodes respectives "ouverts" pour les clients qui utilisent déjà cette API Web?

Comment puis-je identifier si la requête est autorisée à accéder à cette méthode "protégée"?

8
JCruz

Vous devez ajouter un attribut [Authorize] aux méthodes que vous souhaitez protéger éventuellement à l'aide de la surcharge qui accepte un ou plusieurs noms de rôle dans lesquels l'utilisateur appelant doit se trouver.

Ensuite, vous devrez implémenter un moyen de vous assurer que les données d’authentification de l’appelant sont transformées en objet Principal. Définir le principal est généralement quelque chose que vous ne faites pas vous-même, mais que le cadre fait pour vous.

Si vous souhaitez fournir votre propre interface, vous pouvez utiliser un filtre d'authentification implémentant l'interface System.Web.Http.Filters.IAuthenticationFilter

Donc, ce que vous obtiendrez est ceci:

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

Et puis implémentez l'attribut MyAuthentication. Ci-dessous, un exemple, l’important est que vous utilisiez le contexte de la demande entrante et que vous finissiez par définir la propriété context.Principal avec un nouveau 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
}

J'espère que cela vous aide à aller sur la bonne voie. Pour plus d'informations, consultez cet article: http://www.asp.net/web-api/overview/security/authentication-filters

17
Robba

Vous pouvez utiliser l'attribut [Authorize] avec une méthode d'API particulière ainsi qu'au niveau du contrôleur. Si vous placez l'attribut [Authorize] au niveau du contrôleur, vous pouvez utiliser l'attribut [AllowAnonymous] pour les méthodes de l'API auxquelles vous souhaitez accéder sans authentification.

9
Rahul

Par défaut, l'autorisation est globalement désactivée sur l'application. Vous pouvez forcer votre contrôleur à autoriser uniquement les requêtes autorisées en ajoutant le filtre d'action [Autoriser].

[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();
      }
}

Vous pouvez également forcer que certaines méthodes soient autorisées:

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();
      }
}

Ou bien, désactivez simplement l'autorisation sur certaines méthodes d'un contrôleur nécessitant une autorisation:

[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();
      }
}

Vous pouvez également définir qui est autorisé à accéder à votre méthode en utilisant:

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

Ou par des règles utilisant:

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

Ou même créer un attribut Authorize plus complexe, comme dans cette réponse (Based on Claims): Attribut d'autorisation par revendications

3
Rafael A. M. S.

Nous l'avons résolu en utilisant [AllowAnonymous] sur la méthode pour laquelle nous ne voulions pas être authentifiés mais autorisés, en ignorant l'autorisation.

0
Ruben Lopez