Procédure : spécifier les informations d'identification du client pour une demande de service de données (WCF Data Services)
Par défaut, la bibliothèque cliente ne fournit aucune information d'identification lors de l'envoi d'une demande à un service OData . Toutefois, vous pouvez spécifier que les informations d'identification soient transmises aux demandes authentifiées sur le service de données en fournissant un NetworkCredential pour la propriété Credentials du DataServiceContext. Pour plus d'informations, consultez Sécurisation de WCF Data Services. L'exemple de cette rubrique décrit comment fournir explicitement des informations d'identification utilisées par le client Services de données WCF lors d'une demande de données au service de données.
L'exemple dans cette rubrique utilise l'exemple de service de données Northwind et des classes de service de données clientes générées automatiquement. Ce service et les classes de données clientes sont créés lorsque vous complétez le démarrage rapide WCF Data Services. Vous pouvez également utiliser l'exemple de service de données Northwind publié sur le site Web OData ; cet exemple de service de données est en lecture seule et retourne une erreur si vous tentez d'enregistrer les modifications apportées. Les exemples de services de données sur le site Web OData autorisent l'authentification anonyme.
Exemple
L'exemple suivant provient de la page code-behind d'un fichier XAML (Extensible Application Markup Language) qui est la page principale de l'application Windows Presentation Framework. Cet exemple affiche une instance LoginWindow pour collecter les informations d'authentification de l'utilisateur, puis les utilise pour la création d'une demande au service de données.
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.");
}
}
}
}
Vous trouverez ci-après le code XAML qui définit la page principale de l'application 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>
L'exemple suivant provient de la page code-behind de la fenêtre utilisée pour collecter les informations d'authentification de l'utilisateur avant une demande au service de données.
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.");
}
}
}
}
Vous trouverez ci-après le code XAML qui définit la connexion de l'application 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>
Sécurité
Les considérations sur la sécurité suivantes s'appliquent à l'exemple de cette rubrique :
Pour vérifier que les informations d'identification fournies dans cet exemple fonctionnent, le service de données Northwind doit utiliser un schéma d'authentification autre que l'accès anonyme. Autrement, le site Web qui héberge le service de données ne demandera aucune information d'identification.
Les informations d'identification de l'utilisateur ne doivent être demandées que pendant l'exécution et ne doivent pas être mises en cache. Les informations d'identification doivent toujours être stockées en sécurité.
Les données transmises avec une authentification de base et condensée ne sont pas chiffrées, par conséquent les données sont visibles à quiconque. De plus, les informations d'authentification de base (nom d'utilisateur et mot de passe) sont envoyées en texte clair et peuvent être interceptées.
Pour plus d'informations, consultez Sécurisation de WCF Data Services.
Voir aussi
Concepts
Sécurisation de WCF Data Services