Apple OS LDAP操作实现
需求:
在客户端通过javascript与java applet的交互实现Apple OS的用户和组的管理。
环境:
LDAP Sever:Apple OS Server Open Directory
JDK:6.0
Develop Tools:Eclipse 3.30
备注:
1.因为我不知道怎样修改Apple的用户密码,所以在具体应用中,用户是事先创建好的,用户名为约定的格式。在添加用户时是把可用用户的长名和短名改为用户名,在删除用户时,是把用户名的长名和短名修改回去。
2.为了方便,所有输入输出参数都为字符串类型。
3.所有过程均测试成功。
1
import
java.applet.
*
;
2
import
javax.naming.
*
;
3
import
javax.naming.directory.
*
;
4
import
java.util.
*
;
5
import
javax.xml.parsers.
*
;
6
import
org.w3c.dom.
*
;
7
import
java.io.
*
;
8
import
org.xml.sax.
*
;
9
import
javax.xml.transform.
*
;
10
import
javax.xml.transform.dom.
*
;
11
import
javax.xml.transform.stream.
*
;
12
13
public
class
LdapUtil
extends
Applet
{
14
/** *//**
15
* 把XML格式字符串转换为Document
16
* @param xml XML格式字符串
17
* @return
18
* @throws Exception
19
*/
20
private Document lodaXmlString(String xml) throws Exception
{
21
DocumentBuilder docBuilder=DocumentBuilderFactory.newInstance().newDocumentBuilder();
22
23
StringReader strReader=new StringReader(xml);
24
InputSource inSrc=new InputSource(strReader);
25
26
Document xmlDoc=docBuilder.parse(inSrc);
27
28
return xmlDoc;
29
}
30
31
/** *//**
32
* 把Document转换为XML格式字符串
33
* @param xmlDoc Document
34
* @return String
35
* @throws Exception
36
*/
37
private String xmlDocumentToString(Document xmlDoc) throws Exception
{
38
DOMSource domSource=new DOMSource(xmlDoc);
39
StringWriter writer=new StringWriter();
40
StreamResult result=new StreamResult(writer);
41
TransformerFactory tf=TransformerFactory.newInstance();
42
Transformer transformer=tf.newTransformer();
43
transformer.transform(domSource, result);
44
45
return writer.toString();
46
}
47
48
/** *//**
49
* 读取XML格式配置信息转换为DieContext
50
* @param env XML格式配置信息
51
* @return
52
* @throws Exception
53
*/
54
private DirContext connect(String env) throws Exception
{
55
Element root=this.lodaXmlString(env).getDocumentElement();
56
NodeList nodeList=root.getChildNodes();
57
58
int length=nodeList.getLength();
59
60
Properties pro=new Properties();
61
62
for(int i=0;i<length;i++)
{
63
Node node=nodeList.item(i);
64
65
if(node.getNodeName()=="factory")
{
66
pro.put(Context.INITIAL_CONTEXT_FACTORY, node.getTextContent());
67
}
68
else if(node.getNodeName()=="providerURL")
{
69
pro.put(Context.PROVIDER_URL, node.getTextContent());
70
}
71
else if(node.getNodeName()=="principal")
{
72
pro.put(Context.SECURITY_PRINCIPAL, node.getTextContent());
73
}
74
else if(node.getNodeName()=="authentication")
{
75
pro.put(Context.SECURITY_AUTHENTICATION, node.getTextContent());
76
}
77
else if(node.getNodeName()=="credentials")
{
78
pro.put(Context.SECURITY_CREDENTIALS, node.getTextContent());
79
}
80
else if(node.getNodeName()=="version")
{
81
pro.put("java.naming.ldap.version", node.getTextContent());
82
}
83
84
}
85
86
return new InitialDirContext(pro);
87
}
88
89
/** *//**
90
* 报XML字符串转换为SearchControls
91
* @param ctr
92
* @return SearchControls
93
* @throws Exception
94
*/
95
private SearchControls parseXmlToSearchControls(String ctr) throws Exception
{
96
Element root=this.lodaXmlString(ctr).getDocumentElement();
97
98
NodeList nodeList=root.getChildNodes();
99
100
int length=nodeList.getLength();
101
102
SearchControls sc=new SearchControls();
103
104
for(int i=0;i<length;i++)
{
105
Node node=nodeList.item(i);
106
107
if(node.getNodeName()=="countLimit")
{
108
sc.setCountLimit(Long.parseLong(node.getTextContent()));
109
}
110
else if(node.getNodeName()=="derefLinkFlag")
{
111
sc.setDerefLinkFlag(Boolean.parseBoolean(node.getTextContent()));
112
}
113
else if(node.getNodeName()=="returningAttributes")
{
114
sc.setReturningAttributes(node.getTextContent().split(","));
115
}
116
else if(node.getNodeName()=="returningObjFlag")
{
117
sc.setReturningObjFlag(Boolean.parseBoolean(node.getTextContent()));
118
}
119
else if(node.getNodeName()=="searchScope")
{
120
sc.setSearchScope(Integer.parseInt(node.getTextContent()));
121
}
122
else if(node.getNodeName()=="searchScope")
{
123
sc.setSearchScope(Integer.parseInt(node.getTextContent()));
124
}
125
else if(node.getNodeName()=="timeLimit")
{
126
sc.setTimeLimit(Integer.parseInt(node.getTextContent()));
127
}
128
}
129
130
return sc;
131
}
132
133
/** *//**
134
* 查找
135
* @param env XML格式LDAP配置信息
136
* @param name 查找的节点名称
137
* @param filter 属性过滤条件
138
* @param ctr XML格式的SearchControls信息
139
* @return
140
*/
141
public String search(String env,String name,String filter,String ctr)
{
142
DirContext ctx=null;
143
SearchControls sc=new SearchControls();
144
NamingEnumeration<SearchResult> rs=null;
145
String result="";
146
147
try
{
148
ctx=this.connect(env);
149
if(ctr!=null && ctr!="")
{
150
sc=this.parseXmlToSearchControls(ctr);
151
}
152
153
rs=ctx.search(name,filter,sc);
154
155
DocumentBuilder docBuilder=DocumentBuilderFactory.newInstance().newDocumentBuilder();
156
157
Document xmlDoc=docBuilder.newDocument();
158
159
Element rootEl=xmlDoc.createElement("searchResult");
160
161
while(rs!=null && rs.hasMore())
{
162
SearchResult el=rs.next();
163
String elName=el.getName();
164
NamingEnumeration<? extends Attribute> attrs=el.getAttributes().getAll();
165
166
Element recordEl=xmlDoc.createElement("record");
167
168
recordEl.setAttribute("name", elName);
169
170
while(attrs!=null && attrs.hasMore())
{
171
Attribute attr=attrs.next();
172
NamingEnumeration<?> attrEnu=attr.getAll();
173
String attrName=attr.getID();
174
175
while(attrEnu!=null && attrEnu.hasMore())
{
176
Object o=attrEnu.next();
177
Element attrEl=xmlDoc.createElement("attribute");
178
179
attrEl.setAttribute("name",attrName);
180
attrEl.setTextContent(o.toString());
181
182
recordEl.appendChild(attrEl);
183
}
184
}
185
186
rootEl.appendChild(recordEl);
187
}
188
189
ctx.close();
190
191
xmlDoc.appendChild(rootEl);
192
193
result=xmlDocumentToString(xmlDoc);
194
}
195
catch(Exception ex)
{
196
ex.printStackTrace();
197
}
198
199
return result;
200
}
201
202
/** *//**
203
* 添加用户
204
* 没有真正添加
205
* 是把可用的用户的长名和短名修改为指定的用户名
206
* @param env XML格式LDAP配置信息
207
* @param format 可用用户名格式
208
* @param name 用户名称
209
* @return
210
*/
211
public String addUser(String env,String format,String name)
{
212
DirContext ctx=null;
213
String result="false";
214
215
try
{
216
SearchControls sctr=new SearchControls();
217
218
sctr.setSearchScope(2);
219
sctr.setReturningAttributes(new String[]
{"sn","cn"});
220
221
ctx=this.connect(env);
222
NamingEnumeration<SearchResult> rs=ctx.search("cn=users","cn="+format+"*",sctr);
223
224
String usableName="";
225
226
while(rs!=null && rs.hasMore())
{
227
SearchResult el=rs.nextElement();
228
229
if(el.getAttributes().get("sn").get(0).toString().startsWith(format))
{
230
usableName=el.getName();
231
232
break;
233
}
234
}
235
236
if(usableName=="")
{
237
throw new Exception("没有可用用户资源");
238
}
239
240
ModificationItem[] mods=new ModificationItem[2];
241
242
mods[0]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
243
new BasicAttribute("sn", name));
244
mods[1]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
245
new BasicAttribute("cn", name));
246
247
ctx.modifyAttributes(usableName+",cn=users", mods);
248
249
ctx.close();
250
251
result="true";
252
}
253
catch(Exception ex)
{
254
ex.printStackTrace();
255
result="false";
256
}
257
258
return result;
259
}
260
261
/** *//**
262
* 把用户添加到指定组
263
* @param env XML格式LDAP配置信息
264
* @param groupName 组名称
265
* @param userName 用户名称
266
* @return
267
*/
268
public String addUserToGroup(String env,String groupName,String userName)
{
269
DirContext ctx=null;
270
String result="";
271
272
try
{
273
SearchControls sctr=new SearchControls();
274
275
sctr.setSearchScope(2);
276
sctr.setReturningAttributes(new String[]
{"uid","apple-generateduid","sn","cn"});
277
278
ctx=this.connect(env);
279
NamingEnumeration<SearchResult> rs=ctx.search("cn=users","cn="+userName,sctr);
280
281
String uid="";
282
String userGuid="";
283
String dn="";
284
285
while(rs!=null && rs.hasMore())
{
286
SearchResult el=rs.nextElement();
287
Attribute attrCn=el.getAttributes().get("cn");
288
Attribute attrUid=el.getAttributes().get("uid");
289
Attribute attrUserGuid=el.getAttributes().get("apple-generateduid");
290
291
if(attrCn.get(0).toString().trim().equalsIgnoreCase(userName))
{
292
uid=attrUid.get(0).toString();
293
userGuid=attrUserGuid.get(0).toString();
294
dn=el.getName();
295
296
break;
297
}
298
}
299
300
if(dn=="")
{
301
throw new Exception("没有找到此用户");
302
}
303
304
ModificationItem[] mods=new ModificationItem[2];
305
306
mods[0]=new ModificationItem(DirContext.ADD_ATTRIBUTE,
307
new BasicAttribute("memberUid",uid));
308
mods[1]=new ModificationItem(DirContext.ADD_ATTRIBUTE,
309
new BasicAttribute("apple-group-memberguid",userGuid));
310
311
ctx.modifyAttributes("cn="+groupName+",cn=groups", mods);
312
313
result="true";
314
315
ctx.close();
316
}
317
catch(Exception ex)
{
318
ex.printStackTrace();
319
result="false";
320
}
321
322
return result;
323
}
324
325
/** *//**
326
* 从组中删除用户
327
* @param env XML格式LDAP配置信息
328
* @param groupName 组名称
329
* @param uid 用户ID
330
* @return
331
*/
332
public String deleteGroupUser(String env,String groupName,String uid)
{
333
DirContext ctx=null;
334
String result="";
335
336
try
{
337
SearchControls sctr=new SearchControls();
338
339
sctr.setSearchScope(2);
340
sctr.setReturningAttributes(new String[]
{"apple-generateduid"});
341
342
ctx=this.connect(env);
343
NamingEnumeration<SearchResult> rs=ctx.search("cn=users","uid="+uid,sctr);
344
345
String userGuid="";
346
347
while(rs!=null && rs.hasMore())
{
348
SearchResult el=rs.nextElement();
349
userGuid=el.getAttributes().get("apple-generateduid").get(0).toString();
350
}
351
352
ModificationItem[] mods=new ModificationItem[2];
353
354
mods[0]=new ModificationItem(DirContext.REMOVE_ATTRIBUTE,
355
new BasicAttribute("memberUid",uid));
356
mods[1]=new ModificationItem(DirContext.REMOVE_ATTRIBUTE,
357
new BasicAttribute("apple-group-memberguid",userGuid));
358
359
ctx.modifyAttributes("cn="+groupName+",cn=groups", mods);
360
361
ctx.close();
362
363
result="true";
364
}
365
catch(Exception ex)
{
366
ex.printStackTrace();
367
result="false";
368
}
369
370
return result;
371
}
372
373
/** *//**
374
* 删除用户
375
* 没有真正删除用户
376
* 是把用户的长名和短名改为可用格式
377
* @param env XML格式LDAP配置信息
378
* @param format 可用用户名的格式
379
* @param name 用户名称
380
* @return
381
*/
382
public String deleteUser(String env,String format,String name)
{
383
DirContext ctx=null;
384
String result="";
385
386
try
{
387
SearchControls sctr=new SearchControls();
388
389
sctr.setSearchScope(2);
390
sctr.setReturningAttributes(new String[]
{"uid"});
391
392
ctx=this.connect(env);
393
NamingEnumeration<SearchResult> rs=ctx.search("cn=users","cn="+name,sctr);
394
395
String dn="";
396
397
while(rs!=null && rs.hasMore())
{
398
dn=rs.nextElement().getName();
399
400
break;
401
}
402
403
if(dn=="")
{
404
throw new Exception("没有找到此用户");
405
}
406
407
String dnName=dn.replace("uid=", "").trim();
408
409
ModificationItem[] mods=new ModificationItem[2];
410
411
mods[0]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
412
new BasicAttribute("sn", dnName));
413
mods[1]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
414
new BasicAttribute("cn", dnName));
415
416
ctx.modifyAttributes(dn+",cn=users", mods);
417
418
result="true";
419
420
ctx.close();
421
}
422
catch(Exception ex)
{
423
ex.printStackTrace();
424
result="false";
425
}
426
427
return result;
428
}
429
430
/** *//**
431
* 获取指定组的用户
432
* @param env XML格式LDAP配置信息
433
* @param groupName 组名
434
* @param ctr XML格式SearchControls
435
* @return
436
*/
437
public String getGroupUsers(String env,String groupName,String ctr)
{
438
DirContext ctx=null;
439
String result="";
440
441
try
{
442
SearchControls sctr=new SearchControls();
443
444
sctr.setSearchScope(2);
445
sctr.setReturningAttributes(new String[]
{"memberUid"});
446
447
ctx=this.connect(env);
448
NamingEnumeration<SearchResult> rs=ctx.search("cn=groups","cn="+groupName,sctr);
449
450
ArrayList<String> uids=new ArrayList<String>();
451
452
while(rs!=null && rs.hasMore())
{
453
SearchResult el=rs.nextElement();
454
Attribute attrUids=el.getAttributes().get("memberUid");
455
456
NamingEnumeration<?> nAttrUids=attrUids.getAll();
457
458
while(nAttrUids!=null && nAttrUids.hasMore())
{
459
Object uid=nAttrUids.nextElement();
460
461
uids.add(uid.toString());
462
}
463
}
464
465
int uidsSize=uids.size();
466
467
if(uidsSize>0)
{
468
sctr=null;
469
sctr=this.parseXmlToSearchControls(ctr);
470
DocumentBuilder docBuilder=DocumentBuilderFactory.newInstance().newDocumentBuilder();
471
472
Document xmlDoc=docBuilder.newDocument();
473
474
Element rootEl=xmlDoc.createElement("searchResult");
475
476
for(int i=0;i<uidsSize;i++)
{
477
rs=null;
478
rs=ctx.search("cn=users", "uid="+uids.get(i),sctr);
479
480
while(rs!=null && rs.hasMore())
{
481
SearchResult el=rs.nextElement();
482
String elName=el.getName();
483
NamingEnumeration<? extends Attribute> attrs=el.getAttributes().getAll();
484
485
Element recordEl=xmlDoc.createElement("record");
486
487
recordEl.setAttribute("name", elName);
488
489
while(attrs!=null && attrs.hasMore())
{
490
Attribute attr=attrs.next();
491
NamingEnumeration<?> attrEnu=attr.getAll();
492
String attrName=attr.getID();
493
494
while(attrEnu!=null && attrEnu.hasMore())
{
495
Object o=attrEnu.next();
496
Element attrEl=xmlDoc.createElement("attribute");
497
498
attrEl.setAttribute("name",attrName);
499
attrEl.setTextContent(o.toString());
500
501
recordEl.appendChild(attrEl);
502
}
503
}
504
505
rootEl.appendChild(recordEl);
506
}
507
}
508
509
xmlDoc.appendChild(rootEl);
510
511
result=xmlDocumentToString(xmlDoc);
512
}
513
}
514
catch(Exception ex)
{
515
ex.printStackTrace();
516
result="false";
517
}
518
519
return result;
520
}
521
522
/** *//**
523
* 删除组
524
* @param env XML格式LDAP配置信息
525
* @param name 组名
526
* @return
527
*/
528
public String deleteGroup(String env,String name)
{
529
DirContext ctx=null;
530
String result="";
531
532
try
{
533
ctx=this.connect(env);
534
535
ctx.destroySubcontext("cn="+name+",cn=groups");
536
537
ctx.close();
538
539
result="true";
540
}
541
catch(Exception ex)
{
542
ex.printStackTrace();
543
result="false";
544
}
545
546
return result;
547
}
548
549
/** *//**
550
* 添加组
551
* @param env XML格式LDAP配置信息
552
* @param name 组名称
553
* @return
554
*/
555
public String addGroup(String env,String name)
{
556
DirContext ctx=null;
557
String result="false";
558
559
try
{
560
int gidNumber=this.getMaxGeneratedNumber(env,"groups","gidNumber");
561
562
if(gidNumber>0)
{
563
BasicAttributes battrs=new BasicAttributes();
564
BasicAttribute battr= new BasicAttribute("objectClass");
565
566
battr.add("posixGroup");
567
battr.add("apple-group");
568
battr.add("extensibleObject");
569
570
battrs.put(battr);
571
battrs.put("gidNumber",String.valueOf(gidNumber));
572
battrs.put("cn",name);
573
battrs.put("apple-group-realname",name);
574
battrs.put("apple-generateduid",java.util.UUID.randomUUID().toString().toUpperCase());
575
576
ctx=this.connect(env);
577
578
ctx.createSubcontext("cn="+name+",cn=groups",battrs);
579
580
ctx.close();
581
582
result="true";
583
}
584
}
585
catch(Exception ex)
{
586
ex.printStackTrace();
587
result="false";
588
}
589
590
return result;
591
}
592
593
/** *//**
594
* 返回自动生成ID的可用数字
595
* @param env XML格式LDAP配置信息
596
* @param cn 查找的节点
597
* @param genAttr 自动生成ID的属性名称
598
* @return
599
*/
600
public int getMaxGeneratedNumber(String env,String cn,String genAttr)
{
601
DirContext ctx=null;
602
int maxGen=0;
603
604
try
{
605
SearchControls sctr=new SearchControls();
606
607
sctr.setSearchScope(2);
608
sctr.setReturningAttributes(new String[]
{genAttr});
609
610
ctx=this.connect(env);
611
NamingEnumeration<SearchResult> rs=ctx.search("cn="+cn,genAttr+"=*",sctr);
612
613
while(rs!=null && rs.hasMore())
{
614
SearchResult el=rs.nextElement();
615
Attribute attr=el.getAttributes().get(genAttr);
616
617
int genNumber=Integer.parseInt(attr.get(0).toString());
618
619
if(maxGen<genNumber)
{
620
maxGen=genNumber;
621
}
622
}
623
624
ctx.close();
625
}
626
catch(Exception ex)
{
627
ex.printStackTrace();
628
maxGen=0;
629
}
630
631
return maxGen;
632
}
633
}
634

