簡體   English   中英

如何將 devise_token_auth 與 ActionCable 一起用於對用戶進行身份驗證?

[英]How To use devise_token_auth with ActionCable for authenticating user?

我有一個帶有devise_token_auth gem身份驗證的 Rails 5 API。

現在我想為經過身份驗證的用戶進行個人聊天。 我沒有資產,因為我正在使用 API 並且前端在本機應用程序中,我想要本機應用程序消息傳遞。

那么我如何使用 devise_token_auth gem 對用戶進行身份驗證以使用操作電纜進行個人消息傳遞

這里使用ng-token-auth在cookie中設置的auth_headers用於確定請求是否經過身份驗證,如果不是,則拒絕連接。

module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user

    def connect
      self.current_user = find_verified_user
    end

    protected

      def find_verified_user # this checks whether a user is authenticated with devise_token_auth
        # parse cookies for values necessary for authentication
        auth_headers = JSON.parse(cookies['auth_headers'])

        uid_name          = DeviseTokenAuth.headers_names[:'uid']
        access_token_name = DeviseTokenAuth.headers_names[:'access-token']
        client_name       = DeviseTokenAuth.headers_names[:'client']

        uid        = auth_headers[uid_name]
        token      = auth_headers[access_token_name]
        client_id  = auth_headers[client_name]

        user = User.find_by_uid(uid)

        if user && user.valid_token?(token, client_id)
          user
        else
          reject_unauthorized_connection
        end
      end
  end
end

Rails 5 API通常不支持cookie。 請參閱: http//guides.rubyonrails.org/api_app.html#creating-a-new-application

如果您在站點的某個位置(使用devise_token_auth gem)執行常見的HTTP身份驗證,那么您將獲得3個auth標頭 - access_tokenclientuid

在這種情況下,您可以使用這3個auth標頭為您的Websockets連接使用Basic身份驗證(根據https://devcenter.heroku.com/articles/websocket-security#authentication-authorization ):

致電(我使用Chrome Simple WebSocket客戶端 ):

ws://localhost:3000/cable/?access-token=ZigtvvcKK7B7rsF_20bGHg&client=TccPxBrirWOO9k5fK4l_NA&uid=client1@example.com

然后處理:

# Be sure to restart your server when you modify this file. Action Cable runs in an EventMachine loop that does not support auto reloading.
module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user

    def connect

        params = request.query_parameters()

        access_token = params["access-token"]
        uid = params["uid"]
        client = params["client"]

        self.current_user = find_verified_user access_token, uid, client
        logger.add_tags 'ActionCable', current_user.email
    end


    protected

        def find_verified_user token, uid, client_id # this checks whether a user is authenticated with devise

            user = User.find_by email: uid
# http://www.rubydoc.info/gems/devise_token_auth/0.1.38/DeviseTokenAuth%2FConcerns%2FUser:valid_token%3F
            if user && user.valid_token?(token, client_id)
                user
            else
                reject_unauthorized_connection
            end
        end   
  end
end

這類似於常見的Websockets auth https://rubytutorial.io/actioncable-devise-authentication/

這種認證可能就足夠了。 我認為沒有必要在頻道訂閱和發送到服務器的每個Websocket消息上進行身份驗證:

http://guides.rubyonrails.org/action_cable_overview.html#server-side-components-connections

對於服務器接受的每個WebSocket,都會實例化一個連接對象。 此對象成為從那里創建的所有通道訂閱的父對象。 連接本身不處理除身份驗證和授權之外的任何特定應用程序邏輯。

因此,如果您的連接是FooChannel < ApplicationCable::Channel identified_by :current_user ,您可以稍后在FooChannel < ApplicationCable::Channel任何位置訪問current_user 例:

class AppearanceChannel < ApplicationCable::Channel
  def subscribed

    stream_from "appearance_channel"

    if current_user

      ActionCable.server.broadcast "appearance_channel", { user: current_user.id, online: :on }

      current_user.online = true

      current_user.save!

    end


  end

  def unsubscribed

    if current_user

      # Any cleanup needed when channel is unsubscribed
      ActionCable.server.broadcast "appearance_channel", { user: current_user.id, online: :off }

      current_user.online = false

      current_user.save!      

    end


  end 

end

PS我想在Rails 5 API中使用cookies,你可以打開它:

http://guides.rubyonrails.org/api_app.html#other-middleware

配置/ application.rb中

config.middleware.use ActionDispatch::Cookies

http://guides.rubyonrails.org/api_app.html#adding-other-modules

控制器/ API / application_controller.rb

class Api::ApplicationController < ActionController::API

    include ActionController::Cookies
...

我這樣做是因為我們的 React Native 應用程序在標頭中發送身份驗證:

module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user

    def connect
      self.current_user = find_verified_user
    end

    protected

      def find_verified_user
        access_token = request.headers['access-token']
        uid          = request.headers['uid']
        client       = request.headers['client']

        user = User.find_by_uid(uid)

        if user && user.valid_token?(access_token, client)
          logger.add_tags 'ActionCable', uid

          user
        else
          reject_unauthorized_connection
        end
      end
  end
end

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM