我每次發送到WCF的請求都需要傳遞一個值,並檢查服務器上的值並決定是否發出請求,任何人都可以寫一個例子嗎?我不知道那是怎麼回事即將實施WCF和身份驗證
case: 即時生成基於客戶端硬件的密鑰,我想發送該密鑰到服務器與每個請求,以檢查密鑰是否被接受在服務器數據庫然後決定處理請求與否。
在此先感謝。
我每次發送到WCF的請求都需要傳遞一個值,並檢查服務器上的值並決定是否發出請求,任何人都可以寫一個例子嗎?我不知道那是怎麼回事即將實施WCF和身份驗證
case: 即時生成基於客戶端硬件的密鑰,我想發送該密鑰到服務器與每個請求,以檢查密鑰是否被接受在服務器數據庫然後決定處理請求與否。
在此先感謝。
首先我們需要實現在客戶端行爲,並檢查送鑰匙到客戶端進行身份驗證:
class AuthenticationBehaviour : IEndpointBehavior
{
#region IEndpointBehavior Members
public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
{
AuthenticationMessageInspector inspector = new AuthenticationMessageInspector();
clientRuntime.MessageInspectors.Add(inspector);
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
{
//AuthenticationMessageInspector inspector = new AuthenticationMessageInspector();
//endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector);
}
public void Validate(ServiceEndpoint endpoint)
{
}
class AuthenticationMessageInspector : IClientMessageInspector
{
private const string HeaderKey = "Authentication";
public object BeforeSendRequest(ref Message request, IClientChannel channel)
{
if (Session.MachineId == 0)
{
Session.MachineId = LicenseGenerator.GenerateLicense();
}
request.Headers.Add(MessageHeader.CreateHeader(HeaderKey, string.Empty, Session.MachineId));
return null;
}
public void AfterReceiveReply(ref Message reply, object correlationState)
{
}
}
現在我們需要實現在服務器端(WCF服務)的行爲和督察檢查的每個請求,並提取頭然後驗證它:
public class AuthenticationBehaviour : IEndpointBehavior
{
#region IEndpointBehavior Members
public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
{
//AuthenticationMessageInspector inspector = new AuthenticationMessageInspector();
//clientRuntime.MessageInspectors.Add(inspector);
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
{
AuthenticationMessageInspector inspector = new AuthenticationMessageInspector();
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(inspector);
//Console.WriteLine("Dispatcher Applied!");
}
public void Validate(ServiceEndpoint endpoint)
{
}
#endregion
}
public class AuthenticationMessageInspector : IDispatchMessageInspector
{
#region Members
private string conStr = "", commStr = "";
public IDbConnection Connection { get; set; }
public IDbCommand Command { get; set; }
public IDataReader Reader { get; set; }
#endregion
private const string HeaderKey = "Authentication";
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
//Console.WriteLine("recieved Request! ");
int headerIndex = request.Headers.FindHeader(HeaderKey, string.Empty);
if (headerIndex < 0 || string.IsNullOrEmpty(request.Headers.GetHeader<String>(headerIndex)))
{
throw (new Exception("Access Denied!\n"));
return null;
}
bool valid = Validate(request.Headers.GetHeader<String>(headerIndex));
if (!valid)
{
Console.WriteLine("recieved Request! From " + request.Headers.GetHeader<String>(headerIndex) + " and Access Denied!\n");
throw (new Exception("Access Denied!\n" + request.Headers.GetHeader<String>(headerIndex) + " License Number is not athourized! "));
}
if (headerIndex != -1)
{
Console.WriteLine("recieved Request! From " + request.Headers.GetHeader<String>(headerIndex));
}
return null;
}
public void BeforeSendReply(ref Message reply, object correlationState)
{
}
}
現在允許登記的行爲:
_routingHost.Description.Endpoints[0].Behaviors.Add(new Gateway.Controllers.AuthenticationBehaviour());
_routingHost.Open();
這是它的感謝。
您正在尋找訊息檢查員。檢查這個article。
編輯:
提到的方法是你的情況中最容易的方法。您將創建客戶端消息檢查器以添加自定義標頭並分派消息檢查器來提取標頭和驗證密鑰。如果密鑰無效,則會拋出異常。
乾淨的解決方案是創建custom token和cutom credentials,但它非常複雜,因此除非您想深入瞭解WCF安全實現使用消息檢查器。
我已經實現了這樣的事情來處理一些特別的「自定義」身份驗證,其中基於數據庫狀態允許或拒絕方法。它使用PerSession實現,它允許您避免每次都傳遞該密鑰,因爲您可以在執行期間維護代理。它還通過消除重複實例化代理的開銷(可能不是問題取決於您的設計)來提供一些性能優勢。
其實我已經實現它了,非常感謝你幫助我,我用了一種不同的方法,因爲我很快發佈了一個答案 – Stacker 2010-09-07 14:52:24
我在試圖在WCF Rest服務上實現身份驗證機制時談到了這篇文章,我試圖在自定義消息檢查器方法AfterReceiveRequest上獲取身份驗證頭,但遇到了使用提供的System.ServiceModel檢索頭的問題。渠道。消息對象(在方法簽名請求VAR)
public object AfterReceiveRequest(ref Message request, IClientChannel channel,
InstanceContext instanceContext)
Dim headerIndex = request.Headers.FindHeader(HeaderKey, String.Empty)
的headerIndex將總是-1,考慮到本我研究,發現有一個擴展方法的消息類,其允許消息轉換爲對象類型System.Net.Http.HttpRequestMessage。要做到這一點,所有需要的是導入下列程序集:System.ServiceModel.Channel,System.Net.Http。
Dim httpReq As System.Net.Http.HttpRequestMessage = request.ToHttpRequestMessage()
Dim authValue As String
If httpReq.Headers.Contains(HeaderKey) Then
authValue = httpReq.Headers.GetValues(HeaderKey)(0)
End If
參見http://stackoverflow.com/questions/964433/how-to-add-a-custom-header-to-every-wcf-calls自動傳遞數據作爲報頭。不過,我不知道如何在服務器上自動檢查它,但我希望有一個鉤子。 – Rup 2010-09-02 08:37:24