zoukankan      html  css  js  c++  java
  • Module Zero安装

    返回《Module Zero学习目录》



    这里需要抱歉的是,这里使用的博客园的Markdown语法,代码显示不是很好看,没有行号,而且外面还有一个双层框,大家将就着看吧!至于这个双层框,我也不知道怎么回事,不过博客园官方给的例子是没双层框的,如果你知道如何去掉这个框,也麻烦回复一下吧!


    使用模板创建(自动方式)##

    使用ABP和Module-Zero开始一个新的项目最简单的方式通过ABP官网的模板页面创建一个解决方案的模板。看下一篇博客《启动模板》

    手动安装

    如果你之前已经创建了应用,且以后安装module-zero,那么你可以按下面的步骤来做。

    在这篇博客中,我假设你的解决方案有了以下这些项目:

    AbpZeroSample.Core
    AbpZeroSample.Application
    AbpZeroSample.EntityFramework
    AbpZeroSample.Web
    AbpZeroSample.WebApi

    核心(领域)层

    将Abp.Zero nuget包安装到.Core项目中,然后在core module类(本例是AbpZeroSampleCoreModule类)中给AbpZeroCoreModule添加DependsOn特性,如下所示:

    [DependsOn(typeof(AbpZeroCoreModule))]  
    public class AbpZeroSampleCoreModule : AbpModule  
    {  
        public override void Initialize()  
        {  
            IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());  
        }  
    }  
        
    

    领域类(实体)

    Module-zero提供了抽象类User, Role和Tenant,因此我们应该像下面那样实现它们:

    public class User : AbpUser<Tenant, User>
    {
    
    }
    
    public class Role : AbpRole<Tenant, User>
    {
        
    }
    
    public class Tenant : AbpTenant<Tenant, User>
    {
    
    }
    
    

    你可以在这里添加自定义的属性。通过这种方式,我们可以根据自己的需求扩展User, Role和Tenant基类。

    管理者(领域服务)

    因为管理者和存储基类都是抽象的,所以我们应该实现它们。
    让我们从User存储和User管理者开始:

    public class UserStore : AbpUserStore<Tenant, Role, User>  
    {  
        public UserStore(  
            IRepository<User, long> userRepository,  
            IRepository<UserLogin, long> userLoginRepository,  
            IRepository<UserRole, long> userRoleRepository,  
            IRepository<Role> roleRepository,  
            IRepository<UserPermissionSetting, long> userPermissionSettingRepository,  
            IUnitOfWorkManager unitOfWorkManager,  
            ICacheManager cacheManager)    
            : base(  
                userRepository,  
                userLoginRepository,  
                userRoleRepository,  
                roleRepository,  
                userPermissionSettingRepository,  
                unitOfWorkManager,  
                cacheManager)  
        {    
        }      
    }    
    
    public class UserManager : AbpUserManager<Tenant, Role, User>  
    {  
        public UserManager(  
            UserStore userStore,  
            RoleManager roleManager,  
            IRepository<Tenant> tenantRepository,  
            IMultiTenancyConfig multiTenancyConfig,  
            IPermissionManager permissionManager,  
            IUnitOfWorkManager unitOfWorkManager,  
            ISettingManager settingManager,  
            IUserManagementConfig userManagementConfig,  
            IIocResolver iocResolver,  
            ICacheManager cacheManager  
            )  
            : base(  
            userStore,  
            roleManager,  
            tenantRepository,  
            multiTenancyConfig,  
            permissionManager,  
            unitOfWorkManager,  
            settingManager,  
            userManagementConfig,  
            iocResolver,  
            cacheManager)  
        {  
        }  
    }  
    

    不要担心依赖列表,这可能会在下个版本中改变。如果需要的话,只要排列好构造函数就可以了。这对于RoleStore和RoleManager是相似的。

    public class RoleStore : AbpRoleStore<Tenant, Role, User>  
    {  
        public RoleStore(  
            IRepository<Role> roleRepository,  
            IRepository<UserRole, long> userRoleRepository,  
            IRepository<RolePermissionSetting, long> rolePermissionSettingRepository,  
            ICacheManager cacheManager)  
            : base(  
                roleRepository,  
                userRoleRepository,  
                rolePermissionSettingRepository,  
                cacheManager)  
        {  
        }  
    }  
    
    public class RoleManager : AbpRoleManager<Tenant, Role, User>  
    {  
        public RoleManager(  
            RoleStore store,   
            IPermissionManager permissionManager,   
            IRoleManagementConfig roleManagementConfig,   
            ICacheManager cacheManager)  
            : base(  
            store,   
            permissionManager,   
            roleManagementConfig,   
            cacheManager)  
        {  
        }  
    }  
    
    

    这里是租户管理者(tenant manager),没有租户存储类。

    public class TenantManager : AbpTenantManager<Tenant, Role, User>  
    {  
        public TenantManager(EditionManager editionManager) :   
            base(editionManager)  
        {  
        }  
    }  
     
    

    最后是特征值存储和版本管理者。

    
    public class FeatureValueStore : AbpFeatureValueStore<Tenant, Role, User>  
    {  
        public FeatureValueStore(TenantManager tenantManager)  
            : base(tenantManager)  
        {  
        }  
    }  
    
    public class EditionManager : AbpEditionManager  
    {  
    }  
    

    权限管理者

    为了使授权系统生效,我们应该实现权限管理者:

    public class PermissionChecker : PermissionChecker<Tenant, Role, User>  
    {  
        public PermissionChecker(UserManager userManager)  
            : base(userManager)  
        {  
      
        }  
    }  
    
    

    基础设施层

    EntityFramework

    如果你选择了EntityFramework,那么我们应该给它配置module-zero。将Abp.Zero.EntityFramework nuget包安装到.EntityFramework项目中,然后在module文件(本例中是AbpZeroSampleDataModule)中,将AbpEntityFrameworkModule依赖改为AbpZeroEntityFrameworkModule,如下所示:

    [DependsOn(typeof(AbpZeroEntityFrameworkModule), typeof(AbpZeroSampleCoreModule))]  
    public class AbpZeroSampleDataModule : AbpModule  
    {  
        //...  
    }  
    
    

    DbContext

    在DbContext类中,将基类从AbpDbContext改为AbpZeroDbContext,如下所示:

    public class AbpZeroSampleDbContext : AbpZeroDbContext<Tenant, Role, User>  
    {  
        //...  
    }  
    
    

    这样,来自module-zero的实体基类就加到了你的数据库上下文中。

    数据库迁移(Database Migration)

    因为我们的数据库上下文已经改变了,所以,现在我们应该创建数据库迁移。打开包管理器控制台,然后输入以下命令:
    Add-Migration "AbpZero_Installed"
    当然,你可以选择一个不同的迁移名字。在包管理器控制台管理器中不要忘了选择默认的项目为.EntityFramework项目。执行完此命令后,项目中会生成一个新的迁移文件。检查一下,如果需要的话,你可以做出修改。然后输入下面的命令来更新数据库模式:
    Update-Database
    你可以查看EF Code-First文档,获取更多信息。

    初始化数据(Initial Data)

    如果你检查了你的数据库,那么你会发现数据表已经创建了,但是表都是空的。你可以通过EF的种子来初始化数据。你可以使用这么一个类作为初始化数据生成器:

    public class DefaultTenantRoleAndUserBuilder   
    {  
        private readonly AbpZeroSampleDbContext _context;  
    
        public DefaultTenantRoleAndUserBuilder(AbpZeroSampleDbContext context)
        {
            _context = context;
        }
    
        public void Build()
        {
            CreateUserAndRoles();
        }
    
        private void CreateUserAndRoles()
        {
            //Admin role for tenancy owner
    
            var adminRoleForTenancyOwner = _context.Roles.FirstOrDefault(r => r.TenantId == null && r.Name == "Admin");
            if (adminRoleForTenancyOwner == null)
            {
                adminRoleForTenancyOwner = _context.Roles.Add(new Role {Name = "Admin", DisplayName = "Admin"});
                _context.SaveChanges();
            }
    
            //Admin user for tenancy owner
    
            var adminUserForTenancyOwner = _context.Users.FirstOrDefault(u => u.TenantId == null && u.UserName == "admin");
            if (adminUserForTenancyOwner == null)
            {
                adminUserForTenancyOwner = _context.Users.Add(
                    new User
                    {
                        TenantId = null,
                        UserName = "admin",
                        Name = "System",
                        Surname = "Administrator",
                        EmailAddress = "admin@aspnetboilerplate.com",
                        IsEmailConfirmed = true,
                        Password = "AM4OLBpptxBYmM79lGOX9egzZk3vIQU3d/gFCJzaBjAPXzYIK3tQ2N7X4fcrHtElTw==" //123qwe
                    });
    
                _context.SaveChanges();
    
                _context.UserRoles.Add(new UserRole(adminUserForTenancyOwner.Id, adminRoleForTenancyOwner.Id));
    
                _context.SaveChanges();
            }
    
            //Default tenant
    
            var defaultTenant = _context.Tenants.FirstOrDefault(t => t.TenancyName == "Default");
            if (defaultTenant == null)
            {
                defaultTenant = _context.Tenants.Add(new Tenant {TenancyName = "Default", Name = "Default"});
                _context.SaveChanges();
            }
    
            //Admin role for 'Default' tenant
    
            var adminRoleForDefaultTenant = _context.Roles.FirstOrDefault(r => r.TenantId == defaultTenant.Id && r.Name == "Admin");
            if (adminRoleForDefaultTenant == null)
            {
                adminRoleForDefaultTenant = _context.Roles.Add(new Role { TenantId = defaultTenant.Id, Name = "Admin", DisplayName = "Admin" });
                _context.SaveChanges();
            }
    
            //Admin for 'Default' tenant
    
            var adminUserForDefaultTenant = _context.Users.FirstOrDefault(u => u.TenantId == defaultTenant.Id && u.UserName == "admin");
            if (adminUserForDefaultTenant == null)
            {
                adminUserForDefaultTenant = _context.Users.Add(
                    new User
                    {
                        TenantId = defaultTenant.Id,
                        UserName = "admin",
                        Name = "System",
                        Surname = "Administrator",
                        EmailAddress = "admin@aspnetboilerplate.com",
                        IsEmailConfirmed = true,
                        Password = "AM4OLBpptxBYmM79lGOX9egzZk3vIQU3d/gFCJzaBjAPXzYIK3tQ2N7X4fcrHtElTw==" //123qwe
                    });
                _context.SaveChanges();
    
                _context.UserRoles.Add(new UserRole(adminUserForDefaultTenant.Id, adminRoleForDefaultTenant.Id));
                _context.SaveChanges();
            }
        }
    }
    
    

    这个类会创建默认的租户,角色和用户。我们可以在EF的Configuration类中将种子数据初始化到数据库:

    internal sealed class Configuration : DbMigrationsConfiguration<AbpZeroSample.EntityFramework.AbpZeroSampleDbContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = false;
            ContextKey = "AbpZeroSample";
        }
    
        protected override void Seed(AbpZeroSample.EntityFramework.AbpZeroSampleDbContext context)
        {
            context.DisableAllFilters();
            new DefaultTenantRoleAndUserBuilder(context).Build();
        }
    }
    
    

    这里,我们禁用了数据过滤器(为的是我们可以自由地操作数据库)并使用了初始化数据生成器类。

    展示层

    Nuget包

    将下面的nuget包添加到.Web项目中:

    • Abp.Zero.EntityFramework(这个也会添加Abp.Zero和所有依赖)
    • Microsoft.AspNet.Identity.Owin
    • Microsoft.Owin.Host.SystemWeb

    Owin Startup类

    添加一个Owin Startup类如下:

    using AbpZeroSample.Web;
    using Microsoft.AspNet.Identity;
    using Microsoft.Owin;
    using Microsoft.Owin.Security.Cookies;
    using Owin;
    
    [assembly: OwinStartup(typeof(Startup))]
    
    namespace AbpZeroSample.Web
    {
        public class Startup
        {
            public void Configuration(IAppBuilder app)
            {
                // Enable the application to use a cookie to store information for the signed in user
                app.UseCookieAuthentication(new CookieAuthenticationOptions
                {
                    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                    LoginPath = new PathString("/Account/Login")
                });
    
                // Use a cookie to temporarily store information about a user logging in with a third party login provider
                app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
            }
        }
    }
    
    

    Account Controller

    我们可以创建一个用于登录/注销的控制器,如下:

    public class AccountController : AbpZeroSampleControllerBase
    {
        private readonly UserManager _userManager;
    
        private IAuthenticationManager AuthenticationManager
        {
            get
            {
                return HttpContext.GetOwinContext().Authentication;
            }
        }
    
        public AccountController(UserManager userManager)
        {
            _userManager = userManager;
        }
    
        public ActionResult Login(string returnUrl = "")
        {
            if (string.IsNullOrWhiteSpace(returnUrl))
            {
                returnUrl = Request.ApplicationPath;
            }
    
            ViewBag.ReturnUrl = returnUrl;
    
            return View();
        }
    
        [HttpPost]
        public async Task<JsonResult> Login(LoginViewModel loginModel, string returnUrl = "")
        {
            if (!ModelState.IsValid)
            {
                throw new UserFriendlyException("Your form is invalid!");
            }
    
            var loginResult = await _userManager.LoginAsync(
                loginModel.UsernameOrEmailAddress,
                loginModel.Password,
                loginModel.TenancyName
                );
    
            switch (loginResult.Result)
            {
                case AbpLoginResultType.Success:
                    break;
                case AbpLoginResultType.InvalidUserNameOrEmailAddress:
                case AbpLoginResultType.InvalidPassword:
                    throw new UserFriendlyException("Invalid user name or password!");
                case AbpLoginResultType.InvalidTenancyName:
                    throw new UserFriendlyException("No tenant with name: " + loginModel.TenancyName);
                case AbpLoginResultType.TenantIsNotActive:
                    throw new UserFriendlyException("Tenant is not active: " + loginModel.TenancyName);
                case AbpLoginResultType.UserIsNotActive:
                    throw new UserFriendlyException("User is not active: " + loginModel.UsernameOrEmailAddress);
                case AbpLoginResultType.UserEmailIsNotConfirmed:
                    throw new UserFriendlyException("Your email address is not confirmed!");
                default: //Can not fall to default for now. But other result types can be added in the future and we may forget to handle it
                    throw new UserFriendlyException("Unknown problem with login: " + loginResult.Result);
            }
    
            AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
            AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = loginModel.RememberMe }, loginResult.Identity);
    
            if (string.IsNullOrWhiteSpace(returnUrl))
            {
                returnUrl = Request.ApplicationPath;
            }
    
            return Json(new MvcAjaxResponse { TargetUrl = returnUrl });
        }
    
        public ActionResult Logout()
        {
            AuthenticationManager.SignOut();
            return RedirectToAction("Login");
        }
    }
    
    

    还有一个简单的LoginViewModel类:

    
    	public class LoginViewModel
    	{
    
        public string TenancyName { get; set; }			
    
        [Required]
        public string UsernameOrEmailAddress { get; set; }
    
        [Required]
        public string Password { get; set; }
    
        public bool RememberMe { get; set; }
    	}
    
    

    Login视图

    为了可以使用AccountController,我们应该创建一个login页面。创建一个login表单取决于你。只需要经由具有合适参数的AJAX调用AccountController的Login方法就可以了。

    应用安全

    现在,我们可以在HomeController上添加一个AbpAuthorize特性就可以确保只有已经验证的用户可以进入该页面:

    [AbpMvcAuthorize]
    public class HomeController : AbpZeroSampleControllerBase
    {
        public ActionResult Index()
        { 
            return View("~/App/Main/views/layout/layout.cshtml"); //Layout of the angular application.
        }
    }
    
    
  • 相关阅读:
    MATLAB矩阵操作【z】
    matlab绘图方法[z]
    Drawhere 有趣的网页涂鸦工具【z】
    DemoHelper,针对电脑演示的小工具
    Matlab Matrix [z]
    MATLAB函数参考[z]
    计算几何常用算法概览[z]
    matlab命令行环境的常用操作[z]
    不常见数学符号或简写
    matlab加入上级路径和本级路径的方法
  • 原文地址:https://www.cnblogs.com/farb/p/modulezeroInstall.html
Copyright © 2011-2022 走看看