Метод CustomAuthorizationPolicy.Evaluate() никогда не срабатывает в wcf webhttpbinding
Я создаю сервис wcf, как вы можете видеть:
[OperationContract]
[PrincipalPermission(SecurityAction.Demand, Role = "Admin")]
[WebInvoke(Method = "GET", UriTemplate = "/Data/{data}")]
string GetData(string data);
Поэтому я создаю пользовательскую авторизацию, как вы можете видеть:
public class AuthorizationPolicy : IAuthorizationPolicy
{
string id = Guid.NewGuid().ToString();
public string Id
{
get { return this.id; }
}
public System.IdentityModel.Claims.ClaimSet Issuer
{
get { return System.IdentityModel.Claims.ClaimSet.System; }
}
// this method gets called after the authentication stage
public bool Evaluate(EvaluationContext evaluationContext, ref object state)
{
// get the authenticated client identity
IIdentity client = HttpContext.Current.User.Identity;
// set the custom principal
evaluationContext.Properties["Principal"] = new CustomPrincipal(client);
return true;
}
}
public class CustomPrincipal : IPrincipal
{
private IIdentity _identity;
public IIdentity Identity
{
get
{
return _identity;
}
}
public CustomPrincipal(IIdentity identity)
{
_identity = identity;
}
public bool IsInRole(string role)
{
//my code
return true;
// return Roles.IsUserInRole(role);
}
}
И аутентификация:
public class RestAuthorizationManager: ServiceAuthorizationManager
{
protected override bool CheckAccessCore(OperationContext operationContext)
{
//Extract the Authorization header, and parse out the credentials converting the Base64 string:
var authHeader = WebOperationContext.Current.IncomingRequest.Headers["Authorization"];
if ((authHeader != null) && (authHeader != string.Empty))
{
var svcCredentials = System.Text.ASCIIEncoding.ASCII
.GetString(Convert.FromBase64String(authHeader.Substring(6)))
.Split(':');
var user = new
{
Name = svcCredentials[0],
Password = svcCredentials[1]
};
if ((user.Name == "1" && user.Password == "1"))
{
//here i get the role of my user from the database
// return Admin role
//User is authrized and originating call will proceed
return true;
}
else
{
//not authorized
return false;
}
}
else
{
//No authorization header was provided, so challenge the client to provide before proceeding:
WebOperationContext.Current.OutgoingResponse.Headers.Add("WWW-Authenticate: Basic realm=\"MyWCFService\"");
//Throw an exception with the associated HTTP status code equivalent to HTTP status 401
throw new WebFaultException(HttpStatusCode.Unauthorized);
}
}
}
Поэтому я создаю и размещаю https-хостинг в своем IIS и загружаю сервис, мой класс аутентификации работает, но моя авторизация не работает. Почему? Я определяю свою аутентификацию в веб-конфигурации, как вы можете видеть. Но я не знаю, как можно Я определяю мою авторизацию в моем веб-конфиге.
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.5.2" />
<httpRuntime targetFramework="4.5.2"/>
</system.web>
<system.serviceModel>
<client />
<bindings>
<webHttpBinding>
<binding>
<security mode="Transport" />
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceAuthorization
serviceAuthorizationManagerType
="wcfrestauth.RestAuthorizationManager, wcfrestauth"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="webHttpServiceBehavior">
<!-- Important this is the behavior that makes a normal WCF service to REST based service-->
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name="wcfrestauth.Service1" behaviorConfiguration="ServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost/WCFRestAuthentication/api/" />
</baseAddresses>
</host>
<endpoint binding="webHttpBinding" contract="wcfrestauth.IService1" behaviorConfiguration="webHttpServiceBehavior" />
</service>
</services>
<protocolMapping>
<add binding="webHttpBinding" scheme="https"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
Я имею в виду, когда я вызываю свой сервис в клиенте. Сервис не проверяет функцию авторизации. Я должен определить свой собственный класс авторизации внутри web config, но я не знаю как?
public bool IsInRole(string role)
{
//my code
return true;
// return Roles.IsUserInRole(role);
}
2 ответа
Вам может понадобиться установить serviceCredentials
в вашем web config
файл:
<serviceCredentials type="YourString">
<YourTagsHere>
</YourTagsHere>
</serviceCredentials>
Вот ссылка на дополнительную информацию о serviceCredentials
: https://docs.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/wcf/servicecredentials
Вы можете указать свой пользовательский AuthorizationPolicy в <serviceAuthorization>
теги, например:
<serviceAuthorization serviceAuthorizationManagerType=
"wcfrestauth.RestAuthorizationManager, wcfrestauth">
<authorizationPolicies>
<add policyType="wcfrestauth.AuthorizationPolicy, wcfrestauth"
</authorizationPolicies>
</serviceAuthorization>
В документах WCF есть хороший пример реализации пользовательской политики авторизации для службы WCF.
Однако будьте осторожны при переопределении метода CheckAccess абстрактного базового класса AuthorizationManager. Метод базового класса вызывает GetAuthorizationPolicies
внутренний метод для получения коллекции всех существующих объектов IAuthorizationPolicy (см. также эту статью блога).
Если вы переопределите CheckAcces и не вызовете метод родительского класса, не будет вызван какой-либо метод Evaluate объектов IAuthorizationPolicy.