Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Talebi uygulamanız için bir erişim belirtecinde yapılandırdığınızda groups
, Microsoft Entra Id'nin erişim belirtecinde döndürülebilecek en fazla grup sayısı vardır. Sınır aşıldığında Azure, şu anda oturum açmış olan kullanıcının tam grup listesini almak için kullanılabilecek bir URL olan bir grup fazla kullanım talebi sağlar. Bu URL, Microsoft Graph uç noktasını kullanır. Talep hakkında groups
daha fazla bilgi için bkz. Microsoft kimlik platformu erişim belirteçleri.
JSON web belirteçleri (JWT) için Azure, belirteçte bulunabilecek grup sayısını 200 ile sınırlar. Talebin yapılandırılmış olduğu groups
bir kaynak için erişim belirteci istediğinizde, 200'den fazla grubun üyesiyseniz gerçek grupları almak yerine bir grup fazla kullanım talebi alırsınız.
Bu makalede, örnek bir proje kullanarak bir grup fazla kullanım talebinden gerçek kullanıcı grubu listesinin nasıl alındığı tanıtıcıdır.
Uygulamanız için grup talebi yapılandırma
İsteğe groups
bağlı talepleri kullanarak uygulamanız için talebi yapılandırabilirsiniz. Daha fazla bilgi için bkz . Kimlik belirteçlerinde, erişim belirteçlerinde ve SAML belirteçlerinde isteğe bağlı talepleri yapılandırma ve yönetme.
Uygulama birinci taraf bir uygulamaysa (Microsoft uygulaması), talebi yapılandıramazsınız groups
. Bunu yalnızca kendi uygulama kaydınızla yapılandırabilirsiniz. Bir istemci uygulaması için talebi yapılandırmak groups
istiyorsanız, bir kimlik belirtecinde yapılandırmanız gerekir.
Örnek projeyi indirme
Örnek proje MSAL.Net_GroupOveragesClaim indirin. Grup listesinin bir grup fazla kullanım talebinden nasıl alınıp alınamaya ilişkin olduğunu gösterir.
Örnek projeyi çalıştırmadan önce
Örnek proje için bir uygulama kaydı yapılandırın.
Örnek proje hem genel istemci akışını hem de gizli istemci akışını gerçekleştirir, bu nedenle bir web yeniden yönlendirmesi (genel istemci akışı için) ve bir istemci gizli dizisi (gizli istemci akışı için) yapılandırmanız gerekir. Gizli istemcinin
users
uç noktaya gitmesi ve ilk oturum açma belirtecinden alınabilen kullanıcı kimliğine göre grupları araması gerektiğinden, gizli istemci sürümü için Microsoft Graph uygulama izni gerekirGroup.Read.All
. Genel istemci, bir kullanıcı bağlamıme
olduğundan uç noktaya gider.appsettings.json dosyasını uygun değerlerle güncelleştirerek örnek projeyi kiracınızla çalışacak şekilde yapılandırın:
{ "Azure": { "ClientId": "{client_id}", "TenantId": "{tenant_id}", "CallbackPath": "http://localhost", "ClientSecret": "{client_secret}", "AppScopes": [ "https://database.windows.net/.default" ], "GraphScopes": [ "User.Read" ] } }
appsettings.json dosyasındaki ayarların açıklamaları şunlardır:
AppScopes
Talebin
groups
yapılandırıldığı bir kapsamınız olmalıdır.Bu genellikle kiracınızdaki bir API'dir. Ancak bu durumda, user_impersonation izniyle Azure SQL Veritabanı eklemek bu senaryo için işe yarar. Eklediğiniz kapsam bu API için çalışır. Bunun nedeni, talebin
groups
söz konusu API'de yapılandırılmış olmasıdır.GraphScopes
Group.Read.All (grup görünen adını almak için gereklidir) ve User.Read.All (istemci kimlik bilgileri akışını kullanarak grup listesini almak için gereklidir) uygulama izinlerini ekleyin. Bu izinler için yönetici onayı sağlamanız gerekir. User.Read temsilci izni zaten orada olmalıdır. Eklenmiyorsa ekleyin.
Bu örnek projenin uygulama kaydı yapılandırıldıktan sonra, appsettings.json dosyasına istemci kimliğini (uygulama kimliği), istemci gizli dizisini ve kiracı kimliğini ekleyin.
Test grupları oluşturmak için (gerekirse) Create_TestGroup.ps1.txt dosyasında PowerShell betiklerini çalıştırın.
Örnek projede Create_TestGroup.ps1.txt adlı bir metin dosyası vardır. PowerShell betiklerini bu dosyada çalıştırmak için .txt uzantısını kaldırın. Çalıştırmadan önce, test gruplarına eklemek için kullanıcının nesne kimliğine ihtiyacınız vardır. Grup oluşturabilen ve gruplara kullanıcı ekleyebilen bir dizin rolünde olmanız gerekir. Örnek proje, ,
TEST_0002
vb. biçimindeTEST_0001
255 grup oluşturur. Her grup için sağladığınız nesne kimliği eklenir. Betiğin sonunda Azure'da oturum açar, test gruplarını oluşturmak için komutunu çalıştırır ve ardından oturumu kapatabilirsiniz.Not
53. satıra açıklama ekleyen örnek bir temizleme yöntemi vardır:
Connect-AzureAD Create-TestGroups -deleteIfExists $false #Delete-TestGroups Disconnect-AzureAD
Grup fazla kullanım talebi kullanarak tam kullanıcı grupları listesini alma
Örnek uygulamayı çalıştırın.
Uygulamada oturum açın.
Örnek uygulama bir .NET konsol uygulaması olduğundan kimlik doğrulaması tarayıcıda gerçekleşir.
Oturum açtıktan sonra tarayıcıyı kapatın; konsol uygulamasına geri dönersiniz.
Erişim belirteci konsol penceresinde sunulduktan sonra, erişim belirtecini panoya kopyalayın ve kodlanmış belirteci görüntülemek için içine yapıştırın https://jwt.ms . Bu yalnızca bir kullanıcı belirtecidir.
Kullanıcı çok fazla grubun üyesiyse, konsol penceresinde özgün grup fazla kullanım talebi ve bu belirteç için yeni grup fazla kullanım talebi görüntülenir. Yeni grup fazla kullanım talebi Graph .NET SDK isteği yerine .NET HTTP istemci isteğinde kullanılır.
Microsoft Graph için almak istediğiniz erişim belirteci türünü seçin. Şu anda oturum açmış olan kullanıcı için kullanıcı belirteci (yenileme belirteci akışı) veya istemci kimlik bilgileri verme akışını kullanarak bir uygulama belirteci kullanarak erişim belirteci alabilirsiniz.
Kullanıcı gruplarının
.NET HTTP Request
tam listesini almak için veyaGraph .NET SDK
öğesini seçin.Gruplar konsol penceresinde görünür:
Kod hakkında
Get_GroupsOverageClaimURL yöntemi
Örnek proje, kullanıcıların kimliğini doğrulamak ve erişim belirteçleri almak için MSAL.NET (Microsoft.Identity.Client
) kullanır.
System.Net.Http
HTTP istemcisi için, Microsoft.Graph SDK ise grafik istemcisi için kullanılır. JSON dosyasını System.Text.Json
ayrıştırmak için kullanılır. Belirteçten System.IdentityModel.Tokens.Jwt
talepleri almak için kullanılır. Sağlayıcı JwtSecurityToken
, belirteçteki grup fazla kullanım talebi almak için kullanılır.
Belirteç talepleri ve claim_sources
içeriyorsaclaim_names
, belirteç içinde bir grup fazla kullanım talebi olduğunu gösterir. Bu durumda, grup listesinin URL'sini oluşturmak ve konsol penceresinde özgün değeri çıkarmak için kullanıcı kimliğini (oid) ve iki talebi kullanın. İki talep değerinden biri yoksa, try/catch
blok hatayı işler ve bir string.empty
değer döndürür. Bu, belirteçte grup fazla kullanım talebi olmadığını gösterir.
/// <summary>
/// Looks for a group overage claim in an access token and returns the value if found.
/// </summary>
/// <param name="accessToken"></param>
/// <returns></returns>
private static string Get_GroupsOverageClaimURL(string accessToken)
{
JwtSecurityToken token = new JwtSecurityTokenHandler().ReadJwtToken(accessToken);
string claim = string.Empty;
string sources = string.Empty;
string originalUrl = string.Empty;
string newUrl = string.Empty;
try
{
// use the user id in the new graph URL since the old overage link is for Azure AD Graph which is being deprecated.
userId = token.Claims.First(c => c.Type == "oid").Value;
// getting the claim name to properly parse from the claim sources but the next 3 lines of code are not needed,
// just for demonstration purposes only so you can see the original value that was used in the token.
claim = token.Claims.First(c => c.Type == "_claim_names").Value;
sources = token.Claims.First(c => c.Type == "_claim_sources").Value;
originalUrl = sources.Split("{\"" + claim.Split("{\"groups\":\"")[1].Replace("}","").Replace("\"","") + "\":{\"endpoint\":\"")[1].Replace("}","").Replace("\"", "");
// make sure the endpoint is specific for your tenant -- .gov for example for gov tenants, etc.
newUrl = $"https://graph.microsoft.com/v1.0/users/{userId}/memberOf?$orderby=displayName&$count=true";
Console.WriteLine($"Original Overage URL: {originalUrl}");
//Console.WriteLine($"New URL: {newUrl}");
} catch {
// no need to do anything because the claim does not exist
}
return newUrl;
}
Program.cs dosyası
Bu dosyada, kullanıcı oturum açma ve erişim belirteçleri alma için bir genel istemci uygulaması yapılandırması ve uygulama oturum açma ve erişim belirteçleri alma (istemci kimlik bilgileri verme akışı) için gizli bir istemci uygulaması vardır.
ManualTokenProvider
, Graph hizmet istemcisinin Graph'ın hizmete erişmesini sağlamak yerine hizmete erişim belirteci geçirmesi için kullanılır.
Ayrıca çalışma zamanında bu ayarları depolamak için bir appsettings.json dosyası ve bir sınıf (AzureConfig.cs) vardır. Genel statik özellik AzureSettings
, ASP.NET Core uygulamalarına benzer bir yapılandırma oluşturucu kullanarak yapılandırma dosyasından ayarları alır. Bu özellik bir konsol uygulamasına yerel olmadığından eklenmelidir.
static AzureConfig _config = null;
public static AzureConfig AzureSettings
{
get
{
// Only load this when the app starts.
// To reload, you will have to set the variable _config to null again before calling this property.
if (_config == null)
{
_config = new AzureConfig();
IConfiguration builder = new ConfigurationBuilder()
.SetBasePath(System.IO.Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.Build();
ConfigurationBinder.Bind(builder.GetSection("Azure"), _config);
}
return _config;
}
}
Kimlik doğrulama sağlayıcısı
Authentication
Graph hizmeti istemcisinin sağlayıcısı için örnek proje, MSAL kullanarak erişim belirteçlerini zaten almış olan istemci için erişim belirtecini ayarlamak üzere özel bir el ile belirteç sağlayıcısı kullanır.
using Microsoft.Graph;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace MSAL.Net_GroupOveragesClaim.Authentication
{
class ManualTokenProvider : IAuthenticationProvider
{
string _accessToken;
public ManualTokenProvider ( string accessToken)
{
_accessToken = accessToken;
}
async Task IAuthenticationProvider.AuthenticateRequestAsync(HttpRequestMessage request)
{
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _accessToken);
request.Headers.Add("ConsistencyLevel", "eventual");
}
}
}
Get_Groups_HTTP_Method
Bu yöntem, grupların Graph_Request_viaHTTP
listesini almak için yöntemini çağırır ve ardından bu listeyi konsol penceresinde görüntüler.
/// <summary>
/// Entry point to make the request to Microsoft graph using the .Net HTTP Client
/// </summary>
/// <param name="graphToken"></param>
/// <returns></returns>
private static async Task Get_Groups_HTTP_Method(string graphToken, string url)
{
List<Group> groupList = new List<Group>();
groupList = await Graph_Request_viaHTTP(graphToken, url);
foreach (Group g in groupList)
{
Console.WriteLine($"Group Id: {g.Id} : Display Name: {g.DisplayName}");
}
}
/// <summary>
/// Calls Microsoft Graph via a HTTP request. Handles paging in the request
/// </summary>
/// <param name="user_access_token"></param>
/// <returns>List of Microsoft Graph Groups</returns>
private static async Task<List<Group>> Graph_Request_viaHTTP(string user_access_token, string url)
{
string json = string.Empty;
//string url = "https://graph.microsoft.com/v1.0/me/memberOf?$orderby=displayName&$count=true";
List<Group> groups = new List<Group>();
// todo: check for the count parameter in the request and add if missing
/*
* refer to this documentation for usage of the http client in .net
* https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient?view=net-5.0
*
*/
// add the bearer token to the authorization header for this request
_httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue( "Bearer", user_access_token);
// adding the consistencylevel header value if there is a $count parameter in the request as this is needed to get a count
// this only needs to be done one time so only add it if it does not exist already. It is case sensitive as well.
// if this value is not added to the header, the results will not sort properly -- if that even matters for your scenario
if(url.Contains("&$count", StringComparison.OrdinalIgnoreCase))
{
if (!_httpClient.DefaultRequestHeaders.Contains("ConsistencyLevel"))
{
_httpClient.DefaultRequestHeaders.Add("ConsistencyLevel", "eventual");
}
}
// while loop to handle paging
while(url != string.Empty)
{
HttpResponseMessage response = await _httpClient.GetAsync(new Uri(url));
url = string.Empty; // clear now -- repopulate if there is a nextlink value.
if (response.IsSuccessStatusCode)
{
json = await response.Content.ReadAsStringAsync();
// Console.WriteLine(json);
using (JsonDocument document = JsonDocument.Parse(json))
{
JsonElement root = document.RootElement;
// check for the nextLink property to see if there is paging that is occuring for our while loop
if (root.TryGetProperty("@odata.nextLink", out JsonElement nextPage))
{
url = nextPage.GetString();
}
JsonElement valueElement = root.GetProperty("value"); // the values
// loop through each value in the value array
foreach (JsonElement value in valueElement.EnumerateArray())
{
if (value.TryGetProperty("@odata.type", out JsonElement objtype))
{
// only getting groups -- roles will show up in this graph query as well.
// If you want those too, then remove this if filter check
if (objtype.GetString() == "#microsoft.graph.group")
{
Group g = new Group();
// specifically get each property you want here and populate it in our new group object
if (value.TryGetProperty("id", out JsonElement id)) { g.Id = id.GetString(); }
if (value.TryGetProperty("displayName", out JsonElement displayName)) { g.DisplayName = displayName.GetString(); }
groups.Add(g);
}
}
}
}
} else
{
Console.WriteLine($"Error making graph request:\n{response.ToString()}");
}
} // end while loop
return groups;
}
Get_Groups_GraphSDK_Method
Benzer şekilde, Graph SDK'sının bir giriş yöntemi vardır: Get_Groups_GraphSDK_Method
. Bu yöntem, grupların listesini almak için öğesini çağırır Get_GroupList_GraphSDK
ve konsol penceresinde görüntüler.
/// <summary>
/// Entry point to make the request to Microsoft Graph using the Graph SDK and outputs the list to the console.
/// </summary>
/// <param name="graphToken"></param>
/// <returns></returns>
private static async Task Get_Groups_GraphSDK_Method(string graphToken, bool me_endpoint)
{
List<Group> groupList = new List<Group>();
groupList = await Get_GroupList_GraphSDK(graphToken, me_endpoint);
foreach (Group g in groupList)
{
Console.WriteLine($"Group Id: {g.Id} : Display Name: {g.DisplayName}");
}
}
Get_GroupList_GraphSDK yöntemi
Bu yöntem, grup listesini almak için uç noktanın mı yoksa uç noktanın users
mı kullanılacağını me
belirler. Microsoft Graph erişim belirtecini almak için istemci kimlik bilgileri verme akışını kullanıyorsanız uç noktayı kullanın me
. Aksi takdirde (örneğin, erişim belirteci için temsilcili bir akış kullanılır), uç noktayı kullanın users
. Kullanılan yöntemden bağımsız olarak, varsayılan olarak sayfa başına yalnızca 100 kayıt döndürülür. Disk belleği değeri üzerinden @odata.nextLink
belirlenir. Bu özellik için bir değer varsa, sonraki veri sayfası için tam URL çağrılır. Sayfalama hakkında daha fazla bilgi için bkz . Uygulamanızda Microsoft Graph verilerini sayfalama.
/// <summary>
/// Calls the Me.MemberOf endpoint in Microsoft Graph and handles paging
/// </summary>
/// <param name="graphToken"></param>
/// <returns>List of Microsoft Graph Groups</returns>
private static async Task<List<Group>> Get_GroupList_GraphSDK(string graphToken, bool use_me_endpoint)
{
GraphServiceClient client;
Authentication.ManualTokenProvider authProvider = new Authentication.ManualTokenProvider(graphToken);
client = new GraphServiceClient(authProvider);
IUserMemberOfCollectionWithReferencesPage membershipPage = null;
HeaderOption option = new HeaderOption("ConsistencyLevel","eventual");
if (use_me_endpoint)
{
if (!client.Me.MemberOf.Request().Headers.Contains(option))
{
client.Me.MemberOf.Request().Headers.Add(option);
}
membershipPage = await client.Me.MemberOf
.Request()
.OrderBy("displayName&$count=true") // todo: find the right way to add the generic query string value for count
.GetAsync();
} else
{
if (!client.Users[userId].MemberOf.Request().Headers.Contains(option))
{
client.Users[userId].MemberOf.Request().Headers.Add(option);
}
membershipPage = await client.Users[userId].MemberOf
.Request()
.OrderBy("displayName&$count=true")
.GetAsync();
}
List<Group> allItems = new List<Group>();
if(membershipPage != null)
{
foreach(DirectoryObject o in membershipPage)
{
if(o is Group)
{
allItems.Add((Group)o);
}
}
while (membershipPage.AdditionalData.ContainsKey("@odata.nextLink") && membershipPage.AdditionalData["@odata.nextLink"].ToString() != string.Empty)
{
membershipPage = await membershipPage.NextPageRequest.GetAsync();
foreach (DirectoryObject o in membershipPage)
{
if (o is Group)
{
allItems.Add(o as Group);
}
}
}
}
return allItems;
}
Yardım için bize ulaşın
Sorularınız veya yardıma ihtiyacınız varsa bir destek isteği oluşturun veya Azure topluluk desteği isteyin. Ürün geri bildirimini Azure geri bildirim topluluğuna da gönderebilirsiniz.