惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

大猫的无限游戏
大猫的无限游戏
aimingoo的专栏
aimingoo的专栏
I
InfoQ
B
Blog RSS Feed
D
DataBreaches.Net
S
SegmentFault 最新的问题
P
Proofpoint News Feed
A
About on SuperTechFans
WordPress大学
WordPress大学
Hugging Face - Blog
Hugging Face - Blog
博客园 - 司徒正美
小众软件
小众软件
博客园 - Franky
有赞技术团队
有赞技术团队
D
Docker
T
Tailwind CSS Blog
雷峰网
雷峰网
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Blog — PlanetScale
Blog — PlanetScale
酷 壳 – CoolShell
酷 壳 – CoolShell
B
Blog
V
Visual Studio Blog
宝玉的分享
宝玉的分享
爱范儿
爱范儿

博客园 - 振河

SQL Server 2005 Reporting Services动态设置数据源 在windows 2008 server 中Password must meet complexity requirements VS2005 中控件的 GenerateMember 属性 Visual Studio 2008 开发WPF应用程序系列文章——window class 之间的继承 Visual Studio 2005 开发WPF应用程序系列文章——什么是WPF 配置 SQL Server 2005 远程调试存储过程 (转载) C# Office编程——Word 错误类型:“系统找不到 Microsoft.Office.Interop.Word" Reporting Service 在文本框中换行的问题 数据库范式设计 JavaScript 用DIV模拟弹出窗口并跟随窗体滚动 SQL Server 2000 占内存居高不下可能的原因及其解决方法 轻松移除VS2005解决方案中的VSS绑定信息 使用ComponentOne 中 C1TrueDBGrid 实现Master-Detail Grid Reporting Services 运行时设置报表的Page Header的大小 朋友,5.1节日快乐 SQL Server 2005 Reporting Services 使用C#类库中的函数方法 SQL Server 2005 Reporting Services 报表中随意格式化日期的方法 SQL Server 2005 Reporting Services的一个bug及其解决方法 SQL Server 2005 Reporting Services 在排版上存在的一个问题
WCF 安全之自定义的用户名/密码身份验证
振河 · 2008-03-26 · via 博客园 - 振河

本文将记述基于 "用户名/密码" 方式的身份验证开发步骤。

1. 服务器数字证书

(1) 安装证书管理中心(Certification Authority):控制面板——〉添加删除程序里安装

(2) 打开IIS,到默认站点(Default Web Site)——〉右键菜单,属性(Properties),打开属性管理窗口——〉(目录安全)Directory Security——〉Server Certificate,下一步一直到最后生成certreq.txt

(3) 进入Certification Authority,右键根节点,选择All Tasks—Submit new question,选择生成的certreq.txt文件

(4) Click Pending requests, choose Request ID , 右键菜单所以任务---Issue。证书将出现在Issued Certificates,双击在detailcopy file生成证书

(5) IIS中安装证书

或者使用命令的方式准备证书:D:\>makecert -r -pe -n "CN=MyServer" -ss My -sky exchange

2. 创建服务

 1    [ServiceContract]
 2    public interface IService1
 3    {
 4
 5        [OperationContract]
 6        string Test();
 7
 8        [OperationContract]
 9        string GetUserName();
10    }


 1    public class Service1 : IService1
 2    {
 3        public string Test()
 4        {
 5            return "Server:" + DateTime.Now.ToString();
 6        }

 7
 8        public string GetUserName()
 9        {
10            string userName = "";
11            if (ApplicationRequestContext.Current != null && ApplicationRequestContext.Current.AuthenticatedUsername != "")
12            {
13                userName = ApplicationRequestContext.Current.AuthenticatedUsername;
14            }

15            else
16            {
17                string[] tokenParts = OperationContext.Current.ServiceSecurityContext.PrimaryIdentity.Name.Split('|');
18                userName = tokenParts[0];
19            }

20
21            string str = "Hello " + userName + ".";
22            //str += string.Format("  You entered: {0}", value);
23            return str;// "hello world";
24        }

25    }

我们通过继承 UserNamePasswordValidator 来创建一个自定义验证器。

 1public class MyUserNamePasswordValidator : UserNamePasswordValidator
 2{
 3  public override void Validate(string userName, string password)
 4  {
 5    if (userName != "user" || password != "pwd")
 6    {
 7      throw new SecurityTokenException("Unknown Username or Password");
 8    }

 9  }

10}

