2010年2月11日星期四

WCF RIA 服务 (三十二)-- 身份验证、角色、个性化 3

如何:在RIA Services中允许角色功能
使用角色,我们可以指定哪个验证用户组可以访问某些资源。WCF RIA Services中的角色功能是建立在ASP.NET的角色功能上的。
我们只有在用户已经被验证后,才能检索用户的角色信息。通过在域操作中的方法上使用RequireRoleAttribute属性,我们就可以限制角色中的成员对域操作的访问。

配置服务端项目
1. 在服务端项目中,打开Web.config文件。
2. 在段中,添加元素。






3. 在成员数据库中,创建所需的角色并赋予用户所需的角色。更多详情,可看后面的章节。
4. 要确保只有指定角色中的成员才能访问域操作,我们需要对域操作应用RequireRoleAttribute属性。

[RequiresRole("Managers")]
public IQueryable GetCustomers()
{
return this.ObjectContext.Customers;
}


在客户端使用角色
1. 要检测是否用户属于要求的角色,使用Roles属性或调用WebContext.Current.User对象的IsInRole方法。下面示例了在调用域操作之前,检测是否用户属于Managers的角色。

private void LoadRestrictedReports()
{
LoadOperation loadSales = context.Load(context.GetSalesOrderHeadersQuery().Take(numberOfRows));
SalesOrdersGrid.ItemsSource = loadSales.Entities;
SalesOrdersGrid.Visibility = System.Windows.Visibility.Visible;

if (WebContext.Current.User.IsInRole("Managers"))
{
LoadOperation loadCustomers = context.Load(context.GetCustomersQuery().Take(numberOfRows));
CustomersGrid.ItemsSource = loadCustomers.Entities;
CustomersGrid.Visibility = System.Windows.Visibility.Visible;
}
else
{
CustomersGrid.Visibility = System.Windows.Visibility.Collapsed;
}
}

2. 如果想让WebContext对象在XAML中可用,那么在创建RootVisual之前,在Application.Startup事件中把当前WebContext实例添加到应用程序资源中。

private void Application_Startup(object sender, StartupEventArgs e)
{
this.Resources.Add("WebContext", WebContext.Current);
this.RootVisual = new MainPage();
}

WCF RIA 服务 (三十一)-- 身份验证、角色、个性化 2

如何:在RIA Services中允许进行身份验证
WCF RIA Services中的身份验证是建立在ASP.NET验证框架之上的。
本章节展示如后在我们的应用程序中通过RIA Services来允许用户身份验证。我们必须在服务端和客户端添加代码,来使身份验证可行。这个验证对客户端就如同一个服务。我们可以通过对域操作应用RequiresAuthenticationAttribute属性,来保证只有验证用户可以访问域操作。

配置服务端项目

1. 在服务端项目中,打开Web.config文件。
2. 在元素中,添加元素。
3. 设置mode属性为我们想在项目中使用的验证模式。下面的代码展示了mode属性设置为Forms的元素。当然,我们的Web.config文件可能包含其他元素。





4. 保存Web.config文件。
5. 在资源管理器中,右键点击服务端项目,选择"添加->新项"。出现"添加新项"对话框。
6. 选择Authentication Domain Service模板,并制定一个名字。

7. 点击"添加"。
8. 如果想只有验证用户可以访问域操作,对域操作应用RequiresAuthenticationAttribute属性。下面代码展示了只有验证用户才可以访问GetSalesOrderHeaders方法。

[RequiresAuthentication()]
public IQueryable GetSalesOrderHeaders()
{
return this.ObjectContext.SalesOrderHeaders;
}

9. 生成解决方案。

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

1. 在客户端项目中,打开App.xaml文件。
2. 在application lifetime 对象集合中添加当前的WebContext对象。下面的app前缀引用包含生成的WebContext对象的命名空间。通常,这个WebContext用的是客户端项目的基命名空间。






3. 在WebContext元素内,添加验证模式。
我们可以添加WindowsAuthentication或者FormsAuthentication。然而,我们添加的类型应该与服务端的验证模式一致。下面展示了如何添加FormsAuthentication。

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:app="clr-namespace:ExampleApplication"
xmlns:appsvc="clr-namespace:System.Windows.Ria.ApplicationServices;assembly=System.Windows.Ria"
x:Class="ExampleApplication.App">











4. 如果必要的话,在客户端添加一个页面来收集用户凭证。
5. 在登录页面的后台代码文件中,调用Login方法来登录用户。下面的例子展示了如何从登录按钮的事件处理中调用Login方法。包含了一个回调函数来对登录操作的结果做反应。

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;
}

6. 调用Logout方法来登出用户。

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();
}
}

7. 要检测是否用户已登录,检索生成的User实体的IsAuthentication属性。下面的代码展示了在检索个性化信息和调用域操作之前,先检测是否当前用户已经验证了。

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 loadProducts = context.Load(context.GetProductsQuery().Take(numberOfRows));
ProductsGrid.ItemsSource = loadProducts.Entities;
}

8. 如果想让WebContext对象在XAML中可用,那么在创建RootVisual之前,在Application.Startup事件中把当前WebContext实例添加到应用程序资源中。

private void Application_Startup(object sender, StartupEventArgs e)
{
this.Resources.Add("WebContext", WebContext.Current);
this.RootVisual = new MainPage();
}

