如何生成令牌来查询REST ArcGIS服务

本文关键字:REST ArcGIS 服务 查询 何生成 令牌 | 更新日期: 2023-09-27 18:06:59

我有一个。net应用程序需要访问REST ArcGIS服务。此服务是私有的,需要基于令牌的身份验证才能访问服务中的数据。由于我是ArcGIS的新手,所以我不知道如何生成令牌并在我的。net应用程序中使用它。

如何生成令牌来查询REST ArcGIS服务

看一下Esri的代理是如何获得令牌的:https://developers.arcgis.com/authentication/working-with-proxies/

特别是:https://github.com/Esri/resource-proxy/tree/master/DotNethttps://github.com/Esri/resource-proxy/blob/master/DotNet/proxy.ashx

正如@spiskula所提到的,您可以遵循https://github.com/Esri/resource-proxy/blob/master/DotNet/proxy.ashx中所示的方法,特别是getNewTokenIfCredentialsAreSpecified方法。

这里有一个非常简单的例子(在。net 4.5之前),在没有SDK的情况下做同样的事情。用户将需要通过错误处理等使其更健壮。

private string GetToken()
    {
        var request = (HttpWebRequest)WebRequest.Create("https://www.arcgis.com/sharing/rest/oauth2/token/");
        var postData = "client_id=yourclientid"; //required
        postData += "&client_secret=yourclientsecret"; //required
        postData += "&grant_type=client_credentials"; //required
        postData += "&expiration=120"; //optional, default
        var data = Encoding.ASCII.GetBytes(postData);
        request.Method = "POST";
        request.ContentType = "application/x-www-form-urlencoded";
        request.ContentLength = data.Length;
        using (var stream = request.GetRequestStream())
        {
            stream.Write(data, 0, data.Length);
        }
        var response = (HttpWebResponse)request.GetResponse();
        var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
        ESRITokenResponse eToken = Newtonsoft.Json.JsonConvert.DeserializeObject<ESRITokenResponse>(responseString);
        return eToken.access_token;
    }
public class ESRITokenResponse
{
    public string access_token { get; set; }
    public string expires_in { get; set; }
}

如果您想要简单的http请求,您可以创建一个简单的连接,如下所示。

首先,您必须知道生成令牌url。例如,如果服务器url是http://myserver/arcgis/rest/services ....

您的生成令牌url是:http://myserver/arcgis/tokens/generateToken.

第二个操作是准备模型以生成令牌,如下所示:
public class ArcgisTokenResponseModel
{
    public string token { get; set; }
    public string expires { get; set; }
}

对于可重用代码,我们可以创建一个准备querystring键值的类。这个类看起来就像下面的代码:

public class TokenModel
{
    public string f { get; set; }
    public string username { get; set; }
    public string password { get; set; }
    public string ip { get; set; }
    public int expiration { get; set; }
    public string client { get; set; }
    public TokenModel(string username, string password, string ip, int expiration, string f = "json")
    {
        this.expiration = expiration;
        this.f = f;
        this.ip = ip;
        this.password = password;
        this.username = username;
    }
    public string GetQueryStringParameter()
    {
        return "f=" + this.f + "&username=" + this.username + "&password=" + this.password + "&ip=" + this.ip + "&expiration=" + this.expiration;
    }

}

然后编写一个函数,从ArcGis服务器生成带有用户名和密码的令牌。这个函数可能像这样:

    protected string GetToken(string generateTokenUrl,string username,string password)
    {
        try
        {
            string ipadress = _serverInformationHelper.GetIPAddress();
            int exp = 60;
            if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password))
            {
                Model.Arcgis.TokenModel tokenModel = new Model.Arcgis.TokenModel(username, password, ipadress, exp);
                //token bilgisinin alınacağı server url'i
                string post = tokenModel.GetQueryStringParameter();
                WebClient clientToken = new WebClient();
                clientToken.Headers.Add("Content-Type: application/x-www-form-urlencoded");
                string tokenResult = clientToken.UploadString(generateTokenUrl, post);
                ArcgisTokenResponseModel resultTokenModel = _seriliazer.Deserialize<ArcgisTokenResponseModel>(tokenResult);
                if (resultTokenModel != null && !string.IsNullOrEmpty(resultTokenModel.token))
                    return resultTokenModel.token;
            }
            return null;
        }
        catch (Exception ex)
        {
            return null;
        }
    }

