学习008-02-05-01 Use the Security System(使用安全系统)

Use the Security System(使用安全系统)

This article explains how to implement the Security System in your application. The system applies the SecurityStrategyComplex security strategy. According to this strategy, application users have roles with different permission sets. For more information about permissions, see the following topic: Security (Access Control & Authentication).
本文介绍了如何在您的应用程序中实现安全系统。系统应用SecurityStrategyComplex安全策略。根据该策略,应用程序用户具有不同权限集的角色。有关权限的更多信息,请参阅以下主题:安全性(访问控制和身份验证)。

The instructions below describe how to do the following:
以下说明描述了如何执行以下操作:

  • Enable the AuthenticationStandard authentication type.(启用AuthenticationStandard身份验证类型。)
  • Create an administrator user and a common user in code.(在代码中创建管理员用户和普通用户。)
  • Create a user and a role at runtime.(在运行时创建用户和角色。)

The administrator has a full-access permission set. The user has a limited permission set. The administrator can create User objects and Role objects, specify Permissions for them, and then assign Roles to Users at runtime.
管理员有一个全套访问权限集。用户有一个有限的权限集。管理员可以创建用户对象和角色对象,为它们指定权限,然后在运行时为用户分配角色。

With AuthenticationStandard authentication type, the Security System uses the internal XAF authentication mechanism and stores user credentials in the application’s database. Users need to input their name and password in the login form before application startup.
对于AuthenticationStandard身份验证类型,安全系统使用内部XAF身份验证机制,并将用户凭据存储在应用程序的数据库中。用户需要在应用程序启动前在登录表单中输入姓名和密码。

Note
Before you proceed, take a moment to review this lesson: 在继续之前,请花点时间回顾一下本课:

  • Supply Initial Data

Implement Standard Authentication in Code(在代码中实现标准身份验证)

1.In the MySolution.Module\BusinessObjects folder, create the ApplicationUser class. Replace the generated class declaration with the following code:
在MySolutions. Module\BusinessObjects文件夹中,创建Application ationUser类。将生成的类声明替换为以下代码:

C#

using System.Collections.ObjectModel;
using System.ComponentModel;
using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Security;
using DevExpress.Persistent.BaseImpl.EF.PermissionPolicy;

namespace MySolution.Module.BusinessObjects;

[DefaultProperty(nameof(UserName))]
public class ApplicationUser : PermissionPolicyUser, ISecurityUserWithLoginInfo
{
    public ApplicationUser() : base()
    {
        UserLogins = new ObservableCollection<ApplicationUserLoginInfo>();
    }

    [Browsable(false)]
    [DevExpress.ExpressApp.DC.Aggregated]
    public virtual IList<ApplicationUserLoginInfo> UserLogins { get; set; }

    IEnumerable<ISecurityUserLoginInfo> IOAuthSecurityUser.UserLogins => UserLogins.OfType<ISecurityUserLoginInfo>();

    ISecurityUserLoginInfo ISecurityUserWithLoginInfo.CreateUserLoginInfo(string loginProviderName, string providerUserKey)
    {
        ApplicationUserLoginInfo result = ((IObjectSpaceLink)this).ObjectSpace.CreateObject<ApplicationUserLoginInfo>();
        result.LoginProviderName = loginProviderName;
        result.ProviderUserKey = providerUserKey;
        result.User = this;
        return result;
    }
}

You inherit this class from the PermissionPolicyUser class that defines an XAF user with a list of associated security roles.
您可以从PermissionPolicyUser类继承此类,该类定义具有关联安全角色列表的XAF用户。

2.In the same manner, create the ApplicationUserLoginInfo class.
以同样的方式,创建ApplicationUserLoginInfo类。

C#

using DevExpress.ExpressApp.ConditionalAppearance;
using DevExpress.ExpressApp.Security;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace MySolution.Module.BusinessObjects;

[Table("PermissionPolicyUserLoginInfo")]
public class ApplicationUserLoginInfo : ISecurityUserLoginInfo
{
    public ApplicationUserLoginInfo() { }

    [Browsable(false)]
    public virtual Guid ID { get; protected set; }

    [Appearance("PasswordProvider", Enabled = false, Criteria =
    "!(IsNewObject(this)) and LoginProviderName == '" + SecurityDefaults.PasswordAuthentication + "'", Context = "DetailView")]
    public virtual string LoginProviderName { get; set; }

    [Appearance("PasswordProviderUserKey", Enabled = false, Criteria =
    "!(IsNewObject(this)) and LoginProviderName == '" + SecurityDefaults.PasswordAuthentication + "'", Context = "DetailView")]
    public virtual string ProviderUserKey { get; set; }

    [Browsable(false)]
    public virtual Guid UserForeignKey { get; set; }

