代码之家  ›  专栏  ›  技术社区  ›  Roger Costello

使用关系值创建签名字段是最佳做法吗?

  •  0
  • Roger Costello  · 技术社区  · 6 年前

    商店有顾客。每个客户都使用其用户名和密码登录商店。

    我想创建一个合金函数( fun )当传递凭据(用户ID和密码)时,返回拥有这些凭据的客户:

    fun customerWithTheseCredentials[userID: UserID, password: Password]: Customer {
        ???
    }
    

    我确信,要做到这一点,我必须以这种方式声明客户签名:

    sig Customer {
        credentials: UserID lone -> lone Password
    }
    

    通过这种方式创建签名,我可以通过以下方式实现该功能:

    fun customerWithTheseCredentials[userID: UserID, password: Password]: Customer {
        credentials.password.userID
    }
    

    我是否以这种方式创建了客户签名:

    sig Customer {
        userID: UserID,
        password: Password
    }
    

    那么我就不能实现这个功能了。你同意吗?

    我坚信,设计签名字段时最好使用关系值(例如。, credentials: UserID lone -> lone Password )而不是集合(例如。, userID: UserID ). 你也有这样的信念吗?

    以下是我的合金模型:

    sig UserID {}
    sig Password {}
    sig Customer {
        credentials: UserID lone -> lone Password
    } 
    
    fun customerWithTheseCredentials[userID: UserID, password: Password]: Customer {
        credentials.password.userID
    }
    
    run {}
    
    fact Every_customer_has_a_different_password_userID {
        // Every customer has a different userID
        no disj c, c': Customer | 
            c.credentials.Password = c'.credentials.Password
        // Every customer has one userID/password pair
        all c: Customer |
            one id: UserID |
                one p: Password |
                    c.credentials = id -> p
    }
    
    2 回复  |  直到 6 年前
        1
  •  2
  •   Loïc Gammaitoni    6 年前

    我不同意,您可以使用集合理解来轻松检索id和密码作为参数的客户集合。

    看看这个模型(我冒昧地假设每个客户都有不同的密码(“password123”非常常见;-))。

    sig UserID {}
    sig Password {}
    sig Customer {
        id :disj UserID,
        password: Password
    } 
    
    fun customerWithTheseCredentials[userID: UserID, pass: Password]: Customer {
        {c:Customer| c.id=userID and c.password=pass}
    }
    
    run {}
    
        2
  •  1
  •   Peter Kriens    6 年前

    好吧,这是我工作的一个领域,所以我无法展示一个密码不会被更加小心对待的示例:-)我知道这只是一个示例,但人们死于不安全的密码模型!(我喜欢夸张。)作为一个模块化怪胎,我还认为应该将身份验证任务与客户检索分离开来,它们不是天生耦合的,所以应该分开。

    因此,我的模式是:

    sig UserId, PasswordDigest {}
    sig Password { digest : disj PasswordDigest }
    
    sig Customer {
        identity : disj UserId
    }
    
    one sig Authenticator {
        db : UserId lone -> one PasswordDigest
    }
    
    pred authenticate[ id : UserId, password : Password ] {
        password.digest in Authenticator.db[id]
    }
    
    fun customerWithTheseCredentials[ userid: UserId, password : Password ] : lone Customer {
        authenticate[ userid, password ] => identity.userid else none
    }
    
    run { #Customer = 3 and #Password=3}