我知道这不是第一次在StackOverflow中处理该主题,但是,我有一些我找不到答案的问题,或者其他问题有相反的答案。
我正在做一个相当简单的REST API(Silex-PHP),最初仅由一个SPA(主干应用程序)使用。我不想评论此问题中的所有几种身份验证方法,因为该主题已经在SO上完全介绍了。我将基本上为每个用户创建一个令牌,并且该令牌将附加到需要SPA进行身份验证的每个请求中。所有SPA服务器事务将在HTTPS下运行。目前,我的决定是令牌不会过期。每个会话的过期令牌/令牌不符合REST的无状态性,对吗?我知道安全性还有很大的改进空间,但这是我目前的范围。
我有一个令牌模型,因此在数据库中有一个表,其中包含FK到user_id的令牌。我的意思是令牌不是我的用户模型的一部分。
我有一个POST / users(无需身份验证),它在数据库中创建一个用户并返回新用户。这符合一个请求一个资源规则。但是,这给我带来了一些疑问:
我的想法是,在创建一个新用户,为该用户创建一个新令牌,立即将其与Response一起返回时,从而改进了UX。用户将立即能够开始使用Web应用程序。但是,为此类响应返回令牌将破坏仅返回资源的规则。我应该一起提出两个请求吗?一个是创建用户,另一个是检索令牌,而无需用户重新输入凭据?
如果我决定与用户一起返回令牌,那么我相信POST / users对于API使用者会造成混淆,然后出现类似POST / auth / register的信息。再一次,我不喜欢这个想法,因为它涉及一个动词。我真的很喜欢这个答案提供的简单性。但是再一次,我需要一起执行两个请求,一个POST / users和一个POST / tokens。同时执行两个请求是多么的错误,而且,如果两个请求一起发送,我将如何准确发送要附加到特定用户的令牌的相关信息?
现在,我的流程如下所示:
1. Register form makes a POST /users request
2. Server creates a new user and a new token, returns both in the response (break REST rule)
3. Client now attaches token to every Request that needs Authorization
令牌永不过期,从而保持REST无状态。
当前的大多数Web应用程序都需要在不破坏用户体验的情况下进行电子邮件验证,即用户可以在注册后立即使用Web应用程序。另一方面,如果我按照上述建议将令牌与注册请求一起返回,则用户无需验证电子邮件即可立即访问每个资源。
通常,我会执行以下工作流程:
1. Register form sends POST /users request.
2. Server creates a new user with validated_email set to false and stores an email_validation_token. Additionally, the server sends an email generating an URL that contains the email_validation_token.
3. The user clicks on the URL that makes a request: For example POST /users/email_validation/{email_validation_token}
4. Server validates email, sets validated_email to true, generates a token and returns it in the response, redirecting the user to his home page at the same time.
这看起来过于复杂,并且完全破坏了UX。你怎么样了?
这很简单,因为现在我是用这种方式做的,所以如果出错,请纠正我:
1. User fills a log in form which makes a request to POST /login sending Basic Auth credentials.
2. Server checks Basic Auth credentials and returns token for the given user.
3. Web app attached the given token to every future request.
login是一个动词,因此违反了REST规则,尽管每个人似乎都同意这样做。
为什么每个人似乎都需要/ auth / logout端点?从我的角度来看,在Web应用程序中单击“注销”基本上应该从应用程序中删除令牌,而不是在其他请求中发送令牌。服务器对此不起作用。
由于可能会将令牌保留在localStorage中,以防止在可能的页面刷新时丢失令牌,因此注销也将意味着从localStorage中删除令牌。但这仍然不会影响服务器。我了解需要POST / logout的人基本上都在使用会话令牌,这再次打破了REST的无状态性。
我了解记住我基本上是指在我的情况下是否将返回的令牌保存到localStorage。这是正确的吗?
如果您建议进一步阅读该主题,我将非常感激。谢谢!
寄存器
每个会话的过期令牌/令牌不符合REST的无状态性,对吗?
不,这没有错。许多HTTP身份验证方案确实具有过期令牌。OREST2在REST服务中非常流行,许多OAuth2实现强制客户端不时刷新访问令牌。
我的想法是,在创建一个新用户,为该用户创建一个新令牌,立即将其与Response一起返回时,从而改进了UX。用户将立即能够开始使用Web应用程序。但是,为此类响应返回令牌将破坏仅返回资源的规则。我应该一起提出两个请求吗?一个是创建用户,另一个是检索令牌,而无需用户重新输入凭据?
通常,如果您遵循REST最佳实践创建新资源,则不会返回任何信息来响应这样的POST。这样做会使调用更像RPC,因此在这里我同意您的观点……它不是完全RESTful的。我将为此提供两种解决方案:
假设您要使用OAuth2(这不是一个坏主意!)。由于多种原因,OAuth2 API并不是真正的RESTful。我想最好还是使用定义良好的身份验证API,而不是为了获得RESTful而滚动自己的身份验证API。
这仍然给您带来了在API上创建用户的问题,并响应此(POST
)调用,返回了可用作访问/刷新令牌的秘密。
我的替代方法如下:
您无需拥有用户即可开始会话。
相反,您可以做的是在创建用户之前启动会话。这样可以保证在以后的通话中,您都知道自己正在与同一个客户通话。
如果您开始OAuth2流程并收到访问/刷新令牌,则只需在上执行经过身份验证的POST请求即可/users
。这意味着您的系统需要知道两种经过身份验证的用户:
grant_type = client_credentials
)。创建用户后,您可以为新创建的用户实体分配以前的匿名会话,因此创建后无需进行任何访问/刷新令牌交换。
电子邮件验证
您对以下两个方面的建议:
由应用程序完成。哪一个更合适,实际上取决于您的应用程序以及最适合您的应用程序。用户开始使用他们不拥有的电子邮件帐户是否有与之相关的风险?如果否,那么允许用户立即进入就可以了。
这是您不希望执行此操作的示例:如果系统的其他成员使用该电子邮件地址将用户添加为朋友,则该电子邮件地址是一种身份。如果您不强迫用户验证其电子邮件,则意味着我可以代表具有不同电子邮件地址的某人行事。这类似于能够接收邀请等。这是攻击媒介吗?然后,您可能需要考虑在验证电子邮件之前阻止用户使用该应用程序。
您可能还考虑只阻止应用程序中电子邮件地址可能敏感的某些功能。在上一个示例中,您可以阻止人们在验证电子邮件之前看到其他用户的邀请。
这里没有正确的答案,这仅取决于您打算如何使用电子邮件地址。
登录
请只使用OAuth2。您描述的流程已经非常接近OAuth2的工作方式。实际使用OAuth2更进一步。这非常好,一旦您克服了理解协议的最初障碍,就会发现它比您想象的要容易得多,并且只需实现您的API特别需要的位就相当简单。
大多数PHP OAuth2服务器实现都不是很好。他们做得太多,很难整合。自己动手并不难,而且您已经接近建立类似的东西了。
登出
您可能需要注销端点的两个原因是:
记得我
是的,用本地存储实现“记住我”听起来是个好主意。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句