如何:在 RIA Services 中启用身份验证

本主题演示如何使用 WCF RIA Services 在应用程序中启用用户身份验证。其中显示了您必须同时添加到服务器项目和客户端项目的代码,以确保身份验证成为客户端应用程序的一项服务。通过将 RequiresAuthenticationAttribute 属性应用到域操作,可以将对域操作的访问限制为已通过身份验证的用户。

WCF RIA Services 中的身份验证依赖 ASP.NET 中的身份验证框架。有关 ASP.NET 身份验证的更多信息,请参见 Introduction to Membership(成员资格简介)。

配置服务器项目

  1. 在服务器项目中,打开 Web.config 文件。

  2. <system.web> 元素中,添加一个 <authentication> 元素。

  3. mode 属性设置为您要在项目中使用的身份验证模式。

    下面的代码显示将 mode 设置为 Forms<authentication> 元素。将 mode 属性设置为 Windows 以使用 Windows 身份验证。您的 Web.config 文件将包含其他元素。

    <system.web>
      <authentication mode="Forms"></authentication>
    </system.web>
    
  4. 保存 Web.config 文件。

  5. 在**“解决方案资源管理器”中,右击服务器项目,选择“添加”,然后选择“新建项”**。

    将显示**“添加新项”**对话框。

  6. 选择**“身份验证域服务”**模板,并指定该服务的名称。

    RIA_ServicesAddAuth

  7. 单击**“添加”**。

  8. 若要将对域操作的访问限制为已通过身份验证的用户,请将 RequiresAuthenticationAttribute 属性应用到域操作。

    下面的示例指定只有已通过身份验证的用户才可以访问 GetSalesOrderHeaders 方法:

    <RequiresAuthentication()> _
    Public Function GetSalesOrderHeaders() As IQueryable(Of SalesOrderHeader)
        Return Me.ObjectContext.SalesOrderHeaders
    End Function
    
    [RequiresAuthentication()]
    public IQueryable<SalesOrderHeader> GetSalesOrderHeaders()
    {
        return this.ObjectContext.SalesOrderHeaders;
    }
    
  9. 生成解决方案。

