我有点陷入困境,我无法找到解决方案。我有一个rails站点,它使用前端的devise和api的devise_token_auth。前端使用服务器端呈现页面和api调用的组合来向用户显示数据。 如果我使用纯角度登录,登录表格将最终工作(通常2-3次提交):
%div{'ng-controller'=>'logInCtrl'}
%h2 Log In
%div{:layout=>'column'}
%div{:flex=>20}
%div{:flex=>60, :layout=>'column'}
= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f|
%div{:layout=>'column'}
%md-input-container
=f.label :login
%input{'ng-model'=>'loginForm.login', :autofocus => 'true'}
%md-input-container
= f.label :password
%input{:type=>'password', 'ng-model'=>'loginForm.password', :autocomplete => 'off'}
%md-input-container
%md-button.md-raised.md-primary{'ng-click'=>'submitMe()'}
-#{:type=>'submit'}
%md-icon.mdi.mdi-account-key
Log In
:coffee
myApp.controller 'logInCtrl', ($scope, $resource, $http, $mdDialog, $auth ) ->
$scope.submitMe = () ->
$auth.submitLogin($scope.loginForm).then( (resp)->
location.replace('/users/sign_in')
)
如果我使用标准的post方法,服务器会呈现正确的信息,但没有为ng-token-auth
设置令牌。我可以在session #create上手动生成和发送令牌头:
# POST /resource/sign_in
def create
super do |user|
newAuth = user.create_new_auth_token
response.headers.merge!(newAuth)
end
end
我使用这种方法的问题是ng-token-auth从不从标题中提取令牌,因为它没有发出请求。我已经找到了一种手动设置令牌标头而没有运气的方法。
- 作为一方,我不会最终转向oauth解决方案,所以我使用的任何解决方法都需要移植到那个。 - 我应该提到服务器端渲染处理设计元素以及打开和关闭功能。我还使用current_user的元素来根据用户位置设置表名子集。
答案 0 :(得分:0)
经过一些研究和一段时间后,我想出了一个有效的解决方案,虽然有点hacky。
当Devise创建新会话时,将重定向调用到配置文件中指定的路由,因此设置任何变量都将丢失。第二个问题是ng-token-auth
只会设置和使用在登录功能期间设置的令牌,因此不会检测到通过页面标题发送令牌(这是浏览器的限制而不是代码)。
在为我的用户尝试使用ng-token-auth
和标准设计身份验证的不同迭代之后,我得出的结论是,最好首先使用设计授权用户,然后以某种方式设置带有ng-token-auth
的令牌;所以我开始研究ng-token-auth
在通过登录收到令牌时实际做了些什么。事实证明它设置了两个cookie:
currentConfigName |默认| 域 | / | exp date
auth_headers | 网址编码令牌数据 | 域 | / | exp date
现在的问题是如何将新生成的令牌传递给前端;这让我们变得比我想象的更简单。由于Rails中调用之间唯一的数据是会话数据,因此我决定在会话数据中添加一个标志,这标志着我的ApplicationController
生成一个新密钥。
首先我扩展了Devise::SessionsController#create
def create
super do |user|
session[:token] = true
end
end
这会将名为token
的会话变量设置为True
。比ApplicationController
我添加:
before_filter :set_token
def set_token
if session[:token] && user_signed_in?
newAuth = current_user.create_new_auth_token
response.headers.merge!(newAuth)
@auth_token = newAuth
session.delete(:token)
else
@auth_token = false
end
end
此前过滤器会查找session[:token]
,如果设置调用devise-token-auth
' s create_new_auth_token
功能,则需要登录'当前用户。此标头信息既写入传出页面标题,也分配给变量@auth_token
。
最后在 views / laoyouts / applicationhtml.haml 中,此代码块将添加到%body
代码
- if @auth_token
:coffee
myApp.controller 'cookieController', ($scope, $resource, $http, $mdDialog, $auth, ipCookie ) ->
ipCookie('auth_headers', "{\"access-token\": \"#{@auth_token['access-token']}\",\"token-type\": \"Bearer\",\"client\": \"#{@auth_token['client']}\",\"expiry\": \"#{@auth_token['expiry']}\",\"uid\": \"#{@auth_token['uid']}\"}", {path: "/",expires: 9999,expirationUnit: 'days',secure: false})
ipCookie('currentConfigName', 'default', {path: "/",expires: 9999,expirationUnit: 'days',secure: false})
%div{'ng-controller'=>'cookieController'}
这会添加一个空的div
标记和角度控制器,它使用写入@auth_token
的数据和ipCookie
函数(ng-token-auth
所需的)来编写必要的cookie。
一些注释:
ApplicationController
,因为当用户登录我的网站时,他们可能会被重定向到两个页面中的一个,具体取决于他们的凭据。这确保了无论发送到代码令牌的页面是什么,都会生成代码令牌并插入代码块。