共用方式為


HOW TO:指定資料服務要求的用戶端認證 (WCF Data Services)

預設情況下,將要求傳送至 OData 服務時,用戶端程式庫不提供認證。不過,您可以透過為 DataServiceContextCredentials 屬性提供 NetworkCredential,藉以指定要傳送的認證來驗證要求。如需詳細資訊,請參閱保護 WCF Data Services 的安全。本主題中的範例會示範如何在從資料服務要求資料時,明確地提供 WCF Data Services 用戶端所使用的認證。

本主題中的範例使用 Northwind 範例資料服務和自動產生的用戶端資料服務類別。此服務和用戶端資料類別會在您完成 WCF Data Services 快速入門時建立。您也可以使用在 OData 網站上發佈的 Northwind 範例資料服務;此範例資料服務是唯讀的,因此嘗試儲存變更時,會傳回錯誤。OData 網站上的範例資料服務允許匿名驗證。

範例

下列範例取自用於 Windows Presentation Framework 應用程式主頁面之可延伸應用程式標記語言 (XAML) 檔案的程式碼後置頁面。此範例會顯示 LoginWindow 執行個體,以便向使用者收集驗證認證,然後在要求資料服務時使用這些認證。

Imports NorthwindClient.Northwind
Imports System.Data.Services.Client
Imports System.Windows.Data
Imports System.Net
Imports System.Windows
Imports System.Security

