尝试将API密钥授权添加到IIS 7上托管的现有WCF服务
遵循Ron Jacob关于创建从ServiceAuthorizationManager派生的类的教程。
没有被调用。
如果我的理解是错误的,我希望我所要做的就是正确地创建类并在Web.Config中引用它。
此时,我的测试Web客户端应该停止从服务获取数据,直到客户端被更改为处理API Key流程。
然而,客户端仍然正确地使用了合同,并且没有生成我放在ServiceAuthorizationManager类中的Eventlog消息。
我认为它必须是我创建的行为节点 在web.config中但是我已经创建了手动和使用Visual Studio配置编辑器工具,并且两个条目都不起作用。
我相信web config serviceAuthorization节点是正确的,因为它正确引用了授权类的Namespace.Class,我已经仔细检查过Webservice的bin目录中的程序集是CouponParkingWCF.dll。
班级代码是:
namespace CouponParkingWCF
{
public class APIKeyAuthorization:ServiceAuthorizationManager
{
public const string APIKEY = "ApiKey";
public const string APIKEYLIST = "APIKeyList";
public string GetAPIKey(OperationContext operationContext)
{
// Get the request message
ClsLogger.WriteInfoLog("InsideGetAPIKey");
var request = operationContext.RequestContext.RequestMessage;
// Get the HTTP Request
var requestProp = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];
// Get the query string
NameValueCollection queryParams = HttpUtility.ParseQueryString(requestProp.QueryString);
// Return the API key (if present, null if not)
return queryParams[APIKEY];
}
public List<Guid> APIKeys
{
get
{
// Get from the cache
// Could also use AppFabric cache for scalability
var keys = HttpContext.Current.Cache[APIKEYLIST] as List<Guid>;
if (keys == null)
keys = PopulateAPIKeys();
return keys;
}
}
private List<Guid> PopulateAPIKeys()
{
Dt dt = new Dt();
List<Guid> keyList = dt.GetApiKeys();
return keyList;
}
public bool IsValidAPIKey(OperationContext operationContext)
{
// if verification is disabled, return true
//if (Global.APIKeyVerification == false)
// return true;
ClsLogger.WriteInfoLog("InsideIsValidAPIKey");
//return true;
string key = GetAPIKey(operationContext);
Guid apiKey;
// Convert the string into a Guid and validate it
if (Guid.TryParse(key, out apiKey) && APIKeys.Contains(apiKey))
{
return true;
}
// Send back an HTML reply
CreateErrorReply(operationContext, key);
return false;
}
private void CreateErrorReply(OperationContext operationContext, string key)
{
ClsLogger.WriteErrorLog("We have an Authorization Error. Oh Dear.");
}
protected override bool CheckAccessCore(OperationContext operationContext)
{
return IsValidAPIKey(operationContext);
}
}
}
Web配置行为节点是:
<behaviors>
<endpointBehaviors>
<behavior name="RestJSONEndpointBehavior">
<webHttp helpEnabled="false" defaultBodyStyle="Bare" defaultOutgoingResponseFormat="Json" />
</behavior>
<behavior name="RestXMLEndpointBehavior">
<webHttp helpEnabled="false" defaultOutgoingResponseFormat="Xml" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="">
<serviceAuthorization serviceAuthorizationManagerType="CouponParkingWCF.APIKeyAuthorization, CouponParkingWCF, Version=1.0.0.1, Culture=neutral, PublicKeyToken=null" />
</behavior>
<behavior name="wsdl">
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
希望有人能发现我做错了什么。
由于
鲍勃
答案 0 :(得分:0)
问题在于我将serviceAuthorization节点放在其自己的行为节点中。 它应该进入现有的&#34; wsdl&#34;节点
<serviceBehaviors>
<behavior name="wsdl">
<serviceAuthorization serviceAuthorizationManagerType="CouponParkingWCF.APIKeyAuthorization, CouponParkingWCF, Version=1.0.0.1, Culture=neutral, PublicKeyToken=null" />
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
这使API KEY工作,但我们需要让它适用于GET和POST。 Ron的例子显示了使用查询字符串,这对GET很好,但不适用于POST。 所以我们开始将API Key放入标题中。 WCF密钥提取代码是:
public string GetAPIKey(OperationContext operationContext)
{
try
{
var request = operationContext.RequestContext.RequestMessage;
var requestProp = (HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name];
string key = requestProp.Headers["ApiKey"];
return key;
}
catch (Exception exception)
{
ClsLogger.WriteErrorLog("GetAPIKey " + exception.Message);
throw;
}
}