ArcGIS Server kann mit Benutzern und Rollen aus einem benutzerdefinierten Identitätsspeicher gesichert werden.
Ältere Versionen:
Benutzerdefinierte Identitätsspeicher werden nach dem Veröffentlichungszyklus 10.7.x nicht mehr unterstützt. Informationen zu den empfohlenen Sicherheitskonfigurationen finden Sie unter Steuern des Zugriffs in ArcGIS Server.
Zu diesem Zweck bietet ArcGIS Server Unterstützung für die ASP.NET-Mitgliedschafts- und Rollenanbieter.
Hauptschritte zum Konfigurieren eines benutzerdefinierten Identitätsspeichers mit ASP.NET:
- Implementieren Sie einen benutzerdefinierten ASP.NET-Anbieter für ArcGIS Server.
Hinweis:
Der benutzerdefinierte ASP.NET-Anbieter muss .NET Framework 4.5.1 oder höher verwenden.
- Stellen Sie den benutzerdefinierten Anbieter auf ArcGIS Server bereit.
- Konfigurieren Sie ArcGIS Server für die Verwendung des benutzerdefinierten Anbieters.
Nachdem Sie den benutzerdefinierten ASP.NET-Anbieter konfiguriert haben, können Sie dessen Inhalte in Manager anzeigen und die Rollen aus dem benutzerdefinierten Speicher verwenden, um Berechtigungen für Web-Services festzulegen.
Implementieren eines benutzerdefinierten ASP.NET-Anbieters für ArcGIS Server
Um zur Sicherung von ArcGIS Server Benutzer aus einem benutzerdefinierten Identitätsspeicher zu verwenden, müssen Sie einen ASP.NET-Mitgliedschaftsanbieter einrichten, der die folgenden Methoden implementiert:
- FindUsersByName
- GetAllUsers
- GetUser
- ValidateUser
Um zur Sicherung von ArcGIS Server Rollen aus einem benutzerdefinierten Identitätsspeicher zu verwenden, müssen Sie einen ASP.NET-Rollenanbieter einrichten, der die folgenden Methoden implementiert:
- GetAllRoles
- GetRolesForUser
- GetUsersInRole
Hinweis:
Wenn ein benutzerdefinierter ASP.NET-Anbieter implementiert wird, ist es empfehlenswert, ihn für ArcGIS Server als schreibgeschützten Identitätsspeicher bereitzustellen. Um Benutzer-/Rolleninformationen über ArcGIS Server zu erstellen oder zu ändern, müssen Sie zusätzliche Methoden in Ihren benutzerdefinierten ASP.NET-Anbieter implementieren, wie in der folgenden Beispielimplementierung.
Bereitstellen des benutzerdefinierten Anbieters auf ArcGIS Server
- Erstellen Sie den benutzerdefinierten Anbieter in einer .dll-Datei, und kopieren Sie sie auf den Computer mit ArcGIS Server.
- Installieren Sie die .dll für den benutzerdefinierten Anbieter im GAC.
Beispiel: gacutil /i MyCustomProvider.dll
Konfigurieren von ArcGIS Server für die Verwendung des benutzerdefinierten Anbieters
Um ArcGIS Server für die Verwendung Ihres benutzerdefinierten ASP.NET-Anbieters zu konfigurieren, müssen Sie das Typ-Attribut des ASP.NET-Anbieters angeben. Geben Sie optional die von Ihrem Anbieter angeforderten Laufzeiteigenschaften an, z. B. Anmeldedaten für den Benutzer.
- Öffnen Sie das ArcGIS Server-Administratorverzeichnis, und melden Sie sich an.
- Klicken Sie auf security > config > updateIdentityStore.
- Geben Sie die Benutzerspeicher-Konfiguration im JSON-Format ein. Folgende Syntax wird verwendet:
{ "type": "ASP_NET", "class": "{Membership provider's type attribute value}", "properties": { "Property One": "value", .... "Property X": "value" } }
- Geben Sie die Rollenspeicher-Konfiguration im JSON-Format ein. Folgende Syntax wird verwendet:
{ "type": "ASP_NET", "class": "{Role provider's type attribute value}", "properties": { "Property One": "value", .... "Property X": "value" } }
- Klicken Sie auf Aktualisieren, um die Konfiguration zu speichern.
Beispielimplementierung
Nachstehend sehen Sie die Beispielimplementierung eines ASP.NET-Mitgliedschafts- und -Rollenanbieters für ArcGIS Server in C#. Im Beispiel wird ein ASP.NET-Anbieter verwendet, der geändert werden kann. Es ist empfehlenswert, den Anbieter als schreibgeschützten Identitätsspeicher für ArcGIS Server bereitzustellen.
- Beispiel-Mitgliedschaftsanbieter
- Beispiel-Rollenanbieter
- JSON für einen Beispiel-Identitätsspeicher
- Beispiel-Identitätsspeicher
Beispiel-Mitgliedschaftsanbieter
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 */
}
Beispiel-Rollenanbieter
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 für die Konfiguration eines Beispiel-Identitätsspeichers
Benutzerspeicher-JSON
{
"type": "ASP_NET", "class": "CustomProvider.XmlMembershipProvider,CustomProvider,Version=1.0.0.0,Culture=Neutral,PublicKeyToken=b02390eb7f2c02c4", "properties": {
"FileName": "C:\\arcgisserver\\identitystore\\IdentityStore.xml"
}
}
Rollenspeicher-JSON
{
"type": "ASP_NET", "class": "CustomProvider.XmlRoleProvider,CustomProvider,Version=1.0.0.0,Culture=Neutral,PublicKeyToken=b02390eb7f2c02c4", "properties": {
"FileName": "C:\\arcgisserver\\identitystore\\IdentityStore.xml"
}
}
Beispiel-Identitätsspeicher
<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>