Gem 珍爱生命,远离 devise

jasl · 发布于 2013年6月26日 · 最后由 andywang 回复于 2015年10月11日 · 4994 次阅读
1107

过去一直采用纯oauth方式登录,今天增加了邮件密码方式登录。 方案很标准 mongodb+devise+omniauth

由于直接通过oauth方式登录的话是不会填写邮箱和密码的,所以email和password字段都为空。 通过oauth方式注册用户的代码:

def create_from_omniauth(data)
  create do |user|
    auth = Auth.from_omniauth(data)
    user.auths << auth
    user.name = auth.nickname
    user.remote_avatar_url = auth.parse_image(data)
  end
end

有关的oauth回调代码

user = User.create_from_omniauth(omniauth)
user.update_from_omniauth(omniauth)
sign_in user
redirect_to edit_user_registration_path(:new => true)

要注意的是:由于devise的validatable的限制,email和password都是必填,所以按道理这个create是一定失败的,但是奇迹的是,保存确实成功了! 经过调试,create确实没保存成功,但是调用过sign_in方法后,user被持久化了,于是顺着sign_in一路查阅源码没有任何可疑的地方。。。

@lilu 突然提到,可能是trackable的问题,查阅源码,果然发现。。。

def update_tracked_fields!(request)
  old_current, new_current = self.current_sign_in_at, Time.now.utc
  self.last_sign_in_at     = old_current || new_current
  self.current_sign_in_at  = new_current

  old_current, new_current = self.current_sign_in_ip, request.remote_ip
  self.last_sign_in_ip     = old_current || new_current
  self.current_sign_in_ip  = new_current

  self.sign_in_count ||= 0
  self.sign_in_count += 1

  save(:validate => false) or raise "Devise trackable could not save #{inspect}." \
    "Please make sure a model using trackable can be saved at sign in."
end

在更新track的时候,会禁用validation,所以造成了上述问题,顺便看了下其他模块的代码,使用save :validate => false很频繁。

所以,如果因为一些原因要自己处理登录逻辑,调用sign_in之前,一定要确保对象的状态。

PS:这个问题很久前已经有人提issue 了,但是作者的回答完全不着边际 PS2:去济南的时候 @lgn21st 说过,能搞懂devise的绝对不是一般人... PS3:其实自从看到omniauth的设计后,就被深深吸引了,推荐大家放弃复杂的devise...虽然他很省事,但是需要实现一些用户系统的高级功能的时候,要考虑下自己能不能驾驭他...

共收到 29 条回复
6280

仅仅使用devise来实现它自带的那些功能时还是很方便的,一旦要自己定制点东西就麻烦了,前段时间就被坑过,最后干脆放弃不用了。。。

694

devuse用在快速构建上,要定制,算了,我真心觉得自己水平吃不透,

172

从不赞成使用这类gem 对自己水平提高没好处 踏上坑赔上的时间几倍都不止

2492

devise太重了,一般情况下用不到那么复杂的功能,还是自己写吧。

162

devise不算复杂,花点时间看一下源码,特别是models下面的几个able.rb,就能理解一下它为什么这么设计。对于掌握一个系统的用户登录,管理等基础设施来说,这点投资是绝对划算的。

162

另外,你说的这个问题,devise的wiki上已经提到过,可以翻一下wiki上关于omniauth集成的,password是用随机token,email是从api获取。

另另外,通常我喜欢用create!,提早抛出异常,而不是用create的返回值来判断

4584

不过devise的文档还是很丰富,基本都找到自己问题解决方案。我之前用过sorcery,也觉得很好用……说到定制,我也觉得devise很蛋疼,不知其它类似的gem是不是这样?

2622

还是很不错的,用起来方便

1297

发现LZ没看官方wiki的飘过

96

如果用omniauth进行OAuth登陆,可以将password(email也一样)设置为不需要。

def password_required?
  super && provider.blank?
end

这里的provider就是OAuth的provider,也可以设成任意的其它逻辑。

这样的话,既支持OAuth登陆,邮箱与密码登陆也不会受影响。

1107

#6楼 @quakewang 很多网站都不会返回email呀 这里的问题是 sign_in 本身是不应该影响model状态的,却影响了 devise的很多策略都会绕过validation,绕过validation后还失败才抛出异常,没想通他为什么要这样做

1107

#10楼 @hisea 嗯,昨晚花了些时间研究了下源码,搞定了

1107

#9楼 @leopku 关键是sign_in不应当影响model的状态呀,而且sign_in本身不对model操作,而是执行model里定义的devise策略,这样很难去debug

162

#11楼 @jasl 不会返回email的api,可以给用户随机生成一个

1107

#14楼 @quakewang 也不用,覆盖下email_required就好了,这样通过email是否为空还能判断一些东西

1553

#1楼 @edgar_wang_cn 放弃devise之后,请问你是怎么做用户系统的?

#5楼 @quakewang wiki应该讲的是how, 但我想知道why, 有没有哪里有讲devise设计的思想的,或者你可以分享一下看源码的心得?

谢谢!

1107

#16楼 @Peter 有很多啊,omniauth、authlogic、或者纯手写 几个月前我了解过omniauth的设计之后,已经被深深吸引了,虽然他还没有一个类似于devise的full-stack解决方案,但我自己写一个也可以

devise的源码不算难,warden那块才算有点小复杂,但是有大量的hook,所以不全面了解他的话...还是会踩坑里

1173

#17楼 @jasl 纯手写只是登陆注册啥的不算复杂,就是如果要做reset啊啥的逐渐就麻烦上去了-,- 如果定制要求不高,我觉得还是用devise,毕竟那么多人用过,测试充分。

77

跟安全有关的东西我觉得还是保守点好,毕竟 devise 经过大量项目验证,虽然自己写一个验证系统也不难,但万一疏忽了,那可能是难以挽回的损失

6280

#16楼 @Peter 我当时的要求比较简单,最后直接纯手写解决的。- -。

1107

#19楼 @HungYuHei omniauth authlogic同样经过验证的嘛!

#18楼 @xmonkeycn 确实,还是要用现有成熟的gem来做

当然,我这是标题党了...我几乎所有的项目都在用devise...

3753

#16楼 @Peter 纯手写也能做用户系统啊 只是复杂而已 太轻量级的系统有时就没必要用devise了啊 我自己的一个小系统的认证就只用了oauth 连gem都没用 直接写的HTTParty 2个函数解决 毕竟gem也是要占内存空间的

370

哈哈,楼主标题党! 对任何完善封装的产品进行定制化都是麻烦的,不仅 devise,类似的还能说好多: 珍惜生命,远离Rails(因为可定制化不如手写 HTML) 珍惜生命,远离Ruby(因为很多C容易做到的定制化,Ruby不能做) 珍惜生命,远离HTTP(因为如果要定制化一些数据链路层的结构,它做不到) 珍惜生命,远离餐厅(因为厨师给豆腐脑加了糖,而我希望自己加盐,它做不到) ……

1924

#11楼 @jasl 不是很多,是基本上没有,不可能将其比较敏感的用户信息数据返回给第三方的。

818

不要用 devise, 用 omniauth-identity 嘛. 统一用 omniauth

1107

#23楼 @kgen yeah!

96

#17楼 @jasl authlogic我不建议使用,commit得不活跃,很多提交issue都没解决,正准备迁到devise。

96

登录/注册 自己动手丰衣足食

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册