WCF:REST + Basic authentification + IIS

近期一个项目中用到Restful WCF提供服务,但是需要验证机制,网上搜刮了一些,都是太复杂。FQ找到了一篇不错的文章分享一下。

原地址连接: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-header

 
    private 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("\n 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/
 

你可能感兴趣的:(REST)