2

3

4

5

6

7

8

9

10

11

12

13



14


15

16

17

18

19

20



21

22

23

24

25

26

27

28

29

30

31


32

33

34

35

36

37



38

39

40

41

42

43

44

45

46

47

48


49

50

51

52

53

54



55

56

57

58

59

60

61

62



63

64

65



66

67

68



69

70

71



72

73

74



75

76

77



78

79

80



81

82

83

84

85

86

87

88

89


90

91

92

93

94

95



96

97

98

99

100

101

102

103

104



105

106

107



108

109

110



111

112

113



114

115

116



117

118

119



120

121

122



123

124

125



126

127

128

129

130

131

132

133


134

135

136

137

138

139

140

141



142

143

144

145

146

147



148

149



150

151

152

153

154

155

156

157

158

159

160

161



162

163

164

165

166

167

168

169

170



171

172

173

174

175



176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195



196

197

198

199

200

201

202


203

204

205

206

207

208

209

210

211



212

213

214

215



216

217

218

219



220

221

222

223

224

225

226



227

228

229



230

231

232

233

234

235

236



237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253



254

255

256

257

258

259

260

261


262

263

264

265

266

267

268



269

270

271

272



273

274

275

276



277

278

279

280

281

282

283

284

285



286

287

288

289

290

