Skip To Content

使用 ASP.NET 设置自定义标识存储

在本主题中

ArcGIS Server 可通过自定义标识存储中的用户和角色获得安全保护。为此,ArcGIS Server 支持 ASP.NET 成员资格和角色提供程序。

要使用 ASP.NET 配置自定义标识存储,请执行以下步骤:

配置自定义 ASP.NET 提供程序后,可以在管理器中查看其内容,并使用自定义存储中的角色来设置 Web 服务上的权限。

为 ArcGIS Server 实施一个自定义的 ASP.NET 提供程序

要通过自定义标识存储中的用户来确保 ArcGIS Server 的安全性,必须开发一个实施以下方法的 .NET framework 3.5 ASP.NET 成员提供程序:

  • FindUsersByName
  • GetAllUsers
  • GetUser
  • ValidateUser

要通过自定义标识存储中的角色来确保 ArcGIS Server 的安全性,则必须开发一个实施以下方法的 .NET framework 3.5 ASP.NET 角色提供程序:

  • GetAllRoles
  • GetRolesForUser
  • GetUsersInRole

注:

实施自定义 ASP.NET 提供程序时,建议的方法是将其在 ArcGIS Server 中以只读的标识存储形式进行显示。如果您希望通过 ArcGIS Server 创建和修改用户/角色信息,则需要在自定义的 ASP.NET 提供程序中实施其他方法,正如以下实现示例所示。

在 ArcGIS Server 上部署自定义提供程序

  1. 在 .dll 文件中构建自定义提供程序,并将其复制到托管 ArcGIS Server 的计算机中。
  2. 在 GAC 中安装自定义提供程序 .dll。

    示例:gacutil /i MyCustomProvider.dll

配置 ArcGIS Server 以使用自定义提供程序

要将 ArcGIS Server 配置为使用自定义 ASP.NET 提供程序,必须指定 ASP.NET 提供程序的类型属性。作为可选项,还可指定提供程序所需的任意运行时属性,例如用户凭据等。

  1. 打开“ArcGIS Server 管理员目录”并登录。
  2. 单击安全性 > 配置 > 更新标识存储
  3. 以 JSON 格式输入用户存储配置。该语法为:
    {
    	"type": "ASP_NET",
    	"class": "{Membership provider's type attribute value}",
    	"properties": {
    		"Property One": "value",
       ....
    		"Property X": "value"
    	}
    }
  4. 以 JSON 格式输入角色存储配置。该语法为:
    {
    	"type": "ASP_NET",
    	"class": "{Role provider's type attribute value}",
    	"properties": {
    		"Property One": "value",
       ....
    		"Property X": "value"
    	}
    }
  5. 单击更新保存配置。

实现示例

以下是使用 C# 语言的 ArcGIS Server 的 ASP.NET 成员和角色提供程序的实现示例。示例使用的是可修改的 ASP.NET 提供程序。建议的方法是将提供程序在 ArcGIS Server 中以只读的标识存储形式进行显示。

示例成员提供程序

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration.Provider;
using System.Linq;
using System.Text;
using System.Web.Security;
using System.Web.Hosting;
using System.Web.Management;
using System.Web;
using System.Security.Permissions;
using System.Xml;
using System.IO; 

namespace CustomProvider
{
    public class XmlMembershipProvider : MembershipProvider
    {
        private string _appName = null;
        private string _providerName = null;

        private string _userStore;

        public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
        {
            if (config == null)
                throw new ArgumentNullException("config");

            if (String.IsNullOrEmpty(name))
                name = "CustomProvider.XmlMembershipProvider";

            base.Initialize(name, config);
            _providerName = name;

            string path = config["FileName"];
            if (String.IsNullOrEmpty(path))
                path = "C:\\temp\\IdentityStore.xml";
            else
                _userStore = path;     

            FileIOPermission permission = new FileIOPermission(FileIOPermissionAccess.Write,_userStore);
            
            permission.Demand();
        }

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

        public override bool ChangePassword(string username, string oldPassword, string newPassword)
        {
            throw new NotImplementedException();
        }

        public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
        {
            return true;
        }