毕竟,无论你想要什么,你都可以使用GetToken()函数

在ArcGIS pro插件中,

  1. 创建ArcGIS服务令牌
    var url = "https://{baseUrl}/arcgis/tokens/generateToken";
    var request = (HttpWebRequest)WebRequest.Create(url);
    var postData = "f=JSON";
    postData += "&username={username}";
    postData += "&password={password}";
    postData += "&client=ip";
    postData += "&ip=" + GetLocalIP();
    postData += "&expiration=60";
    var data = Encoding.ASCII.GetBytes(postData);
    request.Method = "POST";
    request.ContentType = "application/x-www-form-urlencoded";
    request.ContentLength = data.Length;
    using (var stream = request.GetRequestStream())
    {
      stream.Write(data, 0, data.Length);
    }
    var response = (HttpWebResponse)request.GetResponse();
    var resString = new StreamReader(response.GetResponseStream()).ReadToEnd();
    return (EsriToken)new JavaScriptSerializer().Deserialize(resString, typeof(EsriToken));

EsriToken是一个有两个属性的类:

    public class EsriToken
    {
      public string token { get; set; }
      public string expire { get; set; }
    }
  • 在应用程序cookie中为服务url设置令牌:
  •     ProApp.SetCookie(new Uri("https://{baseUrl}/arcgis/services/"), "agstoken=" + token); // token is into EsriToken class...
    
  • 添加featureLayer作为安全的ArcGIS服务:
  •     await QueuedTask.Run(() =>
        {
          map = MapFactory.Instance.CreateMap(title, MapType.Map, MapViewingMode.Map, Basemap.ProjectDefault);
          ServiceConnectionProperties serviceConnectionProperties = new ServiceConnectionProperties(new Uri("https://{baseUrl}/arcgis/services/{YourServicePath}"));
          using (Geodatabase fs_db = new Geodatabase(serviceConnectionProperties))
          {
              IReadOnlyList<TableDefinition> definitions = fs_db.GetDefinitions<FeatureClassDefinition>();
              var dataset_name = "{YourDatasetNameHere}";
              var fc = fs_db.OpenDataset<FeatureClass>(dataset_name);
              try
              {
                  var layer = LayerFactory.Instance.CreateFeatureLayer(fc, map);
              }
              catch (Exception e)
              {
                  throw;
              }
          }
        });
        App.Panes.CreateMapPaneAsync(map);
    

    Tadaa……好啦!!

    对不起我的英语。

    参见https://developers.arcgis.com/authentication/accessing-arcgis-online-services/#using-rest了解概述。有两个选项:

    1. 更容易:使用ArcGIS Runtime SDK: https://developers.arcgis.com/net/desktop/guide/use-arcgis-token-authentication.htm
    2. 更难:发布你自己的令牌请求:https://developers.arcgis.com/authentication/accessing-arcgis-online-services/#using-rest(没有。net示例,可能因为你真的应该使用ArcGIS Runtime)

    这是一个ArcGIS Runtime SDK for . net示例,使用硬编码登录。我上面链接的. net页面也有一个向用户询问凭据的示例。

    try
    {
        var opts = new GenerateTokenOptions();
        opts.TokenAuthenticationType = TokenAuthenticationType.ArcGISToken;
        // generate an ArcGIS token credential with a hard-coded user name and password
        // (if authentication fails, an ArcGISWebException will be thrown)
        var cred = await IdentityManager.Current.GenerateCredentialAsync(
                                     "http://serverapps10.esri.com/arcgis/rest/services/", 
                                     "user1", 
                                     "pass.word1", 
                                     opts);
        // add the credential to the IdentityManager (will be included in all requests to this portal)
        IdentityManager.Current.AddCredential(cred);
        // load a layer based on a secured resource on the portal
        var layer = new ArcGISDynamicMapServiceLayer(new Uri
                            ("http://serverapps10.esri.com/arcgis/rest/services/GulfLawrenceSecureUser1/MapServer"));
        await layer.InitializeAsync();
        // add the layer to the map and zoom to its extent
        this.MyMapView.Map.Layers.Add(layer);
        await this.MyMapView.SetViewAsync(layer.FullExtent);
    }
    catch (ArcGISWebException webExp)
    {
        MessageBox.Show("Unable to authenticate with portal: " + webExp.Message);
    }
    catch (Exception exp)
    {
        MessageBox.Show("Unable to load secured layer: " + exp.Message);
    }