问题
All, I am having an issue with implementing authorization on one of my web api controller action. This is a .net framework 4.6.1 app and an MVC 5 application makes calls into this web api. We implement windows authentication both on the client(MVC5) and web api. Both client and server use the same service account(The account name the app pool runs under) and these are on separate servers.
Users of the client app is authenticated using AD account before they get to the MVC app section that makes calls to the web api.
I added the [Authorize] attribute to the api controller action, but the request is returned with 401 unauthorized status.
So I added a custom authorization logic, that compares the incoming user name(service account) from the client app, against whats configured in the api's config file(in each environment) and accept/deny request.But the User (please see code below) on the line actionContext.RequestContext.Principal.Identity.Name is an empty string.
I tried enabling asp.net impersonation on the MVC5 apps configuration on IIS, but still no luck
Has anyone done something similar?
Custom Authorize Logic
public class CustomAuthorize : AuthorizeAttribute
{
protected override bool IsAuthorized(HttpActionContext actionContext)
{
var isAuthorized = false;
var environment = ConfigurationManager.AppSettings["Env"];
var configuredAccountName = ConfigurationManager.AppSettings["appserviceaccountname"];
string incomingServiceAccountName = null;
try
{
if(actionContext.RequestContext.Principal != null && actionContext.RequestContext.Principal.Identity != null)
{
incomingServiceAccountName = actionContext.RequestContext.Principal.Identity.Name;
if(!string.IsNullOrWhiteSpace(incomingServiceAccountName))
{
logger.Error(string.Format("Service account name passed in is : {0}", incomingServiceAccountName));
switch (environment)
{
case "Dev":
if(incomingServiceAccountName.ToLower().Equals(configuredAccountName.ToLower()))
{
isAuthorized = true;
}
break;
default:
break;
}
}
}
else if(actionContext.RequestContext.Principal == null)
{
logger.Error("Principal is null");
}
else
{
logger.Error("Identity is null");
}
}
catch (Exception ex)
{
logger.Error(string.Format("Error occurred while authorizing the user inside the class CustomAuthorize and method IsAuthorized with {0}", ex.Message));
isAuthorized = false;
}
return isAuthorized;
}
}
MVC5 Client code that makes the api call
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://webapiurl");
var jsonString = new StringContent(JsonConvert.SerializeObject(search), Encoding.UTF8, "application/json");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.PostAsync(client.BaseAddress, jsonString).Result;
if (response.IsSuccessStatusCode)
{
var result = response.Content.ReadAsStringAsync().Result;
mydate = JsonConvert.DeserializeObject<List<mydate>>(result);
}
}
}
回答1:
Have you set Windows Auth in IIS on on the server? IIS Windows Auth providers also must be present (Negotiate, NTLM) to allow IIS to try to authenticate with AD.
来源:https://stackoverflow.com/questions/48489205/web-api-authorization-by-capturing-clients-service-account-name