        public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
        {
            MembershipUser newUser = new MembershipUser(
                _providerName,
                username,
                null,
                email,
                "Secret Question",
                username,
                true,
                false,
                DateTime.Now,               // creationDate
                DateTime.Now,               // lastLoginDate
                DateTime.Now,               // lastActivityDate
                DateTime.Now,               // lastPasswordChangedDate
                new DateTime(2000, 1, 1)    // lastLockoutDate
                );

            XmlDocument _usersList = ReadUsersFromStore();

            XmlNode newUserNode = _usersList.CreateNode(XmlNodeType.Element, "User", null);

            XmlNode newUserInfoNode = _usersList.CreateElement("UserName");
            newUserInfoNode.InnerText = username;
            newUserNode.AppendChild(newUserInfoNode);

            newUserInfoNode = _usersList.CreateElement("Password");
            newUserInfoNode.InnerText = password;
            newUserNode.AppendChild(newUserInfoNode);

            newUserInfoNode = _usersList.CreateElement("FullName");
            newUserInfoNode.InnerText = username;
            newUserNode.AppendChild(newUserInfoNode);

            newUserInfoNode = _usersList.CreateElement("Email");
            newUserInfoNode.InnerText = email;
            newUserNode.AppendChild(newUserInfoNode);

            newUserInfoNode = _usersList.CreateElement("Roles");
            newUserNode.AppendChild(newUserInfoNode);

            _usersList.DocumentElement.AppendChild(newUserNode);

            _usersList.Save(_userStore);
                  
            status = MembershipCreateStatus.Success;

            return newUser;
            
        }

        public override bool DeleteUser(string username, bool deleteAllRelatedData)
        {
            XmlDocument _usersList = ReadUsersFromStore();

            XmlNode nodeToDelete = _usersList.SelectSingleNode(string.Format("//*[UserName=\"{0}\"]", username));

            if (nodeToDelete != null)
            {
                _usersList.FirstChild.RemoveChild(nodeToDelete);
                _usersList.Save(_userStore);
                return true;
            }
            else
                return false;
        }

        public override bool EnablePasswordReset
        {
            get { return true; }
        }

        public override bool EnablePasswordRetrieval
        {
            get { return true; }
        }

        public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
        {
            throw new NotImplementedException();
        }

        public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
        {

            MembershipUserCollection usersColl = new MembershipUserCollection();
            XmlNodeList matchingNodes = null;

            XmlDocument _usersList = ReadUsersFromStore();
            matchingNodes = _usersList.SelectNodes(string.Format("//*[contains(UserName,\"{0}\")]", usernameToMatch));

            totalRecords = 0;

            if (matchingNodes != null && matchingNodes.Count != 0)
            {
                totalRecords = matchingNodes.Count;

                foreach (XmlNode node in matchingNodes)
                {
                    MembershipUser newUser = new MembershipUser(
                        _providerName,
                        node["UserName"].InnerText,
                        null,
                        node["Email"].InnerText,
                        "",
                        node["UserName"].InnerText,
                        true,
                        false,
                        DateTime.Now,               // creationDate
                        DateTime.Now,               // lastLoginDate
                        DateTime.Now,               // lastActivityDate
                        DateTime.Now,               // lastPasswordChangedDate
                        new DateTime(2000, 1, 1)    // lastLockoutDate
                        );

                    usersColl.Add(newUser);
                }
            }

            return usersColl;
        }

        public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
        {

            MembershipUserCollection usersColl = new MembershipUserCollection();

            XmlDocument _usersList = ReadUsersFromStore();

            XmlNodeList userNodes = _usersList.GetElementsByTagName("User");

            foreach (XmlNode node in userNodes)
            {
                MembershipUser newUser = new MembershipUser(
                    _providerName,
                    node["UserName"].InnerText,
                    null,
                    node["Email"].InnerText,
                    "Secret Question",
                    node["UserName"].InnerText,
                    true,
                    false,
                    DateTime.Now,               // creationDate
                    DateTime.Now,               // lastLoginDate
                    DateTime.Now,               // lastActivityDate
                    DateTime.Now,               // lastPasswordChangedDate
                    new DateTime(2000, 1, 1)    // lastLockoutDate
                    );

                usersColl.Add(newUser);                 
            }

            totalRecords = userNodes.Count;

            return usersColl;                  
        }

        public override int GetNumberOfUsersOnline()
        {
            throw new NotImplementedException();
        }

        public override string GetPassword(string username, string answer)
        {
            throw new NotImplementedException();
        }

        public override MembershipUser GetUser(string username, bool userIsOnline)
        {
            XmlDocument _usersList = ReadUsersFromStore();

            MembershipUser user = null;

            XmlNode node = _usersList.SelectSingleNode(string.Format("//*[UserName=\"{0}\"]", username));

            if (node != null)
            {

                user = new MembershipUser(
                    _providerName,
                    node["UserName"].InnerText,
                    null,
                    node["Email"].InnerText,
                    "Secret Question",
                    node["UserName"].InnerText,
                    true,
                    false,
                    DateTime.Now,               // creationDate
                    DateTime.Now,               // lastLoginDate
                    DateTime.Now,               // lastActivityDate
                    DateTime.Now,               // lastPasswordChangedDate
                    new DateTime(2000, 1, 1)    // lastLockoutDate
                    );
            }

            return user;

        }

        public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
        {
            throw new NotImplementedException();
        }

        public override string GetUserNameByEmail(string email)
        {
            throw new NotImplementedException();
        }

        public override int MaxInvalidPasswordAttempts
        {
            get { throw new NotImplementedException(); }
        }

        public override int MinRequiredNonAlphanumericCharacters
        {
            get { throw new NotImplementedException(); }
        }

        public override int MinRequiredPasswordLength
        {
            get { throw new NotImplementedException(); }
        }

        public override int PasswordAttemptWindow
        {
            get { throw new NotImplementedException(); }
        }

        public override MembershipPasswordFormat PasswordFormat
        {
            get { throw new NotImplementedException(); }
        }

        public override string PasswordStrengthRegularExpression
        {
            get { throw new NotImplementedException(); }
        }

        public override bool RequiresQuestionAndAnswer
        {
            get { throw new NotImplementedException(); }
        }

        public override bool RequiresUniqueEmail
        {
            get { throw new NotImplementedException(); }
        }

        public override string ResetPassword(string username, string answer)
        {
            throw new NotImplementedException();
        }

        public override bool UnlockUser(string userName)
        {
            throw new NotImplementedException();
        }

        public override void UpdateUser(MembershipUser user)
        {
            XmlDocument _usersList = ReadUsersFromStore();

            String username = user.UserName;
            XmlNode nodeToUpdate = _usersList.SelectSingleNode(string.Format("//*[UserName=\"{0}\"]", username));

            if (nodeToUpdate != null)
            {
                nodeToUpdate["Email"].InnerText = user.Email;
                _usersList.Save(_userStore);
            }
            
        }

        public override bool ValidateUser(string username, string password)
        {
            XmlDocument _usersList = ReadUsersFromStore();

            XmlNode node = _usersList.SelectSingleNode(string.Format("//*[UserName=\"{0}\"]", username));

            if (node != null && username.Equals(node["UserName"].InnerText) && password.Equals(node["Password"].InnerText))
                return true;
            else
                return false;
        }

        private XmlDocument ReadUsersFromStore()
        {
            XmlDocument _usersList = new XmlDocument();
            _usersList.Load(_userStore);
            return _usersList;
        }

    } /* XmlFileMembershipProvider */
}

示例角色提供程序

using System;
using System.Collections.Generic;
using System.Collections;
using System.Collections.Specialized;
using System.Configuration.Provider;
using System.Linq;
using System.Text;
using System.Web.Security;
using System.Web.Hosting;
using System.Web.Management;
using System.Web;
using System.Security.Permissions;
using System.Xml;
using System.IO; 

namespace CustomProvider
{
    public class XmlRoleProvider : RoleProvider
    {
        private string _appName = null;
        private string _providerName = null;

        private string _roleStore = null;
        XmlDocument _xmlRoleList = null;

        public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
        {
            if (config == null)
                throw new ArgumentNullException("config");

            if (String.IsNullOrEmpty(name))
                name = "CustomProvider.XmlRoleProvider";

            base.Initialize(name, config);
            _providerName = name;

            string path = config["FileName"];
            if (String.IsNullOrEmpty(path))
                path = "C:\\temp\\IdentityStore.xml";
            else
                _roleStore = path;

            FileIOPermission permission = new FileIOPermission(FileIOPermissionAccess.Write, _roleStore);

            permission.Demand();
        }

        public override void AddUsersToRoles(string[] usernames, string[] roleNames)
        {
            XmlDocument userRoleDoc = ReadUserRolesFromStore();
            foreach (string user in usernames)
            {
                XmlNode userRoleNode = userRoleDoc.SelectSingleNode(string.Format("//*[UserName=\"{0}\"]", user));

                String roleList = userRoleNode["Roles"].InnerText;

                foreach (string role in roleNames)
                {
                    if(roleList.Equals(""))
                        roleList += role;
                    else
                        roleList += "," + role;
                }

                userRoleNode.RemoveChild(userRoleNode.LastChild);

                XmlNode newRoleListNode = userRoleDoc.CreateElement("Roles");
                newRoleListNode.InnerText = roleList;
                userRoleNode.AppendChild(newRoleListNode);
            }
            userRoleDoc.Save(_roleStore);
        }

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

        public override void CreateRole(string roleName)
        {
            ReadRolesFromStore();

            XmlNode newRoleNode = _xmlRoleList.CreateNode(XmlNodeType.Element, "Role", null);

            XmlNode newUserInfoNode = _xmlRoleList.CreateElement("RoleName");
            newUserInfoNode.InnerText = roleName;
            newRoleNode.AppendChild(newUserInfoNode);

            _xmlRoleList.DocumentElement.AppendChild(newRoleNode);

            _xmlRoleList.Save(_roleStore);
        }

        public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
        { 
            ReadRolesFromStore();

            XmlNode nodeToDelete = _xmlRoleList.SelectSingleNode(string.Format("//*[RoleName=\"{0}\"]", roleName));

            if (nodeToDelete != null)
            {
                _xmlRoleList.FirstChild.RemoveChild(nodeToDelete);
                _xmlRoleList.Save(_roleStore);
                return true;
            }
            else
                return false;
        }

        public override string[] FindUsersInRole(string roleName, string usernameToMatch)
        {
            throw new NotImplementedException();
        }

        public override string[] GetAllRoles()
        {
            ArrayList roleArrayList = ReadRolesFromStore();

            return (string[])roleArrayList.ToArray(typeof(string));
        }

        public override string[] GetRolesForUser(string username)
        {
            XmlDocument xmlUserRolesList = ReadUserRolesFromStore();

            XmlNode userRoleNode = xmlUserRolesList.SelectSingleNode(string.Format("//*[UserName=\"{0}\"]", username));

            String[] roleList = userRoleNode["Roles"].InnerText.Split(',');

            if (roleList[0] == "")
                return new string[0];
            else
                return roleList;
        }

        public override string[] GetUsersInRole(string roleName)
        {
            ArrayList userList = new ArrayList();

            XmlDocument xmlUserRolesList = ReadUserRolesFromStore();

            XmlNodeList userRoleNodes = xmlUserRolesList.GetElementsByTagName("User");

            if (userRoleNodes != null)
            {
                int numRoles = userRoleNodes.Count;
                foreach(XmlNode node in userRoleNodes) {
                    String[] roleList = node["Roles"].InnerText.Split(',');

                    foreach (string item in roleList)
                    {
                        if (item.Equals(roleName))
                        {
                            String username = node["UserName"].InnerText;
                            userList.Add(username);
                            break;
                        }
                    }
                }
            }

            return (string[])userList.ToArray(typeof(string));
        }

        public override bool IsUserInRole(string username, string roleName)
        {
            throw new NotImplementedException();
        }

        public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
        {
            XmlDocument userRoleDoc = ReadUserRolesFromStore();
            foreach (string user in usernames)
            {
                XmlNode userRoleNode = userRoleDoc.SelectSingleNode(string.Format("//*[UserName=\"{0}\"]", user));

                ArrayList roleList = new ArrayList();
                roleList.AddRange(userRoleNode["Roles"].InnerText.Split(','));

                foreach (string role in roleNames)
                {
                    if (roleList.Contains(role))
                        roleList.Remove(role);
                }

                userRoleNode.RemoveChild(userRoleNode.LastChild);

                XmlNode newRoleListNode = userRoleDoc.CreateElement("Roles");
                if( roleList.Count > 0 )
                newRoleListNode.InnerText = string.Join(",", (string[])roleList.ToArray(Type.GetType("System.String")));
                userRoleNode.AppendChild(newRoleListNode);
            }
            userRoleDoc.Save(_roleStore);
        }

        public override bool RoleExists(string roleName)
        {
            throw new NotImplementedException();
        }

        private ArrayList ReadRolesFromStore()
        {
            _xmlRoleList = new XmlDocument();
            _xmlRoleList.Load(_roleStore);

            XmlNodeList roleNodes = _xmlRoleList.GetElementsByTagName("Role");

            ArrayList roleArrayList = null;

            if (roleNodes != null)
            {
                roleArrayList = new ArrayList();

                foreach (XmlNode node in roleNodes)
                {
                    roleArrayList.Add( node["RoleName"].InnerText);
                }
            }
            return roleArrayList;
        }

        private XmlDocument ReadUserRolesFromStore()
        {
            XmlDocument xmlUserRolesList = new XmlDocument();
            xmlUserRolesList.Load(_roleStore);

            return xmlUserRolesList;
        }
    }
}

示例标识存储配置 JSON

用户存储 JSON

{
  "type": "ASP_NET",
  "class": "CustomProvider.XmlMembershipProvider,CustomProvider,Version=1.0.0.0,Culture=Neutral,PublicKeyToken=b02390eb7f2c02c4",
  "properties": {
    "FileName": "C:\\arcgisserver\\identitystore\\IdentityStore.xml"
  }
}

角色存储 JSON

{
  "type": "ASP_NET",
  "class": "CustomProvider.XmlRoleProvider,CustomProvider,Version=1.0.0.0,Culture=Neutral,PublicKeyToken=b02390eb7f2c02c4",
  "properties": {
    "FileName": "C:\\arcgisserver\\identitystore\\IdentityStore.xml"
  }
}

示例标识存储

<IdentityStore>
  <User>
    <UserName>amy</UserName>
    <Password>amy</Password>
    <FullName>amy</FullName>
    <Email>amy@amy.amy</Email>
    <Roles>admins</Roles>
  </User>
  <Role>
    <RoleName>admins</RoleName>
  </Role>
</IdentityStore>