我正在尝试围绕 Elm 进行思考。我有 Haskell 经验和一点 Erlang。
我想完成以下练习:
- 向用户显示登录表单
- 提交时,前端向
localhost/auth
发出请求以尝试接收身份验证 token 。 - 成功后,会显示主页,其中会获取一些数据。
- 失败时,登录屏幕会显示错误。
这是非常基础的,但希望足够复杂以模拟真实网络应用的行为。
我的第一个问题是模型
。如果客户端经过身份验证,我只需要数据。我应该把它包装在类似于 Maybe
monad 的东西中吗?
type Model
= NoAuth String String
| AuthFetching
| AuthFailed err
| AuthSuccess String
然后登录屏幕可以显示微调器和错误,或重定向到新页面。
这感觉就像将其余的应用程序状态与身份验证状态联系在一起。虽然是“正确的”,但让整个模型成为一个(变体类型?)只有一条记录感觉不对。
这样的模型“感觉”更正确:
type FetchStatus
= Loading
| Success val
| Err err
type Model =
{ token : RequestStatus String
, data : List number
}
但无论何时更新模型,您现在都需要检查 token
是否仍然存在 - 即记录中的模式匹配。第一个例子,只需要对整个模型进行模式匹配,比较简单。
为了保持登录表单状态,我需要添加额外的字段:
type Model =
{ token : RequestStatus String
, data : List number
, username : String
, password : String
}
这感觉不对,因为登录后不应将 password
保存在内存中。我会将这些保存在记录中,但我不能在自定义 type
声明中使用记录。
总而言之,我有点困惑。有人可以阐明最“正确”、最惯用的方法吗?
最佳答案
所有授权相关的东西都应该在后端处理。 Elm 的工作只是显示服务器发送给它的内容。在我看来,您提出的第一个选项对于这样一个小例子是最好的,但在更现实的应用程序中,类型系统会更复杂:
type LoginForm =
{ username : String
, password : String
}
type Activity
= Login LoginForm
| LoginSuccess
| LoginFailure String
type Model =
{ loggedUser : Maybe String
, activity : Activity
, ...
}
您不需要(也不应该)在前端保留密码。您也不应该在客户端执行任何授权,因为客户端可以轻松地替换其浏览器中的任何脚本。后端将跟踪用户是否通过例如登录。 session cookie。在这种情况下,即使 loggedUser
值设置为 Just "someguy"
并且 "someguy"未标记为在服务器数据库中登录,任何需要授权的操作都将失败.
总结、处理登录和授予访问任何内容的权限是后端的工作。 Elm 是前端语言,所以这里的唯一目的是显示内容。
关于authentication - Elm 中的惯用身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54526526/