ASP.net角色和项目

 2023-02-16    357  

问题描述

编辑 – 重写我的原始问题以提供更多信息


背景信息
在我的工作中,我正在为客户开发ASP.NET Web应用程序.在我们的实施中,我们使用成员Hhipproviders和Roleproviders等技术等技术.一切顺利,直到我在配置角色方面遇到一些困难,因为角色不是整个系统的,而是与客户帐户和项目有关的.

ASP.net角色和项目

我不能命名我们的确切设置/公式,因为我认为我们的公司不会批准…

什么是客户/项目?
我们公司每年(或其他间隔)为客户提供管理信息.
在我们的系统中,客户/合同包括:

  • 一个帐户:有关公司的信息
  • 每个帐户,一个或多个产品:我们将提供的管理信息包
  • 每种产品,一个或多个测量值:一段时间,我们收集并报告数据

Extranet站点设置
最终,我们希望所有客户能够通过我们的在线系统访问其管理信息.外部集由两个站点组成:

  • 公司网站:提供帐户信息和产品的概述
  • 测量站点:选择了有关此期间的测量,详细信息

测量位点是外部集群中最有趣的部分.我们将为新概述,报告,管理和维护对研究重要的资源创建子模型.

我们的Visual Studio解决方案由许多项目组成.一个名为Portal的Web应用程序的基础.站点和模块是该应用程序中的虚拟目录(使得在事物中共享主页更容易).

什么样的角色?
以下用户(读:角色)将使用系统:

  • 管理员:开发用户:)(不相关,完全访问)
  • 员工:我们公司的员工(不相关,完全访问)
  • 客户超级用户:顶级管理人员(完全访问其帐户/测量)
  • 客户联系人:主要联系人(完全访问其测量)
  • 客户经理:部门经理(有限的访问,测量的具体数据)

asp.net用户呢?
该系统将拥有许多ASP.NET用户,让我们专注于客户用户:

  • 帐户之间未共享用户
  • 超级用户X自动可以访问所有(和新的)测量
  • 用户y可以是测量1的主要接触,但没有任何作用的测量作用2
  • 用户y可以是测量1的主要接触,但具有测量经理角色2
  • 部门经理是许多个人用户(每个测量),如果经理Z有测量1登录1,我们想再次使用该登录名,如果他参与度量2.

URL结构
这些是我们应用程序中的典型URL:

  • http://host/login – 登录屏幕
  • http://host/project – 帐户/产品概述屏幕(测量选择)
  • http://host/project/project/project/1000 – 测量(ID:1000)详细信息
  • http://host/project/project/1000/planning planning planning plansview(用于主要联系/超级用户)
  • http://http://host/project/project/project/1000/报告报告下载(经理部门X可以仅访问报告x)

我们还将创建一个文档URL,您可以在其中通过其GUID请求特定文档.该系统将必须检查用户是否对文档有权.该文档与测量,用户或特定角色有关该文档的特定权利.

有什么问题? (最后;))
角色不足以确定允许用户查看/访问/下载特定项目的角色.说经理可以访问某个导航项目是不够的.当用户请求测量1000时,我们必须检查用户不仅具有经理角色,而且还必须担任测量1000的经理角色.

总结:

  1. 我们如何将用户限制为他们的帐户/测量?
    (请记住,超级用户看到所有测量值,一些经理仅特定的测量值)

  2. 我们如何在产品/测量水平上应用角色?
    (用户X可以是测量1的初级接触,但仅是测量的经理2)

  3. 我们如何限制管理器访问报告屏幕的访问,而仅限制了部门的报告?

全部具有ASP.NET类的魔力,也许具有自定义的Roleprovider实现.

类似的stackoverflow问题/问题
asp.net角色的类型

推荐答案

您从我看到的各个帖子中寻求的是一种自定义角色机制,或者是另一种方式,即一种自定义授权机制.身份验证仍然可以使用标准的SQLMembersHippRovider.

我不确定标准角色提供商是否会为您提供所需的内容,因为授权需要您具有项目的上下文.但是,您可以调查编写自定义Roleprovider,以查看是否可以创建一些可以做到这一点的自定义方法.尽管如此,出于回答问题的目的,我将假设您不能使用sqlroleprovider.

所以,这里有一些潜在的模式:

