创建一个带身份验证与用户授权的XAF (Blazor类型),需要安装的包与各项配置

       本文描述:从一个不安全的基本Blazor类型的XAF解决方案,转变成一个安全的XAF解决方案(带身份验证与用户授权),必须的包与配置。

1、创建一个基础XAF,包括的内容,参考:   新建一个 面向目标 net5 的基础 XAF 项目(Blazor型,不带安全的认证与授权) 。

2、创建一个带安全的XAF,比较两者:包与配置的差异,以便学习如何配置 “身份认证与用户授权 ”。

      创建面向NetCore的 WinForm 型 XAF方案,使用 XPO 数据存储框架,身份认证Authentication,有三种选择:标准Standard(登录用户+密码)、标准Standard + OAuth2、标准Standard + AD活动目录、标准Standard + OAuth2 + AD活动目录。

                                                         

               经测试,加入“AD活动目录”验证后,“标准Standard”验证 不能使用了

      1) 三个项目都依赖 :DevExpress.ExpressApp.Security.Xpo 包 ,间接依赖:DevExpress.ExpressApp.Security

 

      2)在通用模块项目 XXXX.Module,增加了两个类:ApplicationUser.cs 、 ApplicationUserLoginInfo.cs ,代表用户,但映射的表不变(PermissionPolicyUser)。

               Module.cs(分部类 Module.Designer.cs 中) ,InitializeComponent() 方法,增加了:

               this.RequiredModuleTypes.Add(typeof(DevExpress.ExpressApp.Security.SecurityModule));

            DatabaseUpdate 目录下,Updater.cs  文件增加了 初始化两个用户User(Admin、User ),两个角色Role (Default、Administrators) 。修改 Using 引用。

      3)平台相关项目 XXXX.Module.Blazor,引用了 :DevExpress.ExpressApp.Security.Xpo 包。

      4) 主体项目的相关变化:

        A、BlazorApplication.cs 的分部类 BlazorApplication.Designer.cs 

         增加属性 : private DevExpress.ExpressApp.Security.SecurityModule securityModule1;

          在  InitializeComponent() 方法中增加:   

               this.securityModule1 = new DevExpress.ExpressApp.Security.SecurityModule();

               this.Modules.Add(this.securityModule1);

         B、Startup.cs  中是主要配置修改 ConfigureServices(IServiceCollection services)

            增加: using DevExpress.ExpressApp.Security;

                        using DevExpress.Persistent.BaseImpl.PermissionPolicy;

            services.AddXafSecurity(options => {

                      options.RoleType = typeof(PermissionPolicyRole);
                      options.UserType = typeof(DXBlazor.Module.BusinessObjects.ApplicationUser);
                      options.UserLoginInfoType = typeof(DXBlazor.Module.BusinessObjects.ApplicationUserLoginInfo);
                      options.Events.OnSecurityStrategyCreated = securityStrategy =>                           

                                ((SecurityStrategy)securityStrategy).RegisterXPOAdapterProviders();

                       options.SupportNavigationPermissionsForTypes = false;
                   })                 

                  .AddAuthenticationStandard(options => {options.IsSupportChangePassword = true; });         

                  .AddExternalAuthentication<HttpContextPrincipalProvider>()   ----  外部验证需要配置参数。 

               services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)

                            .AddCookie(options => {options.LoginPath = "/LoginPage"; });

           C、如果选择AD 活动目录,

                      AddXafSecurity()后 增加:

                     .AddAuthenticationActiveDirectory(o => {
                          o.CreateUserAutomatically = true;   })    

                      增加 :services.Configure<IISServerOptions>(options => {
                                           options.AuthenticationDisplayName = "Windows";  });

            D、 如果选择 标准Standard + OAuth2, 外部验证需要下列配置参数,另外还需要配置: OAuth2 Identity Providers

                 .AddExternalAuthentication<HttpContextPrincipalProvider>(options => {

                      options.Events.OnAuthenticated = (externalAuthenticationContext) => {
                     return;
                     if(externalAuthenticationContext.AuthenticatedUser == null &&
                         externalAuthenticationContext.Principal.Identity.AuthenticationType !=  SecurityDefaults.PasswordAuthentication &&
                     externalAuthenticationContext.Principal.Identity.AuthenticationType != SecurityDefaults.WindowsAuthentication  && !(externalAuthenticationContext.Principal is WindowsPrincipal)) {
                     const bool autoCreateUser = true;

                     IObjectSpace objectSpace = externalAuthenticationContext.LogonObjectSpace;
                    ClaimsPrincipal externalUser = (ClaimsPrincipal)externalAuthenticationContext.Principal;

                     var userIdClaim = externalUser.FindFirst("sub") ?? externalUser.FindFirst(ClaimTypes.NameIdentifier) ?? throw new InvalidOperationException("Unknown user id");
                     string providerUserId = userIdClaim.Value;

                      var userLoginInfo = FindUserLoginInfo(externalUser.Identity.AuthenticationType, providerUserId);
                      if(userLoginInfo != null || autoCreateUser) {
                          externalAuthenticationContext.AuthenticatedUser = userLoginInfo?.User ??                          CreateApplicationUser(externalUser.Identity.Name, providerUserId);
                   }

                   object CreateApplicationUser(string userName, string providerUserId) {
                   if(objectSpace.FirstOrDefault<DXStdOAuth2.Module.BusinessObjects.ApplicationUser>(user => user.UserName == userName) != null) {
                    throw new ArgumentException($"The login with '{userName}' name was already registered within the system");
                 }
                var user = objectSpace.CreateObject<DXStdOAuth2.Module.BusinessObjects.ApplicationUser>();
                user.UserName = userName;
                 user.SetPassword(Guid.NewGuid().ToString());
                 user.Roles.Add(objectSpace.FirstOrDefault<PermissionPolicyRole>(role => role.Name == "Default"));
                 ((ISecurityUserWithLoginInfo)user).CreateUserLoginInfo(externalUser.Identity.AuthenticationType, providerUserId);
                 objectSpace.CommitChanges();
                 return user;
                 }
                ISecurityUserLoginInfo FindUserLoginInfo(string loginProviderName, string providerUserId) {
                return objectSpace.FirstOrDefault<DXStdOAuth2.Module.BusinessObjects.ApplicationUserLoginInfo>(userLoginInfo =>
                 userLoginInfo.LoginProviderName == loginProviderName &&
                userLoginInfo.ProviderUserKey == providerUserId);
            }
       }
     };
});

 

 

 

 

 

  

posted @ 2021-06-08 20:11  eccorp  阅读(262)  评论(0编辑  收藏  举报