    [Required]
    [ForeignKey(nameof(UserForeignKey))]
    public virtual ApplicationUser User { get; set; }

    object ISecurityUserLoginInfo.User => User;
}

3.Go to the MySolution.Module\MySolutionDbContext file and add properties of ApplicationUser and ApplicationUserLoginInfo types to DbSet:
转到MySolutions. Module\MySolutionDbContext文件,并将Application ationUser和ApplicationUserLoginInfo类型的属性添加到DbSet:

C#

public class MySolutionEFCoreDbContext : DbContext {
    //...
    public DbSet<ApplicationUser> Users { get; set; }
    public DbSet<ApplicationUserLoginInfo> UserLoginInfos { get; set; }
}

4.Add a migration and update the database. See the following section for details: Use a DBMS: Setup Migrations.
添加迁移并更新数据库。有关详细信息,请参阅以下部分:使用DBMS:设置迁移。

5.Enable Standard Authentication in the platform-specific Startup files:
在特定于平台的启动文件中启用标准身份验证:

C# (ASP.NET Core Blazor)

using DevExpress.Persistent.BaseImpl.EF.PermissionPolicy;
using MySolution.Module.BusinessObjects;

public class Startup {
// ...
    public void ConfigureServices(IServiceCollection services) {
        // ...
        services.AddXaf(Configuration, builder => {
             // ...
             builder.ObjectSpaceProviders
                 .AddSecuredEFCore().WithDbContext<MySolution.Module.BusinessObjects.MySolutionEFCoreDbContext>((serviceProvider, options) => {
                     // ...
                 })
                 .AddNonPersistent();
             builder.Security
                 .UseIntegratedMode(options => {
                     options.RoleType = typeof(PermissionPolicyRole);
                     options.UserType = typeof(ApplicationUser);
                     options.UserLoginInfoType = typeof(ApplicationUserLoginInfo);
                     options.SupportNavigationPermissionsForTypes = false;
             })
             .AddPasswordAuthentication(options => options.IsSupportChangePassword = true);
        });
        services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
            .AddCookie(options => {
                options.LoginPath = "/LoginPage";
            });
    }
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
        //...
        app.UseRequestLocalization();
        //..
        app.UseAuthentication();
        app.UseAuthorization();
        //...
    }
}

C# (Windows Forms)

// ...
// ...
using DevExpress.Persistent.BaseImpl.EF.PermissionPolicy;
using MySolution.Module.BusinessObjects;

public class ApplicationBuilder : IDesignTimeApplicationFactory {
    public static WinApplication BuildApplication(string connectionString) {
    var builder = WinApplication.CreateBuilder();
    builder.UseApplication<MySolutionWindowsFormsApplication>();
    builder.ObjectSpaceProviders
         .AddSecuredEFCore().WithDbContext<MySolution.Module.BusinessObjects.MySolutionEFCoreDbContext>((application, options) => {
             // ...
         })
         // ...
     builder.Security
         .UseIntegratedMode(options =>
         {
             options.RoleType = typeof(PermissionPolicyRole);
             options.UserType = typeof(ApplicationUser);
             options.UserLoginInfoType = typeof(ApplicationUserLoginInfo);
             options.SupportNavigationPermissionsForTypes = false;
         })
     .UsePasswordAuthentication();               
     //...
    }
}

6.Expand the MySolution.Module project in the Solution Explorer and go to the DatabaseUpdate folder. Open the Updater.cs file and create the Administrator user in the ModuleUpdater.UpdateDatabaseAfterUpdateSchema method.
在解决方案资源管理器中展开MySolutions. Module项目并转到Database aseUpdate文件夹。 打开“Updater.cs”文件,并在“ModuleUpdater.UpdateDatabaseAfterUpdateSchema”方法中创建“Administrator”用户。

C#

//...
using DevExpress.ExpressApp.Security;
using DevExpress.Persistent.BaseImpl.EF.PermissionPolicy;
using MySolution.Module.BusinessObjects;

public class Updater : DevExpress.ExpressApp.Updating.ModuleUpdater {
    //...
    public override void UpdateDatabaseAfterUpdateSchema() {
        base.UpdateDatabaseAfterUpdateSchema();
        //...
        ApplicationUser userAdmin = ObjectSpace.FirstOrDefault<ApplicationUser>(u => u.UserName == "Admin");
        if (userAdmin == null)
        {
            userAdmin = ObjectSpace.CreateObject<ApplicationUser>();
            userAdmin.UserName = "Admin";
            // Set a password if the standard authentication type is used
            userAdmin.SetPassword("");


            /* The UserLoginInfo object requires a user object Id (Oid).
               Commit the user object to the database before you create a UserLoginInfo object.
               This will correctly initialize the user key property. */


            ObjectSpace.CommitChanges(); //This line persists created object(s).
            ((ISecurityUserWithLoginInfo)userAdmin).CreateUserLoginInfo(SecurityDefaults.PasswordAuthentication,
            ObjectSpace.GetKeyValueAsString(userAdmin));
        }
        // If a role with the Administrators name doesn't exist in the database, create this role.
        PermissionPolicyRole adminRole =
        ObjectSpace.FirstOrDefault<PermissionPolicyRole>(r => r.Name == "Administrators");
        if (adminRole == null)
        {
            adminRole = ObjectSpace.CreateObject<PermissionPolicyRole>();
            adminRole.Name = "Administrators";
        }
        //Set the user's role to Administrative. This role has access to objects of all types.
        adminRole.IsAdministrative = true;
        userAdmin.Roles.Add(adminRole);


        ObjectSpace.CommitChanges(); //Uncomment this line to persist created object(s).
    }
}