Create Table Companies
(
    Id int not null Primary Key
    , ...
)
Create Table Projects
(
    Id int not null Primary Key
    , PrimaryContactUserId uniqueidentifier
    , ...
    , Constraint FK_Projects_aspnet_Users
        Foreign Key ( PrimaryContactUserId )
        References dbo.aspnet_Users ( UserId )
)
Create Table Roles
(
    Name nvarchar(100) not null Primary Key
    , ...
)

Create Table ProjectCompanyRoles
(
    CompanyId int not null
    , ProjectId int not null
    , RoleName nvarchar(100) not null
    , Constraint FK_...
)

正如我之前说过的,在项目表中纳入初级接触的原因是确保给定项目只有一个.如果将其包含在角色中,则必须包括一堆箍跳跃代码,以确保项目不超过一个主键.如果是这种情况,然后从项目表中取出初级分子,并使其成为角色.

授权检查将需要针对ProjectCompanyroles的查询.同样,在使用默认角色提供商有问题的项目和公司的上下文中增加了上下文.如果您想将.NET机制用于角色和身份验证,则必须实现自己的自定义Roleprovider.

其他推荐答案

这正是需要自定义Roleprovider的场景.您设计数据库模式以支持您的案件(您可能需要创建一个名为Projectrole的表和一个称为Companyrole的表).

这里有几件事可以让您入门(链接可以在底部提供帮助):

将此部分添加到您的web.config:

<roleManager defaultProvider="MyRoleProvider" enabled="true">
    <providers>
        <add name="MyRoleProvider" type="MyNamespace.MyRoleProvider, MyAssembly, Version=1.0.0.0" description="My Custom Role Provider." enableSearchMethods="false" applicationName="MyApplicationName"/>
    </providers>
</roleManager>

那么这就是MyRoleProvider类的样子(或多或少):

(注意:您的班级必须从System.Web.Security.RoleProvider继承)

namespace MyNamespace
{
    ...

    public class MyRoleProvider : System.Web.Security.RoleProvider
    {
        private string _applicationName;

        public MyRoleProvider()
        {
        }

        public override string ApplicationName
        {
            get
            {
                return _applicationName;
            }
            set
            {
                _applicationName = value;
            }
        }

        ...

    }
}

然后,您只需要覆盖一些方法即可为您的应用程序提供所需的信息:

至少要覆盖这两种方法:

  • getRolesForuser
  • isuserinrole

但是,如果您想:

,也可以覆盖这些方法

  • adduserstoroles
  • from fromroles
  • finduserinrole
  • getusersinrole
  • getallroles
  • createrole
  • deleterole
  • Roleexists

也不是我答应的链接:

  • 实施角色提供者
  • 创建定制的Roleprovider for Aspreprovider for Asp.net wors for asp.net&asp.net worsers&asp.net&asp.net允许和允许
  • 示例角色提供的实施 /li>

其他推荐答案

免责声明:根据评论的交换,我完全对自己进行了混蛋,几乎是解决方案解决方案已经得出,并且已经清除了此答案所有的Asshattery和现在仅包含可能解决OP问题的测试方案. ;-)

对托马斯保持冷静而不放弃的荣誉.


z-告诉我我是否理解你:

您想要所有应用程序/项目的中央会员提供商,并且每个应用程序/项目都有独特的角色筒仓?

您可能不需要实施自定义提供商.标准堆栈可以用 次要存储程序修改 就足够了.最好尝试和甜言蜜语,以完成您想做的事情.它导致工作更少,睡眠更多.

提议的解决方案的显着方面:

  • 一个常见的数据库和连接字符串,
  • 常见的会员申请名称,
  • 一个通用的MachineKey部分,以便每个站点都使用普通表格票.
  • a unique 角色提供商应用程序名称(或您所说的ProjectID).
  • 修改后的aspnet_Users_DeleteUser sproc.

ASPNET_USERS_DELETEUSER的修改涉及清理由角色和配置文件提供商动态创建的ASPNET_USERS中的用户参考,并带有某种条件,即特定的ASPNET_DB实例是由Commun HippRovider 拥有的,仅由CommunHippRovider,仅由Common HippRovider和使用该常见会员资格提供者的网站应连接到它.

将此解决方案映射到OP方案:

每个帐户/公司都有一个不同的ASPNET_DB实例,并且” ProjectID”将映射到Rolemanager提供商元素的应用名称属性.

由于项目被”迁移”,因此他们被分配了一个新的ProjectID(应用程序名称),并且这样做的公司可以通过共同的会员提供者对迁移的项目进行身份验证,但原始项目的角色并未延续凭借独特的角色提供者.

