Spring LDAP - 如何管理编码(SHA)密码

Fre*_*red 2 spring ldap change-password sha spring-ldap

我想使用Spring LDAP实现一个基本的用户存储库,它是对象目录映射(ODM)的概念.

我的User类非常简单:

@Entry(objectClasses = { "inetOrgPerson", "organizationalPerson", "person", "shadowAccount", "top" }, base = "ou=people")
public class User {
    [...]

    @Id
    private Name dn;

    @Attribute(name = "uid")
    @DnAttribute(value = "uid")
    private String username;

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

    @Attribute(name = "givenName")
    private String firstName;

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

    @Attribute(name = "o")
    private String organization;

    @Attribute(name = "userPassword")
    private String password;

    // Getters & Setters
    [...]
}
Run Code Online (Sandbox Code Playgroud)

和我的存储库的基本方法:

public User findByUid(String uid) {
    return ldapTemplate.findOne(query().where("uid").is(uid), User.class);
}

public void update(User user) {
    ldapTemplate.update(user);
}
Run Code Online (Sandbox Code Playgroud)

除密码属性外,一切正常.例如,如果我只更改用户名,则密码也会更改.

我想知道如何处理编码密码(使用SHA - 安全散列算法).

我没有看到任何允许指定编码方法的注释.

我们必须手动处理吗?

Joh*_*mer 7

精简版

@Attribute(name = "userPassword", type = Type.BINARY)
private byte[] password;
Run Code Online (Sandbox Code Playgroud)

是您的密码属性的正确定义.这是因为LDAP也将密码存储为二进制文件.

要提供便捷的交互方式,您应该修改setter password

public void setPassword(String password) {
    this.password = password.getBytes(Charset.forName("UTF-8"));
}
Run Code Online (Sandbox Code Playgroud)

长版

问题是你的定义userPassword.它是一个java.lang.String.Spring LDAP ODM属性注释默认为Type.STRING

您的LDAP将字符串作为字节数组获取并检查它是否具有正确的前缀(在我们的示例中{SSHA}).如果没有前缀,则使用其配置的哈希算法对给定字符串进行哈希处理,并将其作为二进制文件存储在属性中.这就是根本原因.您的属性定义不同.LDAP有一个二进制文件,你有一个字符串.

再次读取条目时,要修改名字,也会读取密码属性.但是,因为它应该是对象中的字符串,所以Spring将二进制数组转换为字符串.这种转换是错误的,因为它创建了一个字符串.

例如

  • 你输入test实体对象的密码字段.
  • Spring接受字符串并将其未经修改地发送到LDAP服务器.
  • 服务器散列字符串并将其保存为 {SSHA}H97JD...
  • 你再次阅读该条目
  • spring获取一个byte [],其中包含表示存储值的ascii数字

    [123, 83, 83, 72, 65, 125, 72, 57, 55, 74, 68, ...]

  • 转换为字符串会导致以下结果:

    123,83,83,72,65,125,72,57,55,74,68,...

  • spring在您的实体中将此字符串设置为密码值

  • 你修改了名字
  • spring再次获取密码字符串并将其原样发送到服务器
  • 服务器前缀检查表示未散列的密码,并在字符串上再次应用哈希算法,因为123,83,启动不是{SSHA}
  • 服务器再次更改密码.