7.In the same manner, create a common user.
以同样的方式,创建一个公共用户。

C#

//...
using DevExpress.ExpressApp.Security;
using DevExpress.Persistent.BaseImpl.EF.PermissionPolicy;
using MySolution.Module.BusinessObjects;

public class Updater : DevExpress.ExpressApp.Updating.ModuleUpdater {
    //...
    public override void UpdateDatabaseAfterUpdateSchema() {
        base.UpdateDatabaseAfterUpdateSchema();
        //...
        ApplicationUser commonUser = ObjectSpace.FirstOrDefault<ApplicationUser>(u => u.UserName == "User");
        if (commonUser == null)
        {
            commonUser = ObjectSpace.CreateObject<ApplicationUser>();
            commonUser.UserName = "User";
            // Set a password if the standard authentication type is used
            commonUser.SetPassword("");

            /* The UserLoginInfo object requires a user object Id (Oid).
               Commit the user object to the database before you create a UserLoginInfo object.
               This will correctly initialize the user key property.*/

            ObjectSpace.CommitChanges(); //This line persists created object(s).
            ((ISecurityUserWithLoginInfo)commonUser).CreateUserLoginInfo(SecurityDefaults.PasswordAuthentication,
            ObjectSpace.GetKeyValueAsString(commonUser));
        }
        PermissionPolicyRole defaultRole = CreateDefaultRole();
        commonUser.Roles.Add(defaultRole);
    }
}

8.Create a common user role and specify its permissions. This user only has access to the current user object.
创建一个通用用户角色并指定其权限。此用户只能访问当前用户对象。

C#

using MySolution.Module.BusinessObjects;
using DevExpress.ExpressApp.SystemModule;
//...

public class Updater : DevExpress.ExpressApp.Updating.ModuleUpdater {
     //...
     public override void UpdateDatabaseAfterUpdateSchema() {
         base.UpdateDatabaseBeforeUpdateSchema();
     }

    private PermissionPolicyRole CreateDefaultRole()
    {
        PermissionPolicyRole defaultRole =
        ObjectSpace.FirstOrDefault<PermissionPolicyRole>(role => role.Name == "Default");
        if (defaultRole == null)
        {
            defaultRole = ObjectSpace.CreateObject<PermissionPolicyRole>();
            defaultRole.Name = "Default";

            defaultRole.AddObjectPermissionFromLambda<ApplicationUser>(SecurityOperations.Read,
            cm => cm.ID == (Guid)CurrentUserIdOperator.CurrentUserId(), SecurityPermissionState.Allow);
            defaultRole.AddNavigationPermission(@"Application/NavigationItems/Items/Default/Items/MyDetails",
            SecurityPermissionState.Allow);
            defaultRole.AddMemberPermissionFromLambda<ApplicationUser>(SecurityOperations.Write,
            "ChangePasswordOnFirstLogon", cm => cm.ID == (Guid)CurrentUserIdOperator.CurrentUserId(),
            SecurityPermissionState.Allow);
            defaultRole.AddMemberPermissionFromLambda<ApplicationUser>(SecurityOperations.Write,
            "StoredPassword", cm => cm.ID == (Guid)CurrentUserIdOperator.CurrentUserId(),
            SecurityPermissionState.Allow);
            defaultRole.AddTypePermissionsRecursively<PermissionPolicyRole>(SecurityOperations.Read,
            SecurityPermissionState.Deny);
            defaultRole.AddTypePermissionsRecursively<ModelDifference>(SecurityOperations.ReadWriteAccess,
            SecurityPermissionState.Allow);
            defaultRole.AddTypePermissionsRecursively<ModelDifferenceAspect>(SecurityOperations.ReadWriteAccess,
            SecurityPermissionState.Allow);
            defaultRole.AddTypePermissionsRecursively<ModelDifference>(SecurityOperations.Create,
            SecurityPermissionState.Allow);
            defaultRole.AddTypePermissionsRecursively<ModelDifferenceAspect>(SecurityOperations.Create,
            SecurityPermissionState.Allow);
        }
        return defaultRole;
    }
}

