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
    [源码下载]

  • 相关阅读:
    linux文件管理之查找
    linux文件管理之管道与重定向
    linux文件管理之proc文件系统
    linux文件管理之bash shell
    linux进程管理之作业控制
    linux进程管理之优先级
    linux进程管理之信号控制
    Inno Setup制作最简单的安装程序
    intel汇编笔记
    WINDOWS程序设计对话框加载显示bmp图像及刷新
  • 原文地址:https://www.cnblogs.com/webabcd/p/1860302.html
Copyright © 2011-2022 走看看