886 字
4 分钟
Vue 前端配合 Devise Token Auth 忘记密码重置操作

缘起#

近来开发个活动报名站,后端使用 Ruby on Rails,前端使用 Vue。由于是SPA,传统的 cookie 法就不太适宜,使用流行的 JWT。因此选用 Devise Token Auth gem 来处理用户模型与 token 发行、验证等工作。

密码重置流程#

其他模块使用正常且方便。而忘记密码重置涉及到邮件,reset link 发行等就显得麻烦。根据官方 wiki 记载 reset password flow

  • 在前端页面中填写邮箱地址输入框,有按钮可以发送重置邮件
  • POST /auth/password JSON: {email, redirect_url} 这里 redirect_url 为前端页面,有填写密码框
  • 后端生成 reset_password_token 与链接填入邮件,形如 http://localhost:3000/api/v1/auth/password/edit?config=default &redirect_url=http%3A%2F%2Flocalhost%3A8080%2Freset &reset_password_token=L77a9yx2JHehPCgVoQ2_
  • 前端跳转 redirect url
  • 前端用 reset_password_token、client、uid 作 headers PUT /auth/password 完成重置

观察链接,发现其中包含reset_password_tokenredirect_url,点击跳转前端链接 http://localhost:8080/reset?

access-token=D3zacAdKrGwRPxcQ-9rnXQ&

client=CwF0zNBw9ovM3KmHaCmIIg&

client_id=CwF0zNBw9ovM3KmHaCmIIg&

config=default&expiry=1538140242&reset_password=true&

token=D3zacAdKrGwRPxcQ-9rnXQ&

uid=1%40e.com

可见 headers 信息都有包含在 URL

问题#

网络中 devise token auth 重置密码相关的文章中使用 MVC,API的相对少,用 Vue 就更少。还得自己摸索。

问题1: hash 路径错位#

最初在项目中 Vue-router 使用 hash 模式,故在请求 json 中填写 redirect_url 包含 #。而 rails 处理后忽略掉 # 造成路径错误,这里可以改用 history 模式解决。URL 中的参数可用 route.query 取出。

另有 router navigation guard 的应设定确保不跳转,不然链接变成 http://localhost:8080/reset?

access-token=D3zacAdKrGwRPxcQ-9rnXQ&

client=CwF0zNBw9ovM3KmHaCmIIg&

client_id=CwF0zNBw9ovM3KmHaCmIIg&

config=default&expiry=1538140242&reset_password=true&

token=D3zacAdKrGwRPxcQ-9rnXQ&uid=1%40e.com#/login

这里本人设定未登录跳转登录页,跳转信息与重置 URL 混杂造成混乱。

Vue 复用密码修改组件(若有登录后修改选项的话)可抽离 request 函数,通过判别是否有登录信息(如 Vuex state、sessionStorage)构造不同的 headers 发送请求。

问题2: 后端路径 host 变前端 host(password#edit)#

原来 devise token anth 生成 reset password url 时取前端 host name,要是后端域名与之不同就出错。如前端 a.com,后端b.com,则邮件中生成 http://a.com/api/v1/auth/password/edit?...。看起来默认当作 MVC,是同域。

而在本地测试时同域端口不同没发现问题,可见靠同域不同端口区分。而部署到服务器用 80,443 端口就不区分了,怎么办呢?最后反代前端 /api 到 rails 解决。如 caddy 写法:

# 前端
a.com {
root /var/www/xxx
}
# 将错误路径导向 api
a.com/api {
proxy / locahost:3000/api {
transparent
}
}
# 后端
b.com {
proxy / locahost:3000 {
transparent
}
}

Bonus: custom Devise Token Auth registration controller#

设定用户删除账户时会同时删除创建的活动、与报名信息(人都跑路,活动显然没了,报名也吹了)防止出错(活动详细页获取不到创建人信息,报名信息有 null)

Devise Token Auth 中 用户注册、删除在 registration controller,默认删除操作只是完成用户删除不管别的。这时需要自定义。创建自定义类继承基类

class Users::RegistrationsController < DeviseTokenAuth::RegistrationsController
def destroy
@resource.events.each(&:destroy)
@resource.bookings.each(&:destroy)
super
end
end

由于在基类中已经获取到资源

module DeviseTokenAuth
class RegistrationsController < DeviseTokenAuth::ApplicationController
before_action :set_user_by_token, only: [:destroy, :update] # 这里 return @resource

因此可以直接使用,而不是向 super 加块处理。因为 super 的方法中块在 destroy 后

def destroy
if @resource
@resource.destroy
yield @resource if block_given? #destroy 后找不到用户相关联的活动
render_destroy_success
else
render_destroy_error
end
end

后记#

其他问题好找,这个就没有了(估计第一篇Rails 5 API + Devise Token Auth + Vue 的密码重置流)。完成这个也算尾声了,现在将要部署,而 production 如何设定,dockerfile 如何写就一脸懵逼。若有运维可以赐教就感激不尽。

Vue 前端配合 Devise Token Auth 忘记密码重置操作
https://blog.ckyol.moe/posts/dtaresetpasswdwithvue/
作者
ckyOL
发布于
2018-09-15
许可协议
CC BY-NC-SA 4.0

分享文章

生成精美分享图或复制链接,与更多人分享本文。

继续阅读

沿着主题读

基于共同的标签与分类

换条路线

从其他文章中稳定抽取

评论

正在加载评论...

最后更新于 ,距今已过 2918

部分内容可能已过时