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

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
P
Palo Alto Networks Blog
T
ThreatConnect
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
T
True Tiger Recordings
P
Privacy & Cybersecurity Law Blog
B
Blog
IT之家
IT之家
Last Week in AI
Last Week in AI
F
Full Disclosure
Hacker News: Ask HN
Hacker News: Ask HN
C
Comments on: Blog
Microsoft Azure Blog
Microsoft Azure Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
N
News and Events Feed by Topic
NISL@THU
NISL@THU
腾讯CDC
雷峰网
雷峰网
Security Latest
Security Latest
李成银的技术随笔
M
Microsoft Research Blog - Microsoft Research
L
LangChain Blog
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Check Point Blog
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
博客园 - Franky
N
News | PayPal Newsroom
V
V2EX
A
About on SuperTechFans
The Register - Security
The Register - Security
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google Online Security Blog
Google Online Security Blog
MyScale Blog
MyScale Blog
Cisco Talos Blog
Cisco Talos Blog
Vercel News
Vercel News
WordPress大学
WordPress大学
C
Cyber Attacks, Cyber Crime and Cyber Security
The Hacker News
The Hacker News
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
爱范儿
爱范儿
A
Arctic Wolf
L
LINUX DO - 最新话题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - 同一片海

Win10 资源管理器窗口无边框的问题 Android Studio发布Release版本之坑--Unknown host 'd29vzk4ow07wi7.cloudfront.net' 浏览器外部署Silverlight更新检查失败的原因及对策 C#调用非托管Dll时的参数传递 使用ATL开发ActiveX控件 大数据量传输时配置WCF的注意事项 Silverlight自定义主题 在Silverlight 3中使用主题 [Silverlight]Selector类到底有没有SelectedValue属性? WCF安全之ASP.NET兼容模式 [Silverlight]AutoCompleteBox控件的一个Bug? [Silverlight]一个简单的GroupBox控件 [Silverlight]DataGrid相关的几个小知识点 实现下拉列表支持DataGrid的AutoCompleteBox 可分片数据持久层-ShardingPL使用说明 Silverlight数据绑定中的可空类型与自定义转换器 - 同一片海 一个丑陋的对Silverlight中的Grid无CellPadding的解决方案 - 同一片海 Silverlight中的资源文件 - 同一片海 - 博客园 【分享】SqlServer数据库文档生成工具
WCF安全之customBinding
同一片海 · 2010-04-28 · via 博客园 - 同一片海

本文是关于WCF安全的一个完整示例,WCF宿主选用IIS,并通过添加“启用Silverlight功能的WCF服务”的方式建立WCF服务。

WCF服务的绑定方式采用Visual Studio 2008默认的customBinding,安全模式选用Transport安全模式(httpsTransport),身份验证模式则选用UserNameOverTransport。

本示例的客户端为Silverlight,并在访问WCF服务时使用了Visual Studio 2008自动生成的代理类。

测试用服务类:

using System;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.Collections.Generic;
using System.Text;

namespace SecSample.Web
{
    [ServiceContract(Namespace = "")]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class WeatherService
    {
        [OperationContract]
        public string GetWeather()
        {
            return "Sunny";
        }
    }
}

1、配置IIS

1.1 生成证书

可以使用Makecert.exe工具生成一个测试用的证书,命令如下:

makecert -sr localmachine -ss My -n CN=localhost -sky exchange -pe -r

其中cn=localhost,表示证书的名称为localhost。

本环节需要注意的问题是:

a. 证书名称必须与访问WCF服务所用的域名或机器名一致,否则用IE访问时会出现如下警告

image

用WCF客户端访问时则会导致“无法为 SSL/TLS 安全通道与颁发机构“XXXX”建立信任关系。”的错误。

该限制的直接后果就是造成无法通过不同域名或IP地址访问同一个网站(比如用localhost或192.168.1.8访问本机),暂未找到生成多域名证书的方法,正在郁闷中,如有高手知道解决措施,望不吝赐教。

b. 以上命令行生成的证书存储在“个人”证书中,需要导入到“受信任的根证书颁发机构”或“受信任的发布者”中。

1.2 为IIS配置绑定

编辑网站绑定,添加https类型,并指定SSL证书。如下图:

image

2、服务端配置