Partial Public Class ClientCredentials
    Inherits Window

    ' Create the binding collections and the data service context.
    Private binding As DataServiceCollection(Of Customer)
    Private context As NorthwindEntities
    Private customerAddressViewSource As CollectionViewSource

    ' Instantiate the service URI and credentials.
    Dim serviceUri As Uri = New Uri("https://localhost:54321/Northwind.svc/")
    Private credentials As NetworkCredential = New NetworkCredential()

    Public Sub Main()
        InitializeComponent()
    End Sub

    Private Sub ClientCredentials_Loaded(ByVal sender As Object, ByVal e As RoutedEventArgs)

        Dim userName = String.Empty
        Dim domain = String.Empty
        Dim password = New SecureString()

        ' Get credentials for authentication.
        Dim login As New LoginWindow()
        login.ShowDialog()

        If login.DialogResult = True _
            AndAlso Not login.userNameBox.Text Is String.Empty _
            AndAlso login.passwordBox.SecurePassword.Length <> 0 Then

            ' Instantiate the context.
            context = New NorthwindEntities(serviceUri)

            ' Get the user name and domain from the login.
            Dim qualifiedUserName As String() = login.userNameBox.Text.Split(New [Char]() {"\"c})
            If qualifiedUserName.Length = 2 Then
                domain = qualifiedUserName(0)
                userName = qualifiedUserName(1)
            Else
                userName = login.userNameBox.Text
            End If
            password = login.passwordBox.SecurePassword

            ' Set the client authentication credentials.
            context.Credentials = _
                New NetworkCredential(userName, password, domain)


            ' Define an anonymous LINQ query that returns a collection of Customer types.
            Dim query = From c In context.Customers
                        Where c.Country = "Germany"
                        Select c

            Try
                ' Instantiate the binding collection, which executes the query.
                binding = New DataServiceCollection(Of Customer)(query)

                ' Load result pages into the binding collection.
                While Not binding.Continuation Is Nothing
                    ' Continue to execute the query until all pages are loaded.
                    binding.Load(context.Execute(Of Customer)(binding.Continuation.NextLinkUri))
                End While

                ' Assign the binding collection to the CollectionViewSource.
                customerAddressViewSource = _
                    CType(Me.Resources("customerViewSource"), CollectionViewSource)
                customerAddressViewSource.Source = binding
            Catch ex As Exception
                MessageBox.Show(ex.Message)
            End Try
        ElseIf login.DialogResult = False Then
            MessageBox.Show("Login cancelled.")
        End If
    End Sub
End Class
using System;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Security;
using NorthwindClient.Northwind;
using System.Data.Services.Client;

namespace NorthwindClient
{
    public partial class ClientCredentials : Window
    {
        // Create the binding collections and the data service context.
        private DataServiceCollection<Customer> binding;
        NorthwindEntities context;
        CollectionViewSource customerAddressViewSource;

        // Instantiate the service URI and credentials.
        Uri serviceUri = new Uri("https://localhost:12345/Northwind.svc/");
        NetworkCredential credentials = new NetworkCredential();

        public ClientCredentials()
        {
            InitializeComponent();
        }

        private void ClientCredentials_Loaded(object sender, RoutedEventArgs e)
        {
            string userName = string.Empty;
            string domain = string.Empty;
            SecureString password = new SecureString();

            // Get credentials for authentication.
            LoginWindow login = new LoginWindow();
            login.ShowDialog();

            if (login.DialogResult == true 
                && login.userNameBox.Text != string.Empty
                && login.passwordBox.SecurePassword.Length != 0)
            { 
                // Instantiate the context.
                context =
                    new NorthwindEntities(serviceUri);

                // Get the user name and domain from the login.
                string[] qualifiedUserName = login.userNameBox.Text.Split(new char[] { '\\' });
                if (qualifiedUserName.Length == 2)
                {
                    domain = qualifiedUserName[0];
                    userName = qualifiedUserName[1];
                }
                else
                {
                    userName = login.userNameBox.Text;
                }
                password = login.passwordBox.SecurePassword;

                // Set the client authentication credentials.
                context.Credentials =
                    new NetworkCredential(userName, password, domain);

               
                // Define an anonymous LINQ query that returns a collection of Customer types.
                var query = from c in context.Customers
                            where c.Country == "Germany"
                            select c;

                try
                {
                    // Instantiate the binding collection, which executes the query.
                    binding = new DataServiceCollection<Customer>(query);
         
                    while (binding.Continuation != null)
                    {
                        // Continue to execute the query until all pages are loaded.
                        binding.Load(context.Execute<Customer>(binding.Continuation.NextLinkUri));
                    }

                    // Assign the binding collection to the CollectionViewSource.
                    customerAddressViewSource =
                        (CollectionViewSource)this.Resources["customerViewSource"];
                    customerAddressViewSource.Source = binding;
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
            else if (login.DialogResult == false)
            {
                MessageBox.Show("Login cancelled.");
            }
        }
    }
}

下列 XAML 定義 WPF 應用程式的主頁面。

    <Window x:Class="ClientCredentials"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="https://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="https://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="312" d:DesignWidth="577" 
             Loaded="ClientCredentials_Loaded">
    <Window.Resources>
        <CollectionViewSource x:Key="customerViewSource" />
    </Window.Resources>
    <Grid x:Name="LayoutRoot" Background="White" DataContext="" Height="312" Width="577"
          VerticalAlignment="Top" HorizontalAlignment="Left">
        <Grid.RowDefinitions>
            <RowDefinition Height="203*" />
            <RowDefinition Height="119*" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="336*" />
        </Grid.ColumnDefinitions>
        <DataGrid AutoGenerateColumns="False" Height="213" HorizontalAlignment="Left" 
                      ItemsSource="{Binding Source={StaticResource customerViewSource}}" 
                      Name="customerDataGrid" RowDetailsVisibilityMode="VisibleWhenSelected" 
                      VerticalAlignment="Top" Width="553" Margin="12,44,0,0" 
                      Grid.RowSpan="2" Grid.ColumnSpan="1">
            <DataGrid.Columns>
                <DataGridTextColumn x:Name="customerIDColumn" Binding="{Binding Path=CustomerID}" 
                                        Header="Customer" Width="80" />
                <DataGridTextColumn x:Name="addressColumn" Binding="{Binding Path=Address}" 
                                        Header="Address" Width="180" />
                <DataGridTextColumn x:Name="cityColumn" Binding="{Binding Path=City}" 
                                        Header="City" Width="120" />
                <DataGridTextColumn x:Name="countryColumn" Binding="{Binding Path=Country}" 
                                        Header="Country" Width="80" />
                <DataGridTextColumn x:Name="postalCodeColumn" Binding="{Binding Path=PostalCode}" 
                                        Header="Postal Code" Width="90" />
                <DataGridTextColumn Binding="{Binding Path=CompanyName}" Header="CompanyName" />
                <DataGridTextColumn Binding="{Binding Path=ContactName}" Header="ContactName" />
                <DataGridTextColumn Binding="{Binding Path=Phone}" Header="Phone" />
            </DataGrid.Columns>
        </DataGrid>
        <Label Grid.Row="0" Grid.Column="0" Height="26" HorizontalAlignment="Left" Margin="16,12,0,0" 
                   Name="serviceUriLabel" VerticalAlignment="Top" Width="550"  />
    </Grid>
</Window>

下列範例取自視窗的程式碼後置頁面,在要求資料服務前,此視窗用來收集使用者的驗證認證。

Imports System.ComponentModel
Imports System.Windows
Imports System.Security

Partial Public Class LoginWindow
    Inherits Window

    Public Sub New()
        InitializeComponent()
    End Sub

    Private Sub OKButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles OKButton.Click
        Me.DialogResult = True
        e.Handled = True
    End Sub

    Private Sub CancelButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs) Handles CancelButton.Click
        Me.DialogResult = False
        e.Handled = True
    End Sub

    Private Sub LoginWindow_Closing(ByVal sender As System.Object, ByVal e As CancelEventArgs)
        If Me.DialogResult = True AndAlso _
                    (Me.userNameBox.Text = String.Empty OrElse Me.passwordBox.SecurePassword.Length = 0) Then
            e.Cancel = True
            MessageBox.Show("Please enter name and password or click Cancel.")
        End If
    End Sub
End Class
using System;
using System.Windows;
using System.Windows.Controls;
using System.ComponentModel;

namespace NorthwindClient
{
    public partial class LoginWindow : Window
    {
        public LoginWindow()
        {
            InitializeComponent();
        }

        private void OKButton_Click(object sender, RoutedEventArgs e)
        {
            this.DialogResult = true;
            e.Handled = true;
        }

        private void CancelButton_Click(object sender, RoutedEventArgs e)
        {
             this.DialogResult = false;
             e.Handled = true;
        }

        private void LoginWindow_Closing(object sender, CancelEventArgs e)
        {
            if (this.DialogResult == true &&
                    (this.userNameBox.Text == string.Empty || this.passwordBox.SecurePassword.Length == 0))
            {
                e.Cancel = true;
                MessageBox.Show("Please enter name and password or click Cancel.");
            }
        }

    }
}

下列 XAML 定義 WPF 應用程式的登入。

    <Window x:Class="LoginWindow"
           xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" 
           xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml" 
           Width="400" Height="200" 
           Title="LoginWindow" xmlns:sdk="https://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" Closing="LoginWindow_Closing">
    <StackPanel Name="LayoutRoot" Orientation="Vertical" VerticalAlignment="Top">
        <StackPanel Orientation="Horizontal">
            <TextBlock Height="25" HorizontalAlignment="Left" Margin="10,20,0,0" Name="userNameLabel" VerticalAlignment="Top" 
                       Width="80" Text="User name:"/>
            <TextBox Height="23" HorizontalAlignment="Left" Margin="10,20,0,0"  Name="userNameBox" VerticalAlignment="Top" 
                     Width="150" Text="DOMAIN\login"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal" VerticalAlignment="Top">
            <TextBlock Height="25" HorizontalAlignment="Left" Margin="10,20,0,0" Name="pwdLabel" Width="80" Text="Password:"/>
            <PasswordBox Height="23" HorizontalAlignment="Left" Margin="10,20,0,0" Name="passwordBox" Width="150" />
        </StackPanel>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" Height="80" VerticalAlignment="Top">
            <Button x:Name="CancelButton" Content="Cancel" Click="CancelButton_Click" Width="75" Height="23" 
                HorizontalAlignment="Right" Margin="8" IsCancel="True" />
            <Button x:Name="OKButton" Content="OK" Click="OKButton_Click" Width="75" Height="23" 
                HorizontalAlignment="Right" Margin="8" IsDefault="True" />
        </StackPanel>
    </StackPanel>
</Window>

安全性

下列安全性考量適用於本主題中的範例:

  • 若要驗證此範例中提供的認證有效,Northwind 資料服務必須使用匿名存取以外的驗證配置。否則,主控資料服務的網站將不會要求認證。

  • 只有在執行期間才會要求使用者認證,而且應該不會快取。認證永遠必須以安全的方式儲存。

  • 使用基本與摘要式驗證傳送的資料不會經過加密,因此敵人可以看到資料。此外,基本驗證認證 (使用者名稱和密碼) 會以純文字傳送,而且可以被攔截。

如需詳細資訊,請參閱保護 WCF Data Services 的安全

另請參閱

概念

保護 WCF Data Services 的安全

其他資源

WCF Data Services 用戶端程式庫