關於openLADP的進一步瞭解(@Id與@DnAttribute)

李明發表於2023-01-18

前言:本週主要對gitlabWebhook轉github的專案寫了寫前臺部分掃了掃尾,並沒有遇到什麼問題,所以就上週LDAP中的疑問進行了進一步的瞭解。
承接上文中的問題:@Id和@DnAttribute之間是什麼關係。為什麼在ldapAdmin中沒有找到@ID對應的欄位。

@Data
@Entry(base = "", objectClasses="inetOrgPerson")
public class Person {

  /**
   * 此欄位不能少
   */
  @Id
  private Name id;

  @DnAttribute(value = "uid", index = 3)
  private String uid;

  @DnAttribute(value = "title", index = 4)
  private String title;

  @Attribute(name = "cn")
  private String commonName;

  @Attribute(name = "sn")
  private String myUerName;

  private String userPassword;

}

就拿上面這個實體來說,我們可以用如下方法查詢它內部的屬性:

List<Person> list = ldapTemplate.search("", filter, new AttributesMapper() {
      @SneakyThrows
      @Override
      public Object mapFromAttributes(Attributes attributes) throws NamingException {
        NamingEnumeration<? extends Attribute> att = attributes.getAll();
        while (att.hasMore()) {
          Attribute a = att.next();
          System.out.println(a.getID() + "=" + a.get());
        }
}

但是結構中並沒有列印出id這一項,但是如果沒有這一項在創造實體時會報如下錯誤。
image.png
報的很直接,就是缺少ID,那麼我們就要去ldapTemplate.creat函式里面去打點,看看報錯是怎麼來的。
測試後發現報錯出現在這裡:
image.png
那麼我們再把ID屬性新增完再來看這裡。
image.png
由於我們生成ID時沒有給ID賦值,他會自動生成ID,而他自動生成的ID就是由我們在試題中宣告的 @DnAttribute 註解來的,根據所給的優先順序進行排序生成。

就類似於@ID是由@DnAttribute統一構成的聯合主鍵,只不過由於LDAP是樹形儲存,主鍵之間需要有優先順序之分,來區別那一項是哪一項的上級節點。

那麼他的儲存形式是什麼呢?
拿下面的實體來舉例:

  @Test
  public void addPerson() {
    Person person = new Person();
    person.setUid("uid:17");
    person.setTitle("13131000001");
    person.setMyUerName("liMing");
    person.setCommonName("liming");
    person.setUserPassword("123456");
    ldapTemplate.create(person);
  }

他在庫中的儲存形式如下,因為UID的優先順序要比title高,所以在父實體中。
image.png
那麼我們如果不給@DnAttribute屬性賦初值呢?
就會報如下錯誤:
image.png

總結來說的話就是@Id是為了構造該實體的DN而存在的,而id是根據@DnAttribute的屬性生成的,LDAP中Dn的構造是源於我們一開始對基礎dn的配置以及儲存實體的@Id欄位。

也就是說這一部分是根據@ID欄位生成的
image.png

那麼理所當然@DnAttribute註解欄位也就不能隨意更改了,如果按照之前的普通屬性修改方法:

  @Test
  public void update(){
    String oldPersonDn = "uid=uid:17";
    Person newPerson = new Person();
    newPerson.setUid("uid=uid:29");
      ldapTemplate.modifyAttributes(oldPersonDn, new ModificationItem[] {
          new ModificationItem(DirContext.REPLACE_ATTRIBUTE, new BasicAttribute("uid", newPerson.getUid().trim())),
      });
  }

會報如下錯誤:

[LDAP: error code 64 - value of naming attribute 'uid' is not present in entry]

也就是說@DnAttribute註解後,LDAP並沒有把它當做普通屬性。
如果我們要修改DN的話(當然一般情況下不應修改dn)可以使用如下方法修改:

ldapTemplate.rename(oldPersonDn, newPersonDn);

遇到的其他小問題:

在初始化前臺時出現了這樣的報錯:

Error creating bean with name 'entityManagerFactory' defined in class path resource [...]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service
. . . . . .
Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service 

去網上查閱之後基本都是說是配置檔案沒有配置完全。
下面是我的配置檔案(application.properties):

server.port=8088
dingTalkUrlPre=https://oapi.dingtalk.com/robot/send
spring.datasource.driver-class-name= com.mysql.cj.jdbc.Driver
spring.datasource.url="jdbc:mysql://localhost:3310/setting?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai"
spring.datasource.username=root
spring.datasource.password=root
spring.jpa.generate-ddl=true
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.dialect="org.hibernate.dialect.MySQL57Dialect"
spring.jpa.hibernate.ddl-auto=update
spring.jpa.database=mysql

並沒有發現有哪些項沒有配置完全,之後才發現是因為spring.jpa.properties.hibernate.dialect和另一個配置項後面的引數用引號括起來了,在application.yml中是否新增引號並不影響識別,但是在application.properties中卻不行,之前並沒有關注過這些,導致了這個錯誤。

相關文章