11

接下来创建服务器配置文件,我们使用 WsHttpBinding,采取 TransportWithMessageCredential安全模式。其他的设置还包括 certificateValidationMode、userNamePasswordValidationMode、customUserNamePasswordValidatorType 等。

 1
 2    <system.serviceModel>
 3
 4        <services>
 5            <service name="WcfServiceUserName.Service1" behaviorConfiguration="NewBehavior">
 6                <!-- Service Endpoints -->
 7
 8                <endpoint address="https://servername/WCFUserName/Service1.svc/ws1" binding="wsHttpBinding" bindingConfiguration="Binding1" contract="WcfServiceUserName.IService1">
 9                    <identity>
10                        <dns value="servername(要和证书中申请的一样)"/>
11                    </identity>
12                </endpoint>
13                <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
14            </service>
15        </services>
16        <bindings>
17            <wsHttpBinding>
18                <binding name="Binding1">
19                    <security mode="TransportWithMessageCredential">
20            <message clientCredentialType="UserName"/>
21                    </security>
22                </binding>
23            </wsHttpBinding>
24        </bindings>
25        <behaviors>
26            <serviceBehaviors>
27                <behavior name="NewBehavior">
28                    <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
29                    <serviceMetadata httpGetEnabled="true"/>
30                    <!-- To receive exception details in faults for debugging purposes, set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
31                    <serviceDebug includeExceptionDetailInFaults="true"/>
32                    <serviceCredentials>
33                        <clientCertificate>
34                            <authentication certificateValidationMode="None"/>
35                        </clientCertificate>
36            <!--userNamePasswordValidationMode can not equal Window,must be Custom-->
37            <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="CustomUserNamePasswordValidator(类的名称),程序集名称"/>
38                    </serviceCredentials>
39                </behavior>
40            </serviceBehaviors>
41        </behaviors>
42  </system.serviceModel>

3. 创建客户端
启动服务器后,创建客户端代理文件。注意自动生成的客户端配置文件中包含了服务器数字证书的相关信息。

 1    <system.serviceModel>
 2        <bindings>
 3            <wsHttpBinding>
 4                <binding name="WSHttpBinding_IService1" closeTimeout="00:01:00"
 5                    openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
 6                    bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
 7                    maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
 8                    messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
 9                    allowCookies="false">
10                    <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
11                        maxBytesPerRead="4096" maxNameTableCharCount="16384" />
12                    <reliableSession ordered="true" inactivityTimeout="00:10:00"
13                        enabled="false" />
14                    <security mode="TransportWithMessageCredential">
15                        <transport clientCredentialType="None" proxyCredentialType="None"
16                            realm="" />
17                        <message clientCredentialType="UserName" negotiateServiceCredential="true"
18                            algorithmSuite="Default" establishSecurityContext="true" />
19                    </security>
20                </binding>
21            </wsHttpBinding>
22        </bindings>
23        <client>
24            <endpoint address="https://servername/WCFUserName/Service1.svc/ws1"
25                binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService1"
26                contract="IService1" name="WSHttpBinding_IService1">
27                <identity>
28                    <dns value="servername" />
29                </identity>
30            </endpoint>
31        </client>
32    </system.serviceModel>

开始调用服务,注意将 CertificateValidationMode 设置为 None,当然也可以写到配置文件中。

 1            try
 2            {
 3                WSHttpBinding mybinding = new WSHttpBinding();
 4                mybinding.Security.Mode = SecurityMode.TransportWithMessageCredential;
 5                mybinding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
 6
 7                EndpointAddress ea = new EndpointAddress(new Uri("https://servername/WCFUserName/Service1.svc/ws1"));
 8                Service1Client client = new Service1Client(mybinding, ea);
 9
10                client.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None;
11                client.ClientCredentials.UserName.UserName = "user";
12                client.ClientCredentials.UserName.Password = "pwd";
13                client.Open();
14                MessageBox.Show(client.GetUserName());
15            }

16            catch (SecurityTokenException ex)
17            {
18                MessageBox.Show(ex.Message.ToString());
19            }

20          

OK,测试通过。测试环境:Windows XP操作系统、VS2008 WCF、VS2008 Windows应用程序。