291



292

293

294

295

296

297

298

299

300



301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317



318

319

320

321

322

323

324

325


326

327

328

329

330

331

332



333

334

335

336



337

338

339

340



341

342

343

344

345

346

347



348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365



366

367

368

369

370

371

372

373


374

375

376

377

378

379

380

381

382



383

384

385

386



387

388

389

390



391

392

393

394

395

396

397



398

399

400

401

402

403



404

405

406

407

408

409

410

411

412

413

414

415

416

417

418

419

420

421

422



423

424

425

426

427

428

429

430


431

432

433

434

435

436

437



438

439

440

441



442

443

444

445



446

447

448

449

450

451

452



453

454

455

456

457

458



459

460

461

462

463

464

465

466

467



468

469

470

471

472

473

474

475

476



477

478

479

480



481

482

483

484

485

486

487

488

489



490

491

492

493

494



495

496

497

498

499

500

501

502

503

504

505

506

507

508

509

510

511

512

513

514



515

516

517

518

519

520

521

522


523

524

525

526

527

528



529

530

531

532



533

534

535

536

537

538

539

540

541



542

543

544

545

546

547

548

549


550

551

552

553

554

555



556

557

558

559



560

561

562



563

564

565

566

567

568

569

570

571

572

573

574

575

576

577

578

579

580

581

582

583

584

585



586

587

588

589

590

591

592

593


594

595

596

597

598

599

600



601

602

603

604



605

606

607

608



609

610

611

612

613



614

615

616

617

618

619



620

621

622

623

624

625

626



627

628

629

630

631

632

633

634

具体代码: