ArcGIS Server se puede proteger con usuarios y roles de un almacén de identidades personalizado.
Nota:
Los almacenes de identidades personalizados han quedado obsoletos en la versión 10.7. Consulte Acceso y autenticación en ArcGIS Server para ver la configuración de seguridad recomendada.
Para ello, ArcGIS Server ofrece soporte para la pertenencia y proveedores de roles ASP.NET.
Los pasos principales para configurar un almacén de identidades personalizado usando ASP.NET son:
- Implementar un proveedor personalizado de ASP.NET para ArcGIS Server.
Nota:
Su proveedor personalizado de ASP.NET debe usar .NET Framework 4.5.1 o versiones posteriores.
- Implemente el proveedor personalizado en ArcGIS Server.
- Configure ArcGIS Server para utilizar el proveedor personalizado.
Después de configurar el proveedor personalizado de ASP.NET, puede ver su contenido en el Administrador y, a continuación, utilice las funciones de almacenamiento personalizado para establecer permisos en los servicios Web.
Implementar un proveedor personalizado de ASP.NET para ArcGIS Server
Si desea utilizar usuarios de un almacén de identidades personalizado para proteger ArcGIS Server, debe desarrollar un proveedor de pertenencia ASP.NET que implemente los siguientes métodos:
- FindUsersByName
- GetAllUsers
- GetUser
- ValidateUser
Si desea utilizar roles de un almacén de identidades personalizado para proteger ArcGIS Server, debe desarrollar un proveedor de roles ASP.NET que implemente los siguientes métodos:
- GetAllRoles
- GetRolesForUser
- GetUsersInRole
Nota:
Al implementar un proveedor de ASP.NET personalizado, el planteamiento recomendado es exponerlo a ArcGIS Server como un almacén de identidades de solo lectura. Si desea crear y modificar información de usuarios/roles a través de ArcGIS Server, necesitará implementar métodos adicionales en su proveedor ASP.NET personalizado, como se muestra en la implementación de ejemplo que aparece a continuación.
Implemente el proveedor personalizado en ArcGIS Server
- Cree su proveedor personalizado en un archivo .dll y cópielo en el equipo que aloja ArcGIS Server.
- Instalar el proveedor personalizado .dll en el GAC.
Ejemplo: gacutil /i MyCustomProvider.dll
Configurar ArcGIS Server para utilizar el proveedor personalizado
Para configurar ArcGIS Server para usar su proveedor ASP.NET personalizado, debe especificar el atributo de tipo del proveedor ASP.NET. Opcionalmente, también puede especificar cualquier propiedad de tiempo de ejecución que requiera su proveedor.
- Abra el Directorio de administrador de ArcGIS Server e inicie sesión.
- Haga clic en seguridad > config > updateIdentityStore.
- Introduzca la configuración Almacén de usuarios en formato JSON. La sintaxis es:
{ "type": "ASP_NET", "class": "{Membership provider's type attribute value}", "properties": { "Property One": "value", .... "Property X": "value" } }
- Introduzca la configuración del Almacén de roles en formato JSON. La sintaxis es:
{ "type": "ASP_NET", "class": "{Role provider's type attribute value}", "properties": { "Property One": "value", .... "Property X": "value" } }
- Haga clic en Actualizar para guardar la configuración.
Implementación de ejemplo
A continuación, aparece una implementación de ejemplo de un proveedor de pertenencia y roles ASP.NET para ArcGIS Server en C#. Este ejemplo utiliza un proveedor ASP.NET que se puede modificar. El planteamiento recomendado es exponer el proveedor a ArcGIS Server como un almacén de identidades de solo lectura.
- Proveedor de pertenencia de ejemplo
- Proveedor de roles de ejemplo
- JSON de almacén de identidades de ejemplo
- Almacén de identidades de ejemplo
Proveedor de pertenencia de ejemplo
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 */
}
Proveedor de roles de ejemplo
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 de configuración de almacén de identidades de ejemplo
JSON de almacén de usuarios
{
"type": "ASP_NET", "class": "CustomProvider.XmlMembershipProvider,CustomProvider,Version=1.0.0.0,Culture=Neutral,PublicKeyToken=b02390eb7f2c02c4", "properties": {
"FileName": "C:\\arcgisserver\\identitystore\\IdentityStore.xml"
}
}
JSON de almacén de roles
{
"type": "ASP_NET", "class": "CustomProvider.XmlRoleProvider,CustomProvider,Version=1.0.0.0,Culture=Neutral,PublicKeyToken=b02390eb7f2c02c4", "properties": {
"FileName": "C:\\arcgisserver\\identitystore\\IdentityStore.xml"
}
}
Almacén de identidades de ejemplo
<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>