Note
You can find more examples in the following topic: Security (Access Control & Authentication).
您可以在以下主题中找到更多示例:安全性(访问控制和身份验证)。

9.Optionally, you can configure your application to store user differences (individual user settings) in the database. Make the following changes in the MySolution.Blazor.Server\BlazorModule.cs (ASP.NET Core Blazor) and MySolution.Win\WinModule.cs (Windows Forms) files:
或者,您可以将应用程序配置为在数据库中存储用户差异(单个用户设置)。在MySolutions. Blazor.Server\BlazorModule.cs(ASP.NETCore Blazor)和MySolution.Win\WinModule.cs(Windows窗体)文件中进行以下更改:

C#
ASP.NET Core Blazor

using DevExpress.ExpressApp;
using DevExpress.Persistent.BaseImpl;
// ...

public sealed class MySolutionBlazorModule : ModuleBase {
    // ...
    public override void Setup(XafApplication application) {
        base.Setup(application);
        application.CreateCustomUserModelDifferenceStore += Application_CreateCustomUserModelDifferenceStore;
    }
    private void Application_CreateCustomUserModelDifferenceStore(object sender, CreateCustomModelDifferenceStoreEventArgs e) {
        e.Store = new ModelDifferenceDbStore((XafApplication)sender, typeof(ModelDifference), false, "Blazor");
        e.Handled = true;
    }
}

C#
Windows Forms

using DevExpress.ExpressApp;
using DevExpress.Persistent.BaseImpl;
// ...

public sealed class MySolutionWinModule : ModuleBase {
    // ...
    public override void Setup(XafApplication application) {
        base.Setup(application);
        application.CreateCustomUserModelDifferenceStore += Application_CreateCustomUserModelDifferenceStore;
    }
    private void Application_CreateCustomUserModelDifferenceStore(object sender, CreateCustomModelDifferenceStoreEventArgs e) {
        e.Store = new ModelDifferenceDbStore((XafApplication)sender, typeof(ModelDifference), false, "Win");
        e.Handled = true;
    }
}

This way you can persist Detail View Layout changes made by individual users among other things. See the following help topic for more details: Persist Layout Customization For Individual Users.
通过这种方式,您可以持久化单个用户所做的详细信息视图布局更改等。有关详细信息,请参阅以下帮助主题:为个人用户持久化布局自定义。

10.Run the application. Log in under Admin. Leave the password field empty (you didn’t specify the password when you created this user). When you click the Log In button, the user’s credentials are authenticated and the application runs.
运行应用程序。在管理员下登录。将密码字段留空(您在创建此用户时没有指定密码)。单击登录按钮时,用户的凭据将经过身份验证,应用程序将运行。

11.Select the My Details item in the navigation control and see the Detail View.
在导航控件中选择我的详细信息项并查看详细信息视图。

Create a Role in the UI(在UI中创建角色)

Administrators and other users with Role creation permission can create roles at runtime.
具有角色创建权限的管理员和其他用户可以在运行时创建角色。

1.Select the Role item in the navigation control and click the New button. In the invoked Detail View, set the name and permissions for the new role.
在导航控件中选择角色项,然后单击新建按钮。在调用的详细信息视图中,设置新角色的名称和权限。

ASP.NET Core Blazor
在这里插入图片描述

Windows Forms
在这里插入图片描述

With the Permission Policy property, you can assign the following permission policies:
使用权限策略属性,您可以分配以下权限策略:

  • Deny all by default(默认拒绝所有)
  • Read only all by default(默认情况下只读全部)
  • Allow all by default(默认允许所有)

For each operation, you can explicitly specify the Allow or Deny modifier, or leave it blank. If you don’t specify the modifier, the permission follows the role’s permission policy.
对于每个操作,您可以显式指定允许或拒绝修饰符,或将其留空。如果不指定修饰符,则权限遵循角色的权限策略。

Create a User in the UI(在UI中创建用户)

Administrators and other users with User creation permission can create users at runtime.
管理员和其他具有用户创建权限的用户可以在运行时创建用户。

1.Select the Application User item in the navigation control and click the New button. In the invoked Detail View, specify the User Name and assign one or more roles.
在导航控件中选择Application User项,然后单击New按钮。在调用的详细信息视图中,指定用户名并分配一个或多个角色。

ASP.NET Core Blazor
在这里插入图片描述

Windows Forms
在这里插入图片描述

Tip
Deselect the Is Active checkbox if you need to deny user access to the application.
如果您需要拒绝用户访问应用程序,请取消选中Is Active复选框。

Next Lesson(下一课)

Implement Property Value Validation
实现属性值验证

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

汤姆•猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值