问题
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