在客户端项目上配置身份验证服务

  1. 在客户端项目中,打开 App.xaml 文件的代码隐藏文件(App.xaml.cs 或 App.xaml.vb)。

  2. 在构造函数中,创建 WebContext 类的实例。

  3. Authentication 属性设置为您在服务器项目中配置的身份验证类型,并将 WebContext 实例添加到 ApplicationLifetimeObjects

    下面的示例显示如何将身份验证设置为 FormsAuthentication

    Public Sub New()
        InitializeComponent()
    
        Dim webcontext As New WebContext
        webcontext.Authentication = New System.ServiceModel.DomainServices.Client.ApplicationServices.FormsAuthentication
        Me.ApplicationLifetimeObjects.Add(webcontext)
    End Sub
    
    public App()
    {
        this.Startup += this.Application_Startup;
        this.UnhandledException += this.Application_UnhandledException;
    
        InitializeComponent();
    
        WebContext webcontext = new WebContext();
        webcontext.Authentication = new System.ServiceModel.DomainServices.Client.ApplicationServices.FormsAuthentication();
        this.ApplicationLifetimeObjects.Add(webcontext);
    }
    
  4. 如果您使用的是 Windows 身份验证,或您要加载具有持久化凭据的用户,请在向用户显示登录选项前调用 LoadUser 方法。

    下面的示例显示如何从 Application_Startup 方法调用 LoadUser 方法:

    Private Sub Application_Startup(ByVal o As Object, ByVal e As StartupEventArgs) Handles Me.Startup
        WebContext.Current.Authentication.LoadUser(AddressOf OnLoadUser_Completed, Nothing)
        Me.RootVisual = New MainPage()
    End Sub
    
    Private Sub OnLoadUser_Completed(ByVal operation As LoadUserOperation)
        ' Update UI, if necessary
    End Sub
    
    private void Application_Startup(object sender, StartupEventArgs e)
    {
        WebContext.Current.Authentication.LoadUser(OnLoadUser_Completed, null);
        this.RootVisual = new MainPage();
    }
    
    private void OnLoadUser_Completed(LoadUserOperation operation)
    {
        // update UI, if necessary
    }
    
  5. 如有必要,将一个页添加到客户端项目以收集用户凭据。

  6. 在登录页的代码隐藏文件中,调用 Login 方法以使用户登录。

    下面的示例显示如何从登录按钮的事件处理程序调用 Login 方法。包含一个回调方法来响应登录操作的结果。

    Private Sub LoginButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        Dim lp As LoginParameters = New LoginParameters(UserName.Text, Password.Password)
        WebContext.Current.Authentication.Login(lp, AddressOf Me.LoginOperation_Completed, Nothing)
        LoginButton.IsEnabled = False
        LoginResult.Text = ""
    End Sub
    
    Private Sub LoginOperation_Completed(ByVal lo As LoginOperation)
        If (lo.HasError) Then
            LoginResult.Text = lo.Error.Message
            LoginResult.Visibility = System.Windows.Visibility.Visible
            lo.MarkErrorAsHandled()
        ElseIf (lo.LoginSuccess = False) Then
            LoginResult.Text = "Login failed. Please check user name and password."
            LoginResult.Visibility = System.Windows.Visibility.Visible
        ElseIf (lo.LoginSuccess = True) Then
            SetControlVisibility(True)
        End If
        LoginButton.IsEnabled = True
    End Sub
    
    private void LoginButton_Click(object sender, RoutedEventArgs e)
    {
        LoginParameters lp = new LoginParameters(UserName.Text, Password.Password);
        WebContext.Current.Authentication.Login(lp, this.LoginOperation_Completed, null);
        LoginButton.IsEnabled = false;
        LoginResult.Text = "";
    }
    
    private void LoginOperation_Completed(LoginOperation lo)
    {
        if (lo.HasError)
        {
            LoginResult.Text = lo.Error.Message;
            LoginResult.Visibility = System.Windows.Visibility.Visible;
            lo.MarkErrorAsHandled();
        }
        else if (lo.LoginSuccess == false)
        {
            LoginResult.Text = "Login failed. Please check user name and password.";
            LoginResult.Visibility = System.Windows.Visibility.Visible;
        }
        else if (lo.LoginSuccess == true)
        {
            SetControlVisibility(true);
        }
        LoginButton.IsEnabled = true;
    }
    
  7. 若要注销用户,请调用 Logout 方法。

    下面的示例显示如何从注销按钮的事件处理程序调用 Logout 方法。包含一个回调方法来响应注销操作的结果。

    Private Sub LogoutButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
        WebContext.Current.Authentication.Logout(AddressOf Me.LogoutOperation_Completed, Nothing)
    End Sub
    
    Private Sub LogoutOperation_Completed(ByVal lo As LogoutOperation)
        If (Not (lo.HasError)) Then
            SetControlVisibility(False)
        Else
            Dim ew As ErrorWindow = New ErrorWindow("Logout failed.", "Please try logging out again.")
            ew.Show()
            lo.MarkErrorAsHandled()
        End If
    End Sub
    
    private void LogoutButton_Click(object sender, RoutedEventArgs e)
    {
        WebContext.Current.Authentication.Logout(this.LogoutOperation_Completed, null);
    }
    
    private void LogoutOperation_Completed(LogoutOperation lo)
    {
    
        if (!lo.HasError)
        {
            SetControlVisibility(false);
        }
        else
        {
            ErrorWindow ew = new ErrorWindow("Logout failed.", "Please try logging out again.");
            ew.Show();
            lo.MarkErrorAsHandled();
        }
    }
    
  8. 若要检查用户是否经过了身份验证,请对已生成的“用户”实体检索 IsAuthenticated 属性。

    下面的示例在检索配置文件属性和调用域操作前检查当前用户是否经过了身份验证:

    Private Sub LoadReports()
        If (WebContext.Current.User.IsAuthenticated) Then
            numberOfRows = WebContext.Current.User.DefaultRows
            AddHandler WebContext.Current.User.PropertyChanged, AddressOf User_PropertyChanged
            LoadRestrictedReports()
        Else
            CustomersGrid.Visibility = System.Windows.Visibility.Collapsed
            SalesOrdersGrid.Visibility = System.Windows.Visibility.Collapsed
        End If
    
        Dim loadProducts = context.Load(context.GetProductsQuery().Take(numberOfRows))
        ProductsGrid.ItemsSource = loadProducts.Entities
    End Sub
    
    private void LoadReports()
    {
        if (WebContext.Current.User.IsAuthenticated)
        {
            numberOfRows = WebContext.Current.User.DefaultRows;
            WebContext.Current.User.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(User_PropertyChanged);
            LoadRestrictedReports();
        }
        else
        {
            CustomersGrid.Visibility = System.Windows.Visibility.Collapsed;
            SalesOrdersGrid.Visibility = System.Windows.Visibility.Collapsed;
        }
    
        LoadOperation<Product> loadProducts = context.Load(context.GetProductsQuery().Take(numberOfRows));
        ProductsGrid.ItemsSource = loadProducts.Entities;
    }
    
  9. 如果要使 WebContext 对象在 XAML 中可用,请在创建根可视元素前将当前 WebContext 实例添加到 Application.Startup 事件中的应用程序资源。

    下面的示例显示如何将 WebContext 实例添加为应用程序资源:

    Private Sub Application_Startup(ByVal o As Object, ByVal e As StartupEventArgs) Handles Me.Startup
        Me.Resources.Add("WebContext", WebContext.Current)
        Me.RootVisual = New MainPage()
    End Sub
    
    private void Application_Startup(object sender, StartupEventArgs e)
    {
        this.Resources.Add("WebContext", WebContext.Current);
        this.RootVisual = new MainPage();
    }
    

另请参见

任务

演练:将身份验证服务用于 Silverlight 导航应用程序
演练:将身份验证服务用于 Silverlight 业务应用程序