所有标准会员管理策略,例如ASPNET配置工具,登录控件,CreateUser向导,会员功能(尤其是sigresship.deleteuser() – 谢谢Thomas)的行为会如预期的那样,没有任何修改.

配置文件可以在任一方向上实现,使用会员资格提供商的应用程序ID将允许配置文件数据跟随用户到任何关联的项目.使用角色提供商的独特ProjectID(应用程序名称)将允许每个项目中的每个用户分开配置文件.

更多的细节和测试是 在这里 ..

显着配置部分在下面列出,以下是修改的sproc.

web.config

<?xml version="1.0"?>
<configuration>
  <connectionStrings>
    <add name="testDb" providerName="System.Data.SqlClient" connectionString="Data Source=(local);Initial Catalog=__SingleAuthMultiRole;Integrated Security=True"/>
  </connectionStrings>
  <system.web>
    <compilation debug="true"/>

    <!-- this key is common all your apps - generate a new one @ http://www.developmentnow.com/articles/machinekey_generator.aspx -->
    <machineKey validationKey="841FEF8E55CD7963CE9EAFED329724667D62F4412F635815DFDDBE7D2D8D15819AE0FDF70CEF8F72792DBD7BF661F163B01134092CBCB80D7D71EAA42DFBF0A9" decryptionKey="FC9B0626224B0CF0DA68C558577F3E37723BB09AACE795498C4069A490690669" validation="SHA1" decryption="AES"/>

    <authorization>
      <deny users="?"/>
    </authorization>

    <authentication mode="Forms" />

    <membership defaultProvider="SqlProvider" userIsOnlineTimeWindow="15">
      <providers>
        <clear/>
        <add name="SqlProvider"
             type="System.Web.Security.SqlMembershipProvider"
             connectionStringName="testDb"
             applicationName="Common"  /> <!-- membership applicationName is common to all projects  -->
      </providers>
    </membership>

    <roleManager enabled="true" defaultProvider="SqlRoleManager" cacheRolesInCookie="true">
      <providers>
        <add name="SqlRoleManager"
             type="System.Web.Security.SqlRoleProvider"
             connectionStringName="testDb"
             applicationName="WebApplication1"/> <!-- roleManager applicationName is unique to each projects  -->
      </providers>
    </roleManager>

  </system.web>
</configuration>

用法:
在用Aspnet_regsql.exe配置ASPNET_DB之后,运行此脚本以修改ASPNET_USERS_DELETEUSER SPROC.

/*************************************************************/
/*************************************************************/
--- Modified DeleteUser SP

IF (EXISTS (SELECT name
              FROM sysobjects
             WHERE (name = N'aspnet_Users_DeleteUser')
               AND (type = 'P')))
DROP PROCEDURE [dbo].aspnet_Users_DeleteUser
GO
CREATE PROCEDURE [dbo].[aspnet_Users_DeleteUser]
    @ApplicationName  nvarchar(256),
    @UserName         nvarchar(256),
    @TablesToDeleteFrom int,
    @NumTablesDeletedFrom int OUTPUT    

AS
BEGIN
    -- holds all user id for username
    DECLARE @UserIds TABLE(UserId UNIQUEIDENTIFIER)
    SELECT  @NumTablesDeletedFrom = 0

    DECLARE @TranStarted   bit
    SET @TranStarted = 0

    IF( @@TRANCOUNT = 0 )
    BEGIN
        BEGIN TRANSACTION
        SET @TranStarted = 1
    END
    ELSE
    SET @TranStarted = 0

    DECLARE @ErrorCode   int
    DECLARE @RowCount    int

    SET @ErrorCode = 0
    SET @RowCount  = 0

    -- get all userid for username
    INSERT INTO @UserIds
    SELECT  UserId
    FROM    dbo.aspnet_Users 
    WHERE   LoweredUserName = LOWER(@UserName)

