近期一个项目中用到Restful WCF提供服务,但是需要验证机制,网上搜刮了一些,都是太复杂。翻墙找到了一篇不错的文章分享一下。
原地址连接:http://vgolovchenko.wordpress.com/2012/05/20/wcf-soaprest-ssl-basic-authentification-iis/
如何实现REST + Basic auth?
1. 创建WCF lib宿主到iis上
参考:http://www.cnblogs.com/yongqiangyue/p/4050258.html
参考:http://www.cnblogs.com/wlflovenet/archive/2011/10/28/WCFREST.html
2. 利用类BasicAuthenticationManager来解析BasicAuth http-header并且验证
代码如下:
public class BasicAuthenticationManager : ServiceAuthorizationManager { protected override bool CheckAccessCore(OperationContext operationContext) { try { var msg = operationContext.RequestContext.RequestMessage; // If user requests standart help-page then ignore authentication check. if (msg.Properties.ContainsKey("HttpOperationName") && msg.Properties["HttpOperationName"].ToString() == "HelpPageInvoke") { return base.CheckAccessCore(operationContext); } var httpRequestHeaders = ((HttpRequestMessageProperty) msg.Properties[HttpRequestMessageProperty.Name]).Headers; // Is Authorization-header contained in http-headers? if (!httpRequestHeaders.AllKeys.Contains(HttpRequestHeader.Authorization.ToString())) { return false; } // Try to parse standart Basic-auth header. var authenticationHeaderBase64Value = httpRequestHeaders[HttpRequestHeader.Authorization.ToString()]; var basicAuthenticationFormatString = Base64EncodeHelper.DecodeUtf8From64(authenticationHeaderBase64Value).Remove(0, "Basic ".Length); var basicAuthenticationParams = basicAuthenticationFormatString.Split(new[] {':'}, 2); var login = basicAuthenticationParams.FirstOrDefault(); var password = basicAuthenticationParams.LastOrDefault(); // Check credentials.// 自定义验证方式:CAuthorizationAPI是自己封装的验证用户名和密码的方法类 if(!CAuthorizationAPI.Validate(login, password)) { return false; } } catch (Exception ex) { return false; } return base.CheckAccessCore(operationContext); } } 对应的配置文件修改(behavior-section部分的修改)<system.serviceModel> <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/> <behaviors> <!--<endpointBehaviors> <behavior name=""> <webHttp helpEnabled="true" faultExceptionEnabled="true" /> </behavior> </endpointBehaviors>--> <serviceBehaviors> <behavior> <!-- 为避免泄漏元数据信息, 请在部署前将以下值设置为 false 并删除上面的元数据终结点 --> <serviceMetadata httpGetEnabled="True" /> <!-- 要接收故障异常详细信息以进行调试, 请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息--> <serviceDebug includeExceptionDetailInFaults="true" /> <serviceAuthorization serviceAuthorizationManagerType="DMService.Infrastructure.BasicAuthenticationManager, DMService" /> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel>3. 写一个测试程序:增加basic auth http-headerprivate static void Main(string[] args) { try { var request = WebRequest.Create(string.Format("http://localhost:21568/api/test/yueyq/{0}", Uri.EscapeDataString("rest-client (ssl-basic auth)"))); // ! Remove this string in production code. Emulate working with the trusted certificate. ServicePointManager.ServerCertificateValidationCallback = delegate { return true; }; // The straightforward passing of credential parameter for demo. const string login = "user"; const string password = "password"; request.Headers.Add( HttpRequestHeader.Authorization, Base64EncodeHelper.EncodeUtf8To64(string.Format("Basic {0}:{1}", login, password))); using (var reader = new StreamReader(request.GetResponse().GetResponseStream())) { Console.WriteLine(reader.ReadToEnd()); } } catch (Exception e) { Console.WriteLine(e.ToString()); } Console.WriteLine(" press Enter to exit.."); Console.ReadLine(); } }4. 类Base64EncodeHelper的实现public static class Base64EncodeHelper { /// <summary> /// The method create a Base64 encoded string from a normal string. /// </summary> /// <param name="toEncode">The String containing the characters to encode.</param> /// <returns>The Base64 encoded string.</returns> public static string EncodeUtf8To64(string toEncode) { var toEncodeAsBytes = Encoding.UTF8.GetBytes(toEncode); var returnValue = Convert.ToBase64String(toEncodeAsBytes); return returnValue; } /// <summary> /// The method to Decode your Base64 strings. /// </summary> /// <param name="encodedData">The String containing the characters to decode.</param> /// <returns>A String containing the results of decoding the specified sequence of bytes.</returns> public static string DecodeUtf8From64(string encodedData) { var encodedDataAsBytes = Convert.FromBase64String(encodedData); var returnValue = Encoding.UTF8.GetString(encodedDataAsBytes); return returnValue; } }
更多的关于WCF安全可以详细的查看下面链接:http://wcfsecurityguide.codeplex.com/