2010年2月10日星期三

WCF RIA 服务 (三十)-- 身份验证、角色、个性化

在Web应用中,我们经常会限制某些特定用户使用一些功能,并对每个用户保持性能。ASP.NET提供了身份验证、角色、个性化实现这些功能。身份验证允许我们核实用户的凭证并标记用户为已登录。角色允许我们根据职责来把用户分组,并对组中成员授予资源许可。个性化允许我们保持验证用户的属相并在web应用中检索这些属性。

WCF RIA Services框架在表现层和中间层都提供这些功能。这节就介绍RIA Services中的身份验证、角色、和个性化。

身份验证域服务
RIA Services提供身份验证域服务模板来简化在表示层中使用身份验证、角色和个性化。我们把验证域服务添加到服务端项目中。

当我们添加一个身份验证域服务时,RIA Services框架自动在服务端添加两个类。代表身份验证服务的类派生于AuthenticationBase(T)类。代表用户的类派生于UserBase类。用户类为已经验证的用户包含个性化属性。
通过客户端代码,我们调用身份验证域服务来请求我们需要的验证、角色或个性化信息。

WebContext
当我们添加一个身份验证域服务时,RIA Services自动在客户端生成一个WebContext类。这个类派生于WebContextBase类,并允许我们在客户端访问身份验证域服务和用户。用Current属性来获取WebContext的当前实例。

身份验证
要想在RIA Services解决方案中使用身份验证,我们必须在服务端和客户端来配置验证。
通过在客户端使用WebContext,我们可以从Silverlight应用程序同步登陆用户。当我们实施了身份验证时,我们通常会用到下面的方法和属性。
Authentication属性(WebContext.Current.Authentication): 提供对身份验证服务的访问。
User属性(WebContext.Current.User): 提供对包含用户状态的对象的访问。
Login(String,String)方法(WebContext.Current.Authentication.Login(String,String):同步验证用户凭证。
Logout(Boolean)方法(WebContext.Current.Authentication.Logout(boolean):同步登出一个已验证用户。

角色
在我们实施了身份验证后,我们就可以配置我们的解决方案来使用角色功能。当我们实施角色功能时,通常会用到下面的属性和方法。
WebContext.Current.User.Roles : 提供用户被赋予的角色的集合。
WebContext.Current.User.IsInRole(String) : 判断已验证用户是否是指定角色的成员。

个性化
要想使用个性化功能,我们必须为个性化功能配置我们的解决方案。当我们实施了个性化功能时,通常会用到下面的属性和方法。
WebContext.Current.User : 包含所有我们已经添加到User类中的属性。例如,User.PhoneNumber。
LoadUser()方法(WebContext.Current.Authentication.LoadUser()) : 刷新用户状态。
SaveUser(Boolean)方法(WebContext.Current.Authentication.SaveUser(boolean)) : 把所有的更改保存到用户状态中。

在客户端处理身份验证错误
我们可以处理在登录、登出、装载或保存用户时产生的错误。思路是通过在调用这些方法时提供回调参数。在回调方法中,我们添加处理错误的代码,并调用MarkErrorAsHandled方法来指定framwork不要抛出异常。AuthenticationService类允许我们在调用下面的方法时提供回调参数。
-- LoadUser
-- Login
-- Logout
-- SaveUser

限制对域服务的访问
在我们实施了身份验证和角色功能后,我们就可以限制特定用户对域服务的访问。可以对整个域服务或服务中个别的操作应用下面的属性。如果我们对整个服务使用了属性,它会应用到所有的操作。
- RequiresAuthenticationAttribute : 指定只有具有验证凭证的用户可以访问操作。
- RequiresRoleAttribute : 指定只有属于特定角色的验证用户可以访问操作。
我们也可以创建自己的验证属性,更多相关信息可以看后面的章节。

WCF RIA 服务 (二十九)-- Silverlight 客户端 10

如何:在客户端添加计算特性
我们可以在客户端添加成员属性,这些属性是有实体类中的成员属性计算而来。局部方法被用来引发事件,来通知用户界面元素数值已被更改。当我们添加计算的成员属性时,这些属性只存在于客户端项目中。

1. 在客户端项目中,添加一个类文件。
2. 声明一个局部类,这个类与我们想要修改的实体代理类具有相同的名字和命名空间。
3. 添加一个属性,创建一个基于一个或多个实体代理类中值的新值。
4. 对每一个用于计算新值的成员属性都实施On[CustomProperty]Changed局部方法,并且调用RaisePropertyChanged方法来通知框架计算的属性已经更改。

下面的示例演示了如何为一个员工计算总的不工作的有效时间,这个时间是基于休假时间和生病请假的时间。对休假时间或生病请假的时间的改动,都将会对总时间产生一个改动。

using System.Windows.Ria;

namespace RIAServicesExample.Web
{
public partial class Employee : Entity
{
public int TotalOffHours
{
get { return this.SickLeaveHours + this.VacationHours; }
}
partial void OnSickLeaveHoursChanged()
{
this.RaisePropertyChanged("TotalOffHours");
}
partial void OnVacationHoursChanged()
{
this.RaisePropertyChanged("TotalOffHours");
}
}
}


可以用下面的代码来对计算的属性进行数据绑定: