【问题标题】:Authentication issue with Devise, devise_token_auth, and ng-token-authDevise、devise_token_auth 和 ng-token-auth 的身份验证问题
【发布时间】:2017-03-01 21:52:48
【问题描述】:

我有点卡住了,我无法找到解决方案。我有一个 Rails 站点,它使用 devise 作为前端,devise_token_auth 作为 api。前端使用服务器端渲染页面和 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')
      )

如果我使用标准发布方法,服务器会呈现正确的信息,但没有为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 的元素根据用户位置设置表名的子集。

【问题讨论】:

    标签: ruby-on-rails angularjs authentication devise


    【解决方案1】:

    经过一些研究和一点时间,我想出了一个可行的解决方案,虽然有点笨拙。

    当 Devise 创建新会话时,会调用重定向到配置文件中指定的路由,因此设置任何变量都会丢失。第二个问题是ng-token-auth 只会设置和使用在登录功能期间设置的令牌,因此不会检测到简单地通过页面标题发送令牌(这是浏览器的限制而不是代码)。

    在尝试了使用ng-token-auth 和为我的用户进行标准设计身份验证的不同迭代后,我得出的结论是,最好先使用设计授权用户,然后以某种方式使用ng-token-auth 设置令牌;所以我开始研究ng-token-auth 通过登录收到令牌时实际做了什么。原来它设置了两个cookie:

    当前配置名称 |默认 | | / | 有效期

    auth_headers | url 编码的令牌数据 | | / | 有效期

    现在的问题是如何将新生成的令牌传递给前端;这让我们变得比我想象的要简单。由于在 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-authcreate_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,因为当用户登录到我的站点时,他们可能会被重定向到两个页面之一,具体取决于他们的凭据。这样可以确保无论发送到哪个页面,都会生成代码令牌并插入代码块。
    • 我知道可能有更好的方法来处理 cookie 的生成,而不是创建一个空的 div 并为其分配一个控制器。我愿意接受更优雅的解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-27
      • 1970-01-01
      • 2018-05-01
      相关资源
      最近更新 更多