zoukankan      html  css  js  c++  java
  • 稳扎稳打Silverlight(60) 4.0通信之WCF RIA Services: 权限验证

    [索引页]
    [源码下载]


    稳扎稳打Silverlight(60) - 4.0通信之WCF RIA Services: 权限验证



    作者:webabcd


    介绍
    Silverlight 4.0 之 WCF RIA Services:权限验证


    在线DEMO
    http://www.cnblogs.com/webabcd/archive/2010/08/09/1795417.html


    示例
    演示在 WCF RIA Services 框架中实现权限验证的方法
    1、服务端
    MyDomainService.cs

    代码
    /*
     * 一个 Domain Service 服务
     
    */

    namespace Silverlight40.Web.Service
    {
        
    using System;
        
    using System.Collections.Generic;
        
    using System.ComponentModel;
        
    using System.ComponentModel.DataAnnotations;
        
    using System.Data;
        
    using System.Linq;
        
    using System.ServiceModel.DomainServices.EntityFramework;
        
    using System.ServiceModel.DomainServices.Hosting;
        
    using System.ServiceModel.DomainServices.Server;
        
    using Silverlight40.Web.Model;

        
    /*
         * 用 LinqToEntities 实现 Domain Service 则继承 LinqToSqlDomainService<NorthwindEntities>;用 LinqToSql 实现 Domain Service 则继承 LinqToSqlDomainService<NorthwindEntities>
         * Domain Service 内所有对客户端可见的方法都应该是 public 的,Domain Service 内的方法不支持重载
         * 对客户端可见的方法要满足命名约定,或为其指定对应的 Attribute。当前支持 6 种数据操作:Query, Update, Insert, Delete, Invoke, Named Update, 详见文档
         * 
         * [EnableClientAccess()] - 该类对客户端可见
         * [EnableClientAccess(RequiresSecureEndpoint = true)] - 使用 HTTPS 协议
         * [Ignore] - 指定的方法不作为服务而公开
         * [Query(IsComposable=true)] - 支持客户端的 linq 查询,而且此查询会被在服务端执行
         * 
         * 在多个 Domain Services 间共享实体:通过 [ExternalReference], [Association()], Context.AddReference() 实现,详见文档
         
    */

        
    // 服务端的类名为:MyDomainService,则其生成的客户端上下文的类名为:MyDomainContext
        [EnableClientAccess()]
        
    public class MyDomainService : LinqToEntitiesDomainService<NorthwindEntities>
        {
            [Query(IsDefault 
    = true)]
            
    public IQueryable<Category> GetCategories()
            {
                
    return this.ObjectContext.Categories;
            }

            
    public void InsertCategory(Category category)
            {
                
    if ((category.EntityState != EntityState.Detached))
                {
                    
    this.ObjectContext.ObjectStateManager.ChangeObjectState(category, EntityState.Added);
                }
                
    else
                {
                    
    this.ObjectContext.Categories.AddObject(category);
                }
            }

            
    public void UpdateCategory(Category currentCategory)
            {
                
    this.ObjectContext.Categories.AttachAsModified(currentCategory, this.ChangeSet.GetOriginal(currentCategory));
            }

            
    public void DeleteCategory(Category category)
            {
                
    if ((category.EntityState == EntityState.Detached))
                {
                    
    this.ObjectContext.Categories.Attach(category);
                }
                
    this.ObjectContext.Categories.DeleteObject(category);
            }



            [Query(IsDefault 
    = true)]
            
    public IQueryable<Product> GetProducts()
            {
                
    return this.ObjectContext.Products;
            }

            
    public IQueryable<Product> GetProductsBySort(string sort)
            {
                
    return ObjectContext.Products.OrderBy(sort);
            }

            
    public void InsertProduct(Product product)
            {
                
    if ((product.EntityState != EntityState.Detached))
                {
                    
    this.ObjectContext.ObjectStateManager.ChangeObjectState(product, EntityState.Added);
                }
                
    else
                {
                    
    this.ObjectContext.Products.AddObject(product);
                }
            }

            
    public void UpdateProduct(Product currentProduct)
            {
                
    this.ObjectContext.Products.AttachAsModified(currentProduct, this.ChangeSet.GetOriginal(currentProduct));
            }

            
    public void DeleteProduct(Product product)
            {
                
    if ((product.EntityState == EntityState.Detached))
                {
                    
    this.ObjectContext.Products.Attach(product);
                }
                
    this.ObjectContext.Products.DeleteObject(product);
            }

            
    public IQueryable<Product> GetProductsByCategoryId(int categoryId)
            {
                
    return this.ObjectContext.Products.Where(p => p.CategoryID == categoryId);
            }



            
    // 通过验证的并且角色属于“管理员”的用户才有权限调用此方法
            [Invoke]
            [RequiresAuthentication()]
            [RequiresRole(
    "管理员")]
            
    public string GetAuthenticationStatus()
            {
                
    return "看到了这条信息,就证明你有权限";
            }
        }
    }



    MyDomainService.metadata.cs

    代码
    /*
     * [MetadataTypeAttribute()] - 指定类的元数据对象
     * [Include] - 生成的客户端上下文包含此字段
     * [Exclude] - 生成的客户端上下文不包含此字段
     * [Composition] - 指定字段为关联数据,即父实体增删改查时,此关联数据也会做相应的变化。指定此 Attribute 后,需显式指定其为 [Include]
     *     注:如果使用 DomainDataSource 则不能将字段设置为 [Composition]
     * [Editable(true)], [Editable(false)] - 指定字段是否可编辑
     * 
     * 支持 Data Annotation 方式的数据验证:DataTypeAttribute(具有很多常用的数据类型的验证), RangeAttribute, RegularExpressionAttribute, RequiredAttribute, StringLengthAttribute 等
     * 注:如果需要将自定义的验证既作用于服务端又作用于客户端,则需要把自定义的验证逻辑代码设置为 shared 模式
     
    */

    namespace Silverlight40.Web.Model
    {
        
    using System;
        
    using System.Collections.Generic;
        
    using System.ComponentModel;
        
    using System.ComponentModel.DataAnnotations;
        
    using System.Data.Objects.DataClasses;
        
    using System.Linq;
        
    using System.ServiceModel.DomainServices.Hosting;
        
    using System.ServiceModel.DomainServices.Server;

        
    using Silverlight40.Web.Service.Validation;

        [MetadataTypeAttribute(
    typeof(Category.CategoryMetadata))]
        [CustomValidation(
    typeof(CategoryValidator), "ValidateCategory")] // 演示通过自定义的实体验证器来实现验证
        public partial class Category
        {
            
    internal sealed class CategoryMetadata
            {
                
    private CategoryMetadata()
                {
                }

                [Key()]
                
    public int CategoryID { getset; }

                [Display(Name 
    = "类别名称")] // 显示用
                [Numeric(ErrorMessage = "字段“{0}”必须是数字")] // 演示通过继承 RegularExpressionAttribute 实现字段的自定义验证
                [StartsWith(ErrorMessage = "{0}")] // 演示通过继承 ValidationAttribute 实现字段的自定义验证
                [CustomValidation(typeof(EndsWidthValidator), "ValidateCategoryName")]  // 演示通过自定义的字段验证器来实现验证
                public string CategoryName { getset; }

                
    public string Description { getset; }

                [Exclude]
                
    public byte[] Picture { getset; }

                [Include]
                [Composition]
                
    public EntityCollection<Product> Products { getset; }
            }
        }

        [MetadataTypeAttribute(
    typeof(Product.ProductMetadata))]
        
    public partial class Product
        {
            
    internal sealed class ProductMetadata
            {
                
    private ProductMetadata()
                {
                }

                
    public Category Category { getset; }

                
    public Nullable<int> CategoryID { getset; }

                
    public bool Discontinued { getset; }

                
    public EntityCollection<Order_Detail> Order_Details { getset; }

                [Display(Order 
    = 0, Name = "产品ID")]
                
    public int ProductID { getset; }

                [Display(Order 
    = 1, Name = "产品名称")]
                
    public string ProductName { getset; }

                
    public string QuantityPerUnit { getset; }

                
    public Nullable<short> ReorderLevel { getset; }

                
    public Supplier Supplier { getset; }

                
    public Nullable<int> SupplierID { getset; }

                
    public Nullable<decimal> UnitPrice { getset; }

                
    public Nullable<short> UnitsInStock { getset; }

                
    public Nullable<short> UnitsOnOrder { getset; }
            }
        }
    }


    MyAuthenticationDomainService.cs

    代码
    /*
     * 实现自定义的权限验证(基于 Forms 验证)
     
    */

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    using System.Linq;
    using System.ServiceModel.DomainServices.Hosting;
    using System.ServiceModel.DomainServices.Server;
    using System.ServiceModel.DomainServices.Server.ApplicationServices;

    using System.Security.Principal;

    namespace Silverlight40.Web.Service
    {
        
    // AuthenticationBase<T> - 要实现自定义的验证逻辑需要继承这个基类,“T”是用户实体类型(其要实现 System.ServiceModel.DomainServices.Server.ApplicationServices.IUser 接口)
        [EnableClientAccess]
        
    public class MyAuthenticationDomainService : AuthenticationBase<User>
        {
            
    // 本例只做演示,所以不会和数据库交互,如果需要和数据库交互就用 MyDomainService
            private MyDomainService _context = new MyDomainService();

            
    // 根据用户名和密码判断其是否是合法用户,如果是合法用户则写入 cookie
            protected override bool ValidateUser(string username, string password)
            {
                
    if (username == "webabcd" && password == "111111")
                {
                    System.Web.Security.FormsAuthentication.SetAuthCookie(
    "webabcd"true);
                    
    return true;
                }

                
    return false;
            }

            
    // 获取当前已验证的用户信息
            protected override User GetAuthenticatedUser(IPrincipal pricipal)
            {
                User user 
    = new User();

                user.Name 
    = pricipal.Identity.Name;
                user.Nickname 
    = "我是 Nickname";
                user.Roles 
    = new string[] { "管理员""开发" };

                
    return user;
            }

            
    // 初始化
            public override void Initialize(DomainServiceContext context)
            {
                
    this._context.Initialize(context);
                
    base.Initialize(context);
            }

            
    // 释放资源
            protected override void Dispose(bool disposing)
            {
                
    if (disposing)
                    
    this._context.Dispose();

                
    base.Dispose(disposing);
            }
        }


        
    // 自定义的用户实体类型,继承自 UserBase(UserBase 实现了 System.ServiceModel.DomainServices.Server.ApplicationServices.IUser 接口)
        public class User : UserBase
        {
            
    public string Nickname { getset; }
        }
    }


    MyRoleProvider.cs

    代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;

    using System.Web.Security;

    namespace Silverlight40.Web.Service
    {
        
    public class MyRoleProvider : RoleProvider
        {
            
    public override void AddUsersToRoles(string[] usernames, string[] roleNames)
            {
                
    throw new NotImplementedException();
            }

            
    public override string ApplicationName
            {
                
    get
                {
                    
    throw new NotImplementedException();
                }
                
    set
                {
                    
    throw new NotImplementedException();
                }
            }

            
    public override void CreateRole(string roleName)
            {
                
    throw new NotImplementedException();
            }

            
    public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
            {
                
    throw new NotImplementedException();
            }

            
    public override string[] FindUsersInRole(string roleName, string usernameToMatch)
            {
                
    throw new NotImplementedException();
            }

            
    public override string[] GetAllRoles()
            {
                
    throw new NotImplementedException();
            }

            
    // 这是必须要重写的方法
            
    // 当 Domain Service 的方法被声明为 [RequiresRole("...")] 时,其通过此方法来判断当前用户是否属于指定的角色
            public override string[] GetRolesForUser(string username)
            {
                
    return new string[] { "管理员""开发" };
            }

            
    public override string[] GetUsersInRole(string roleName)
            {
                
    throw new NotImplementedException();
            }

            
    public override bool IsUserInRole(string username, string roleName)
            {
                
    throw new NotImplementedException();
            }

            
    public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
            {
                
    throw new NotImplementedException();
            }

            
    public override bool RoleExists(string roleName)
            {
                
    throw new NotImplementedException();
            }
        }
    }


    Web.config

    代码
    <authentication mode="Forms">
        
    <forms name=".WCFRIAServices" />
    </authentication>
    <roleManager enabled="true" defaultProvider="MyRoleProvider">
        
    <providers>
            
    <add name="MyRoleProvider" type="Silverlight40.Web.Service.MyRoleProvider" />
        
    </providers>
    </roleManager>



    2、客户端
    AuthenticationDemo.xaml

    代码
    <navigation:Page x:Class="Silverlight40.WCFRIAServices.AuthenticationDemo" 
               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"
               xmlns:navigation
    ="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
               Title
    ="AuthenticationDemo Page">
        
    <Grid x:Name="LayoutRoot">
            
    <StackPanel HorizontalAlignment="Left">

                
    <!--
                    用于登录/注销的操作
                
    -->
                
    <StackPanel Orientation="Horizontal" Margin="5">
                    
    <TextBlock Text="账号:" />
                    
    <TextBox Name="txtUserName" Text="webabcd" />

                    
    <TextBlock Text="账号:" />
                    
    <TextBox Name="txtPassword" Text="111111" />

                    
    <Button Name="btnLogin" Content="登录" Click="btnLogin_Click" />
                    
    <Button Name="btnLogout" Content="注销" Click="btnLogout_Click" />
                
    </StackPanel>

                
    <!--
                    用于显示登录状态
                
    -->
                
    <StackPanel Orientation="Horizontal" Margin="5">
                    
    <TextBlock Text="登录状态:" />
                    
    <TextBlock Name="lblStatus" Text="" />
                
    </StackPanel>

                
    <!--
                    通过绑定到 WebContext 的方式,显示登录用户的信息
                
    -->
                
    <TextBlock Text="{Binding Source={StaticResource WebContext}, Path=User.Nickname}" Margin="5" />

                
    <!--
                    已登录的用户会返回正确的结果,未登录的用户会返回“拒绝访问”
                
    -->
                
    <Button Name="btnAuthenticationTest" Content="权限测试" Click="btnAuthenticationTest_Click" />

            
    </StackPanel>
        
    </Grid>
    </navigation:Page>


    AuthenticationDemo.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 System.Windows.Navigation;

    using System.ServiceModel.DomainServices.Client.ApplicationServices;
    using Silverlight40.Web.Service;
    using System.ServiceModel.DomainServices.Client;

    namespace Silverlight40.WCFRIAServices
    {
        
    public partial class AuthenticationDemo : Page
        {
            
    public AuthenticationDemo()
            {
                InitializeComponent();
            }

            
    // 如果当前用户已经通过验证,则获取其用户信息
            protected override void OnNavigatedTo(NavigationEventArgs e)
            {
                WebContext.Current.Authentication.LoadUser(
    delegate
                {
                    
    if (WebContext.Current.User.IsAuthenticated)
                    {
                        lblStatus.Text 
    = string.Format("登录成功,当前用户:{0},昵称:{1},所属角色:{2}",
                            WebContext.Current.User.Name,
                            WebContext.Current.User.Nickname,
                            
    string.Join(",", WebContext.Current.User.Roles));
                    }
                }, 
                
    null);
            }

            
    // 根据用户名和密码做身份验证
            private void btnLogin_Click(object sender, RoutedEventArgs e)
            {
                LoginParameters lp 
    = new LoginParameters(txtUserName.Text, txtPassword.Text, truenull);
                WebContext.Current.Authentication.Login(
                lp, 
                (lo) 
    =>
                {
                    
    if (lo.HasError)
                    {
                        lblStatus.Text 
    = lo.Error.ToString();
                    }
                    
    else if (lo.LoginSuccess == false)
                    {
                        lblStatus.Text 
    = "验证失败";
                    }
                    
    else if (lo.LoginSuccess == true)
                    {
                        lblStatus.Text 
    = string.Format("登录成功,当前用户:{0},昵称:{1},所属角色:{2}",
                            WebContext.Current.User.Name,
                            WebContext.Current.User.Nickname,
                            
    string.Join(",", WebContext.Current.User.Roles));
                    }
                }, 
                
    null);
            }

            
    // 注销
            private void btnLogout_Click(object sender, RoutedEventArgs e)
            {
                WebContext.Current.Authentication.Logout(
                (lo) 
    =>
                {
                    
    if (lo.HasError)
                        lblStatus.Text 
    = lo.Error.ToString();
                    
    else
                        lblStatus.Text 
    = "注销成功";
                }, 
                
    null);
            }

            
    // 通过验证的并且角色属于“管理员”的用户才有权限访问 GetAuthenticationStatus 方法
            private void btnAuthenticationTest_Click(object sender, RoutedEventArgs e)
            {
                
    // if (WebContext.Current.User.IsInRole("管理员"))
                if (true)
                {
                    MyDomainContext context 
    = new MyDomainContext();

                    InvokeOperation
    <string> io = context.GetAuthenticationStatus();

                    io.Completed 
    += delegate
                    {
                        
    if (io.HasError)
                        {
                            MessageBox.Show(io.Error.Message);
                            io.MarkErrorAsHandled();
                        }
                        
    else
                        {
                            MessageBox.Show(io.Value);
                        }
                    };
                }
            }
        }
    }



    OK
    [源码下载]

  • 相关阅读:
    jchdl
    jchdl
    UVa 10256 (判断两个凸包相离) The Great Divide
    UVa 11168 (凸包+点到直线距离) Airport
    LA 2572 (求可见圆盘的数量) Kanazawa
    UVa 10652 (简单凸包) Board Wrapping
    UVa 12304 (6个二维几何问题合集) 2D Geometry 110 in 1!
    UVa 10674 (求两圆公切线) Tangents
    UVa 11796 Dog Distance
    LA 3263 (平面图的欧拉定理) That Nice Euler Circuit
  • 原文地址:https://www.cnblogs.com/webabcd/p/1860302.html
Copyright © 2011-2022 走看看