ArcGIS Server peut être sécurisé grâce à des utilisateurs et rôles provenant d’un magasin d’identifiants personnalisé.
Héritage :
Les magasins d’identités personnalisés ne sont pas pris en charge au-delà du cycle de versions 10.7.x. Consultez la rubrique Contrôler l’accès dans ArcGIS Server pour les configurations de sécurité recommandées.
Pour ce faire, ArcGIS Server assure la prise en charge des fournisseurs de rôles et d’appartenance ASP.NET.
Les principales étapes de la configuration d’un magasin d’identités personnalisé avec ASP.NET sont les suivantes :
- Implémenter un fournisseur personnalisé ASP.NET pour ArcGIS Server.
Remarque :
Votre fournisseur personnalisé ASP.NET doit utiliser .NET Framework 4.5.1 une version ultérieure.
- Déployer le fournisseur personnalisé sur ArcGIS Server.
- Configurer ArcGIS Server de manière à utiliser le fournisseur personnalisé.
Après avoir configuré le fournisseur ASP.NET personnalisé, vous pouvez en afficher le contenu dans le Gestionnaire et utiliser les rôles du magasin personnalisé pour définir des autorisations sur les services Web.
Implémenter un fournisseur ASP.NET personnalisé pour ArcGIS Server
Pour utiliser des utilisateurs provenant d’un magasin d’identités personnalisé pour sécuriser ArcGIS Server, vous devez développer un fournisseur d’appartenance ASP.NET qui implémente les méthodes suivantes :
- FindUsersByName
- GetAllUsers
- GetUser
- ValidateUser
Pour utiliser des rôles provenant d’un magasin d’identités personnalisé pour sécuriser ArcGIS Server, vous devez développer un fournisseur de rôles ASP.NET qui implémente les méthodes suivantes :
- GetAllRoles
- GetRolesForUser
- GetUsersInRole
Remarque :
Lorsque vous implémentez un fournisseur ASP.NET personnalisé, l’approche recommandée consiste à le proposer dans ArcGIS Server en tant que magasin d’identifiants en lecture seule. Pour créer et modifier des informations utilisateur/rôle via ArcGIS Server, vous devez mettre en œuvre des méthodes supplémentaires dans votre fournisseur ASP.NET personnalisé comme indiqué dans l’exemple de mise en œuvre ci-dessous.
Déployer le fournisseur personnalisé sur ArcGIS Server
- Créez votre fournisseur personnalisé dans un fichier .dll et copiez-le sur l’ordinateur où est hébergé ArcGIS Server.
- Installez le fichier .dll du fournisseur personnalisé dans le GAC.
Exemple : gacutil /i MyCustomProvider.dll
Configurer ArcGIS Server de manière à utiliser le fournisseur personnalisé
Pour configurer ArcGIS Server de manière à utiliser votre fournisseur ASP.NET personnalisé, vous devez spécifier l’attribut de type du fournisseur ASP.NET. Vous pouvez également fournir des propriétés d'exécution, par exemple les informations d'identification de l'utilisateur, qui sont demandées par votre fournisseur.
- Ouvrez le répertoire administrateur de ArcGIS Server et connectez-vous.
- Cliquez sur security > config > updateIdentityStore.
- Saisissez la configuration User Store (Magasin d’utilisateurs) au format JSON. Cette syntaxe est la suivante :
{ "type": "ASP_NET", "class": "{Membership provider's type attribute value}", "properties": { "Property One": "value", .... "Property X": "value" } }
- Saisissez la configuration Role Store (Magasin de rôles) au format JSON. Cette syntaxe est la suivante :
{ "type": "ASP_NET", "class": "{Role provider's type attribute value}", "properties": { "Property One": "value", .... "Property X": "value" } }
- Cliquez sur Update (Mettre à jour) pour enregistrer votre configuration.
Exemple d'implémentation
Voici un exemple d’implémentation d’un fournisseur d’appartenance et de rôles ASP.NET pour ArcGIS Server en C#. L’exemple utilise un fournisseur ASP.NET que vous pouvez modifier. L’approche recommandée consiste à proposer le fournisseur dans ArcGIS Server en tant que magasin d’identifiants en lecture seule.
- Exemple de fournisseur d’appartenance
- Exemple de fournisseur de rôles
- Exemple JSON de magasin d’identifiants
- Exemple de magasin d’identifiants
Exemple de fournisseur d'appartenance
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 */
}
Exemple de fournisseur de rôles
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;
}
}
}
Exemple de configuration JSON d'un magasin d'identifiants
Magasin d'utilisateurs JSON
{
"type": "ASP_NET", "class": "CustomProvider.XmlMembershipProvider,CustomProvider,Version=1.0.0.0,Culture=Neutral,PublicKeyToken=b02390eb7f2c02c4", "properties": {
"FileName": "C:\\arcgisserver\\identitystore\\IdentityStore.xml"
}
}
Magasin de rôles JSON
{
"type": "ASP_NET", "class": "CustomProvider.XmlRoleProvider,CustomProvider,Version=1.0.0.0,Culture=Neutral,PublicKeyToken=b02390eb7f2c02c4", "properties": {
"FileName": "C:\\arcgisserver\\identitystore\\IdentityStore.xml"
}
}
Exemple de magasin d'identifiants
<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>
Vous avez un commentaire à formuler concernant cette rubrique ?