WEB API - Authorize at controller or action level (no authentication)

不打扰是莪最后的温柔 提交于 2019-12-21 04:09:09

问题


I have an existing API that has No Authentication. It`s a public Web API which several clients use by making simple requests.

Now, there is the need to authorize access to a certain method.

Is there any way to do this, keeping the rest of the controllers and respective methods "open" for the clients that already use this Web API?

How can i identify if the request has permissions to access this "protected" method?


回答1:


What you'll need to do is add an [Authorize] attribute to the methods you want to protect optionally using the overload that accepts one or more role names that the calling user must be in.

Then what you'll have to implement is a way to ensure that authentication data of the caller is transformed into a Principal object. Setting the Principal is generally something you don't do yourself, but instead have the framework do for you.

If you do want to provide your own interface, you can using an authentication filter implementing the System.Web.Http.Filters.IAuthenticationFilter interface.

So what you'll get is this:

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

And then implement the MyAuthentication attribute. Below is an example, the important thing is that you use the context of the incoming request and end up setting the context.Principal property with a new 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
}

I hope this helps you get on the right track. For more information check this post: http://www.asp.net/web-api/overview/security/authentication-filters




回答2:


You can use [Authorize] attribute at particular API method as well as at controller level. In case you put the [Authorize] attribute at controller level then you can use [AllowAnonymous] attribute for those API method which you want to access without authentication.




回答3:


By default, authorization is globally disabled on application. You can force your controller to only allow authorized requests by adding the action filter [Authorize].

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

You can also force only certain methods be authorized:

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

Or just disable authorization on some methods inside a controller that requires authorization:

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

You can also set who's allowed to access your method by using:

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

Or by Rules using:

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

Or even build a more complex Authorize attribute like in this answer (Based on Claims): Authorization Attribute by Claims




回答4:


We solved it using [AllowAnonymous] on the method who we didn't wanted to being Authenticated but Authorizated, overriding the Authorization.



来源:https://stackoverflow.com/questions/38751104/web-api-authorize-at-controller-or-action-level-no-authentication

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!