[英]Built-in way to do Basic Authentication with WCF REST service?
我在 WCF 服务中使用基本身份验证。 并且还使用 ASP 成员身份提供程序进行身份验证。
Web.Config:对于 REST 服务:
<webHttpBinding>
<binding name="webHttpBinding" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="200065536" maxBufferPoolSize="200065536" maxReceivedMessageSize="200065536" transferMode="Buffered" useDefaultWebProxy="true">
<readerQuotas maxDepth="202048000" maxStringContentLength="202048000" maxArrayLength="202048000"
maxBytesPerRead="202048000" maxNameTableCharCount="202048000"/>
<security mode="Transport">
</security>
</binding>
</webHttpBinding>
认证类型和模式:
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="MembershipProvider" membershipProviderName="CustomMemberShipProvider" />
</serviceCredentials>
在调用任何方法之前,我的 BasicAuthentication 自定义类。 代码如下所示:
namespace BasicAuth.Service
{
public class BasicAuthenticationInvoker : Attribute, IOperationBehavior, IOperationInvoker
{
#region Private Fields
private IOperationInvoker _invoker;
#endregion Private Fields
#region IOperationBehavior Members
public void ApplyDispatchBehavior(OperationDescription operationDescription,
DispatchOperation dispatchOperation)
{
_invoker = dispatchOperation.Invoker;
dispatchOperation.Invoker = this;
}
public void ApplyClientBehavior(OperationDescription operationDescription,
ClientOperation clientOperation)
{
}
public void AddBindingParameters(OperationDescription operationDescription,
BindingParameterCollection bindingParameters)
{
}
public void Validate(OperationDescription operationDescription)
{
}
#endregion IOperationBehavior Members
#region IOperationInvoker Members
public object Invoke(object instance, object[] inputs, out object[] outputs)
{
System.Diagnostics.Debugger.Break();
if (Authenticate())
return _invoker.Invoke(instance, inputs, out outputs);
else
{
outputs = null;
return null;
}
}
public object[] AllocateInputs()
{
return _invoker.AllocateInputs();
}
public IAsyncResult InvokeBegin(object instance, object[] inputs,
AsyncCallback callback, object state)
{
throw new NotSupportedException();
}
public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
{
throw new NotSupportedException();
}
public bool IsSynchronous
{
get
{
return true;
}
}
#endregion IOperationInvoker Members
private bool Authenticate()
{
string[] credentials = GetCredentials(WebOperationContext.Current.IncomingRequest.Headers);
if (credentials != null && credentials.Length == 2)
{
var username = credentials[0];
var password = credentials[1];
if (Membership.ValidateUser(username, password)) //if valid user
{
//get the roles of the user
string[] roles = Roles.GetRolesForUser(username);
Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity(username), roles);
return true;
}
}
WebOperationContext.Current.OutgoingResponse.Headers["WWW-Authenticate"] = string.Format("Basic realm=\"{0}\"", string.Empty);
WebOperationContext.Current.OutgoingResponse.StatusCode = HttpStatusCode.Unauthorized;
return false;
}
private string[] GetCredentials(WebHeaderCollection headers)
{
string credentials = WebOperationContext.Current.IncomingRequest.Headers["Authorization"];
if (credentials != null)
credentials = credentials.Trim();
if (!string.IsNullOrEmpty(credentials))
{
try
{
string[] credentialParts = credentials.Split(new[] { ' ' });
if (credentialParts.Length == 2 && credentialParts[0].Equals("basic", StringComparison.OrdinalIgnoreCase))
{
credentials = Encoding.ASCII.GetString(Convert.FromBase64String(credentialParts[1]));
credentialParts = credentials.Split(new[] { ':' });
if (credentialParts.Length == 2)
return credentialParts;
}
}
catch (Exception ex)
{
}
}
return null;
}
}
}
我的 Iservice 如下所示:
我的自定义类用作 Iservice 合同中的属性
public interface IService1
{
[OperationContract]
[BasicAuthenticationInvoker] //my custom class for authentication
[WebGet(UriTemplate = "GetString?userID={userID}",
ResponseFormat = WebMessageFormat.Json)]
string GetString(string userID);
}
使用AJAX 调用调用 WCF REST 服务时,我将 Authentication 标头添加到 Request 并使用上述自定义类对用户进行身份验证。
AJAX 调用:下面是用于调用服务的 Ajax 调用,在访问服务之前使用 beforeSend 对用户进行身份验证。
<script>
$(function () {
alert("onload");
$.ajax
({
type: "GET",
data:jsondata,
url: https://localhost:446/BasicAuthService.svc/rest/GetString',
cache: false,
async: true,
crossDomain:true,
dataType: "json",
contentType: "application/json; charset=utf-8",
beforeSend: function (xhr) {
xhr.setRequestHeader('Authorization', 'Basic plc2gxMjMk');
},
error: function(jqXHR, exception)
{
alert(jqXHR.status+" "+exception);
}
});
});
</script>
我的问题是:
我希望你能大致了解我的代码是如何工作的。
所以我需要的是,我如何验证对服务的每个请求,而不是对 BasicAuthentication使用自定义类? WCF 中是否有任何用于验证传入请求的内置功能?
提前致谢。
您的安全模式应指定基本身份验证:
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.