DECLARE @tmp int
SELECT @tmp = COUNT(*) FROM @UserIds
    IF NOT EXISTS(SELECT * FROM @UserIds)
        GOTO Cleanup

    -- Delete from Membership table if (@TablesToDeleteFrom & 1) is set
    IF ((@TablesToDeleteFrom & 1) <> 0 AND
        (EXISTS (SELECT name FROM sysobjects WHERE (name = N'vw_aspnet_MembershipUsers') AND (type = 'V'))))
    BEGIN
        DELETE FROM dbo.aspnet_Membership WHERE UserId IN (SELECT UserId from @UserIds)

        SELECT @ErrorCode = @@ERROR,
               @RowCount = @@ROWCOUNT

        IF( @ErrorCode <> 0 )
            GOTO Cleanup

        IF (@RowCount <> 0)
            SELECT  @NumTablesDeletedFrom = @NumTablesDeletedFrom + 1
    END

    -- Delete from aspnet_UsersInRoles table if (@TablesToDeleteFrom & 2) is set
    IF ((@TablesToDeleteFrom & 2) <> 0  AND
        (EXISTS (SELECT name FROM sysobjects WHERE (name = N'vw_aspnet_UsersInRoles') AND (type = 'V'))) )
    BEGIN
        DELETE FROM dbo.aspnet_UsersInRoles WHERE UserId IN (SELECT UserId from @UserIds)

        SELECT @ErrorCode = @@ERROR,
                @RowCount = @@ROWCOUNT

        IF( @ErrorCode <> 0 )
            GOTO Cleanup

        IF (@RowCount <> 0)
            SELECT  @NumTablesDeletedFrom = @NumTablesDeletedFrom + 1
    END

    -- Delete from aspnet_Profile table if (@TablesToDeleteFrom & 4) is set
    IF ((@TablesToDeleteFrom & 4) <> 0  AND
        (EXISTS (SELECT name FROM sysobjects WHERE (name = N'vw_aspnet_Profiles') AND (type = 'V'))) )
    BEGIN
        DELETE FROM dbo.aspnet_Profile WHERE UserId IN (SELECT UserId from @UserIds)

        SELECT @ErrorCode = @@ERROR,
                @RowCount = @@ROWCOUNT

        IF( @ErrorCode <> 0 )
            GOTO Cleanup

        IF (@RowCount <> 0)
            SELECT  @NumTablesDeletedFrom = @NumTablesDeletedFrom + 1
    END

    -- Delete from aspnet_PersonalizationPerUser table if (@TablesToDeleteFrom & 8) is set
    IF ((@TablesToDeleteFrom & 8) <> 0  AND
        (EXISTS (SELECT name FROM sysobjects WHERE (name = N'vw_aspnet_WebPartState_User') AND (type = 'V'))) )
    BEGIN
        DELETE FROM dbo.aspnet_PersonalizationPerUser WHERE UserId IN (SELECT UserId from @UserIds)

        SELECT @ErrorCode = @@ERROR,
                @RowCount = @@ROWCOUNT

        IF( @ErrorCode <> 0 )
            GOTO Cleanup

        IF (@RowCount <> 0)
            SELECT  @NumTablesDeletedFrom = @NumTablesDeletedFrom + 1
    END

    -- Delete from aspnet_Users table if (@TablesToDeleteFrom & 1,2,4 & 8) are all set
    IF ((@TablesToDeleteFrom & 1) <> 0 AND
        (@TablesToDeleteFrom & 2) <> 0 AND
        (@TablesToDeleteFrom & 4) <> 0 AND
        (@TablesToDeleteFrom & 8) <> 0 AND
        (EXISTS (SELECT UserId FROM dbo.aspnet_Users WHERE UserId IN (SELECT UserId from @UserIds))))
    BEGIN
        DELETE FROM dbo.aspnet_Users WHERE UserId IN (SELECT UserId from @UserIds)

        SELECT @ErrorCode = @@ERROR,
                @RowCount = @@ROWCOUNT

        IF( @ErrorCode <> 0 )
            GOTO Cleanup

        IF (@RowCount <> 0)
            SELECT  @NumTablesDeletedFrom = @NumTablesDeletedFrom + 1
    END

    IF( @TranStarted = 1 )
    BEGIN
        SET @TranStarted = 0
        COMMIT TRANSACTION
    END

    RETURN 0

Cleanup:
    SET @NumTablesDeletedFrom = 0

    IF( @TranStarted = 1 )
    BEGIN
        SET @TranStarted = 0
        ROLLBACK TRANSACTION
    END

    RETURN @ErrorCode

END
GO

以上所述是小编给大家介绍的ASP.net角色和项目,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对77isp云服务器技术网的支持!

原文链接:https://77isp.com/post/33981.html

=========================================

https://77isp.com/ 为 “云服务器技术网” 唯一官方服务平台,请勿相信其他任何渠道。