商店有顾客。每个客户使用他们的用户ID和密码登录商店。
我想创建一个Alloy函数(<servlet>
<servlet-name>WSTutorial</servlet-name>
<servlet-class>WSTutorial</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>WSTutorial</servlet-name>
<url-pattern>/WSTutorial</url-pattern>
</servlet-mapping>
),当传递凭据(userID和密码)时,返回拥有这些凭据的客户:
fun
我已经说服自己,要做到这一点,我必须以这种方式声明客户签名:
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
)的签名字段总是更好。你是否也有这种信念?
以下是我的Alloy型号:
userID: UserID
答案 0 :(得分:2)
我不同意,您可以使用set comprehension轻松检索具有作为参数给出的id和密码的客户集。
看看这个模型(我冒昧地不假设每个客户都有不同的密码(&#34;密码123&#34;只是太常见了; - ))。
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 {}
答案 1 :(得分:1)
嗯,这是我工作的一个区域,所以我无法展示密码不会被更加小心对待的例子:-)我知道这只是一个例子,但是人们因为一个不安全的密码模型而死了! (我喜欢夸张。)作为一个模块化狂热者,我也认为你应该将认证任务与客户的检索分开,它们本身并不是耦合的,所以应该是分开的。
我的模型因此是:
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}