אינטגרציית LDAP ישירה באפליקציה ניידת היא כמעט תמיד טעות ארכיטקטונית: פורטים 389/636 חסומים על ידי חומות אש, לא ניתן לאחסן אישורי LDAP bind במכשיר, והחיבור דרך האינטרנט הנייד ל-AD מקומי אינו יציב. הסכימה הנכונה היא פרוקסי backend: נייד ← API של backend ← AD/LDAP. זה מבטיח אבטחה וסקלביליות. אנו מיישמים אינטגרציה turnkey באמצעות פרוטוקולים מודרניים והצפנה. המהנדסים המוסמכים שלנו מבצעים ביקורת תשתית ומציעים את הפתרון האופטימלי. השאירו פנייה לייעוץ חינמי להערכת הפרויקט שלכם.
למה לא כדאי להתחבר ל-LDAP ישירות מהנייד
רשתות ניידות אינן צפויות, ושרתי LDAP ארגוניים נמצאים מאחורי חומות אש מחמירות. ניסיון לחיבור ישיר מוביל לחסימות רשת, דרישות לפתיחת פורטים (הפרת מדיניות אבטחה), ופגיעות באחסון אישורים במכשיר. אפילו עם VPN, זה מוסיף זמן אחזור ומורכבות ניהולית. פרוקסי backend פותר את הבעיות האלה: כל החיבורים יוצאים מפלח רשת מאובטח, והאפליקציה הניידת מתקשרת רק דרך HTTPS עם JWT.
ארכיטקטורת אינטגרציה: פרוקסי backend
ה-backend פועל כפרוקסי LDAP: הוא מקבל בקשות מהנייד דרך HTTPS עם אימות JWT, שואל את AD/LDAP בתוך הרשת הארגונית, ומחזיר נתונים בפורמט REST.
Мобильный ──HTTPS/JWT──► Backend API ──LDAP 636──► Active Directory └──LDAP 389──► OpenLDAP לאימות דרך AD ב-backend, אנו משתמשים ב-LDAP bind:
// Node.js, ldapjs
const client = ldap.createClient({
url: "ldaps://dc01.company.local:636",
tlsOptions: {
rejectUnauthorized: true,
ca: [fs.readFileSync("ca.crt")],
},
});
async function authenticateUser(username, password) {
const userDN = `cn=${username},ou=Users,dc=company,dc=local`;
return new Promise((resolve, reject) => {
client.bind(userDN, password, (err) => {
if (err) {
reject(new InvalidCredentialsError());
} else {
resolve(true);
client.unbind();
}
});
});
}לאחר bind מוצלח, ה-backend יוצר JWT ומחזיר אותו לנייד. הסיסמה של המשתמש לעולם לא עוזבת את ה-backend.
| פרמטר | גישה ישירה | פרוקסי backend |
|---|---|---|
| אבטחה | נמוכה: סיסמה במכשיר | גבוהה: סיסמה לא מאוחסנת |
| סקלביליות | מוגבלת: יציבות רשת | גבוהה: caching, איזון עומסים |
| מהירות | תלויה ברשת הלקוח | מותאמת ב-backend |
| מורכבות יישום | פשוטה אך מסוכנת | דורשת פיתוח |
עבור לקוח קמעונאי עם 5,000 עובדים, יישמנו ארכיטקטורה זו, והפחתנו את זמן ההתחברות מ-3 שניות לפחות משנייה אחת, וביטלנו את הסיכונים באחסון אישורים.
איך להגן על אישורי משתמש
הסיסמה של המשתמש מועברת מהנייד ל-backend דרך HTTPS. ה-backend מבצע LDAP bind — המקום היחיד שבו נעשה שימוש בסיסמה. לאחר האימות, ה-backend יוצר JWT עם תוחלת חיים מוגבלת (לדוגמה, שעה). המכשיר הנייד מאחסן רק את ה-JWT; הסיסמה לעולם לא נשמרת במטמון. כאשר עובד עוזב, חשבון ה-AD שלו מושבת; ה-backend, ב-refresh_token הבא, מזהה כישלון ב-LDAP lookup ומבטל את ה-JWT — הגישה נחסמת מיד.
שליפת מאפייני משתמש
AD מאחסן סט עשיר של מאפיינים: Мобильный ──HTTPS/JWT──► Backend API ──LDAP 636──► Active Directory └──LDAP 389──► OpenLDAP , // Node.js, ldapjs const client = ldap.createClient({ url: "ldaps://dc01.company.local:636", tlsOptions: { rejectUnauthorized: true, ca: [fs.readFileSync("ca.crt")] }, }); async function authenticateUser(username, password) { const userDN = `cn=${username},ou=Users,dc=company,dc=local`; return new Promise((resolve, reject) => { client.bind(userDN, password, (err) => { if (err) { reject(new InvalidCredentialsError()); } else { resolve(true); client.unbind(); } }); }); } , displayName, mail, telephoneNumber, department (קבוצות), manager (תמונת פרופיל). עבור אפליקציה ארגונית, זהו מקור נתונים יקר ערך — אין צורך לשכפל פרופילי משתמש.
async function getUserAttributes(username) {
const base = "ou=Users,dc=company,dc=local";
const opts = {
filter: `(sAMAccountName=${username})`,
scope: "sub",
attributes: [
"displayName",
"mail",
"department",
"manager",
"memberOf",
"thumbnailPhoto",
],
};
return new Promise((resolve, reject) => {
client.search(base, opts, (err, res) => {
let entry = null;
res.on("searchEntry", (e) => (entry = e.object));
res.on("end", () => resolve(entry));
res.on("error", reject);
});
});
}memberOf הוא JPEG ב-base64 ישירות ב-AD. אנו מחזירים אותו כמחרוזת base64 או שומרים אותו באחסון אובייקטים ומחזירים URL.
thumbnailPhoto מכיל DN של קבוצות: async function getUserAttributes(username) { const base = "ou=Users,dc=company,dc=local"; const opts = { filter: `(sAMAccountName=${username})`, scope: "sub", attributes: [ "displayName", "mail", "department", "manager", "memberOf", "thumbnailPhoto", ], }; return new Promise((resolve, reject) => { client.search(base, opts, (err, res) => { let entry = null; res.on("searchEntry", (e) => (entry = e.object)); res.on("end", () => resolve(entry)); res.on("error", reject); }); }); } . קבוצות קובעות הרשאות משתמש באפליקציה — אנו מנתחים את ה-CN מה-DN וממפים לתפקידי אפליקציה.
בניית המבנה הארגוני מ-AD
AD מספק היררכיה דרך המאפיין thumbnailPhoto (DN של מנהל) ו-memberOf. בניית עץ ארגוני באמצעות שאילתות LDAP רקורסיביות אפשרית אך איטית להיררכיות עמוקות. עדיף: לשמור את המבנה במטמון ב-backend עם עדכונים תקופתיים (פעם בשעה/יום), והנייד מבקש את הגרף המוכן.
// Android — отображение оргструктуры
data class OrgNode(
val employeeId: String,
val name: String,
val position: String,
val department: String,
val avatarUrl: String?,
val directReports: List<OrgNode>
)
@Composable
fun OrgChart(rootNode: OrgNode) {
LazyColumn {
item {
EmployeeCard(node = rootNode, level = 0)
}
items(rootNode.directReports) { report ->
EmployeeCard(node = report, level = 1)
// Рекурсивно для вложенных уровней через expandable state
}
}
} חיפוש עובדים
חיפוש טקסט מלא ב-AD דרך מסנן LDAP:
const filter = `(&(objectClass=person)(|(displayName=*${query}*)(mail=*${query}*)(sAMAccountName=*${query}*)))`; ביצועים: wildcard מוביל (CN=VPN-Users,OU=Groups,DC=company,DC=local) לא משתמש באינדקס של AD; החיפוש איטי עבור ספריות גדולות. עבור אפליקציות עם אלפי עובדים, אנו מסנכרנים את AD ל-Elasticsearch או PostgreSQL full-text search ומבצעים חיפוש שם.
Caching וסנכרון
AD הוא מקור האמת לנתוני עובדים. האפליקציה הניידת עובדת עם מטמון ה-backend. לרעננות: אירועי webhook דרך יומן אירועים של AD (AD 2016+) או בדיקה כל 15–30 דקות לשינויים דרך המאפיין manager.
כאשר עובד מסיים את תפקידו, חשבון ה-AD מושבת. ה-backend, ב-refresh_token הבא, רואה כישלון ב-LDAP lookup ומבטל את ה-JWT. הנייד מופנה להתחברות.
מאפייני Azure AD (Entra ID)
אם החברה משתמשת ב-Azure AD (Microsoft Entra ID) — אין LDAP ישיר, רק Microsoft Graph API או OIDC. Graph API נוח הרבה יותר: REST, JSON, תיעוד עשיר. directReports מחזיר כל מה ש-LDAP מחזיר, ללא ספריות ADO.
עבור סביבה היברידית (AD מקומי + Azure AD עם Azure AD Connect) — הנתונים מסונכרנים; ניתן להשתמש ב-Graph API או ב-LDAP מקומי בהתאם לדרישות האבטחה.
מה כלול
- ביקורת תשתית AD/LDAP קיימת ואפליקציה ניידת
- עיצוב ארכיטקטורת פרוקסי backend
- יישום אימות דרך LDAP bind עם JWT
- API למאפיינים, מבנה ארגוני וחיפוש
- הגדרת caching וסנכרון
- אינטגרציה עם Azure Graph API (במידת הצורך)
- תיעוד והדרכה לצוות הלקוח
- תמיכה טכנית במהלך התפעול
לוח זמנים ועלות משוערים
אינטגרציית AD/LDAP (פרוקסי backend + לקוח נייד + מבנה ארגוני + חיפוש): 3–6 שבועות. העלות נקבעת לאחר הערכה ראשונית. צרו קשר לביקורת כדי לקבל הצעת מחיר מדויקת.
הצוות שלנו השלים למעלה מ-15 פרויקטים של אינטגרציית AD/LDAP עבור בנקים, קמעונאות ותעשייה. אנו מבטיחים תאימות לכל שרת LDAP (OpenLDAP, FreeIPA, Active Directory). צרו קשר לביקורת וקבלו הצעה אישית.