Web.config文件中system.serviceModel节的代码如下:

  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="defaultServiceBehavior">
          <serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false" />
          <serviceCredentials>
            <userNameAuthentication userNamePasswordValidationMode="Custom"
              customUserNamePasswordValidatorType="SecSample.Web.CustomUserNameValidator,SecSample.Web" />
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <customBinding>
        <binding name="defaultCustomBinding">
          <binaryMessageEncoding />
          <security authenticationMode="UserNameOverTransport"/>
          <httpsTransport/>
        </binding>
      </customBinding>
    </bindings>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
    <services>
      <service behaviorConfiguration="defaultServiceBehavior" name="SecSample.Web.WeatherService">
        <endpoint address="" binding="customBinding" bindingConfiguration="defaultCustomBinding"
          contract="SecSample.Web.WeatherService" />
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>
  </system.serviceModel>

serviceBehaviors节中命名为defaultServiceBehavior的behavior设置了如下内容:

a. 允许https协议获取元数据

b. userNamePasswordValidationMode选用Custom,验证类为继承自UserNamePasswordValidator类的CustomUserNameValidator类,CustomUserNameValidator类的完整源代码如下:

using System;
using System.Collections.Generic;
using System.IdentityModel.Selectors;
using System.Linq;
using System.ServiceModel;
using System.Web;

namespace SecSample.Web
{
    public class CustomUserNameValidator : UserNamePasswordValidator
    {

        public override void Validate(string userName, string password)
        {
            if (userName == "admin" && password == "123456") return;
            throw new ApplicationException("验证失败!");
        }
    }
}

customBinding节中命名为defaultCustomBinding的binding设置了customBinding所选用的编码方式(binaryMessageEncoding)、安全验证模式(UserNameOverTransport)及传输协议(httpsTransport)。

3、客户端配置

客户端ServiceReferences.ClientConfig文件的完整代码如下:

<configuration>
  <system.serviceModel>
    <bindings>
      <customBinding>
        <binding name="defaultCustomBinding">
          <binaryMessageEncoding />
          <security authenticationMode="UserNameOverTransport" />
          <httpsTransport />
        </binding>
      </customBinding>
    </bindings>
    <client>
      <endpoint address="../WeatherService.svc" binding="customBinding"
        bindingConfiguration="defaultCustomBinding" contract="WeatherServiceRef.WeatherService"
        name="CustomBinding_WeatherService" />
    </client>
  </system.serviceModel>
</configuration>

由于Silverlight及WCF使用同一个网站承载并假定相对位置固定,客户端终结点使用了相对地址“../WeatherService.svc”

以避免更换域名造成的问题(可惜证书与域名绑定的问题避免不了),customBinding节中则作了与服务器端对应的配置。

4、客户端示例页面

MainPage.xaml文件:

<UserControl x:Class="SecSample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
  <Grid x:Name="LayoutRoot">
        <Button Name="btnGet" Content="GetWeather" Click="GetWeather"
                HorizontalAlignment="Center" VerticalAlignment="Center"></Button>
  </Grid>
</UserControl>

MainPage.xaml.cs文件:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using SecSample.WeatherServiceRef;

namespace SecSample
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();

            _client = new SecSample.WeatherServiceRef.WeatherServiceClient();

            _client.ClientCredentials.UserName.UserName = "admin";
            _client.ClientCredentials.UserName.Password = "123456";

             
            _client.GetWeatherCompleted += new EventHandler<GetWeatherCompletedEventArgs>(_client_GetWeatherCompleted);
        }
        
        private WeatherServiceClient _client;

        private void GetWeather(object sender, RoutedEventArgs e)
        {
            this._client.GetWeatherAsync();
            this.btnGet.IsEnabled = false;
        }

        void _client_GetWeatherCompleted(object sender, GetWeatherCompletedEventArgs e)
        {
            this.btnGet.IsEnabled = true;
            
            if (e.Error == null)
            {
                MessageBox.Show(e.Result);
            }
            else
            {
                MessageBox.Show(e.Error.Message);
            }
        }
    }
}

示例页面非常简单,添加一个按钮并在按钮单击时调用WCF服务,调用成功时显示调用结果,否则显示错误信息。

需注意的是客户端代理类的初始化,在服务器端要求UserNameOverTransport验证后,需要为客户端代理类指定UserName及Password。

至此,整个示例就完成了。运行效果图如下:

image

但如果用另一个机器访问该服务,会可能会出现如下警告:

image

这是由于我们使用的只是自己生成的测试用证书,而该证书并没有受到客户机的信任。如果只是测试或企业内部使用,客户端将该证书安装到受信任区域即可,如果是正式对外提供服务,则可能需要向相关机构申请正式证书。

示例测试环境:

操作系统:Windows7

开发环境:Visual Studio 2008 + Silverlight 3

IIS:7.5

浏览器:IE8