복붙노트

[RUBY-ON-RAILS] 한 번에 사용자 당 고안 제한 한 세션

RUBY-ON-RAILS

한 번에 사용자 당 고안 제한 한 세션

내 애플 레일 3.0.4과 고안 1.1.7을 사용하고 있습니다.

앱에서 가입 기반 서비스이기 때문에 나는 공유 계정의 사용자를 방지 할 수있는 방법을 찾고 있어요. 일주일 이상을 찾고 있었고, 난 여전히 솔루션을 구현하는 방법을 모르겠어요. 나는 누군가가 솔루션을 구현하고 올바른 방향으로 날 지점 수 바라고 있어요.

솔루션 (답변과 통찰력 당신에게 모두 감사합니다!)

애플리케이션 controller.rb에서

before_filter :check_concurrent_session

def check_concurrent_session
  if is_already_logged_in?
    sign_out_and_redirect(current_user)
  end
end

def is_already_logged_in?
  current_user && !(session[:token] == current_user.login_token)
end

session_controller에서 고안 세션 컨트롤러를 오버라이드 (override) :

skip_before_filter :check_concurrent_session

def create
  super
  set_login_token
end

private
def set_login_token
  token = Devise.friendly_token
  session[:token] = token
  current_user.login_token = token
  current_user.save
end

마이그레이션 AddLoginTokenToUsers에서

def self.up
  change_table "users" do |t|
    t.string "login_token"
  end
end

def self.down
  change_table "users" do |t|
    t.remove "login_token"
  end
end

해결법

  1. ==============================

    1.당신은 그것을 할 수 없습니다.

    당신은 그것을 할 수 없습니다.

    그러나이 중 어느 것도 단 한 명의 사용자 만이 로그인을 사용하도록 보장하지 않으며, 것입니다 세계 각지 사람들 (105) IP 프록시 또는 무엇이든을 사용하는 경우에만 하나의 고유 한 사용자에 속하지 않는 것을.

    그리고 마지막 : 당신은 인터넷이 필요하지 않습니다.

    UPD

    일부 토큰을 저장할 수 있도록, 그 일부 암호화 된 데이터가 포함됩니다 : IP + 비밀 문자열 + 사용자 에이전트 + 사용자의 브라우저 버전 + 사용자 OS + 기타 개인 정보를 : 암호화 (IP + "어떤 비밀 문자열"+ request.user_agent +를 ... .). 그리고 당신은 그 토큰 세션 또는 쿠키를 설정할 수 있습니다. 그리고 각 요청에 당신은 그것을 가져올 수 : 사용자가 동일한 경우? 그는 같은 브라우저와 같은 OS 등에서 같은 브라우저 버전을 사용하고 있습니다

    또한 동적 토큰을 사용할 수 있습니다 : 각 요청 토큰이 변경됩니다 때문에, 그래서 단 한 사용자가 세션 당 시스템을 사용할 수, 각 요청 토큰 변경, 다른 사용자는 지금까지 자신의 토큰이 만료됩니다으로 로그 아웃됩니다.

  2. ==============================

    2.이 보석은 잘 작동 : https://github.com/devise-security/devise-security

    이 보석은 잘 작동 : https://github.com/devise-security/devise-security

    Gemfile에 추가

    gem 'devise-security'
    

    번들 후 설치

    rails generate devise_security:install
    

    그런 다음 실행

    rails g migration AddSessionLimitableToUsers unique_session_id
    

    마이그레이션 파일을 편집

    class AddSessionLimitableToUsers < ActiveRecord::Migration
      def change
        add_column :users, :unique_session_id, :string, limit: 20
      end
    end
    

    그런 다음 실행

    rake db:migrate
    

    편집 앱이 / 모델 / user.rb 파일

    class User < ActiveRecord::Base
      devise :session_limitable # other devise options
      ... rest of file ...
    end
    

    끝난. 이제 다른 브라우저에서 로그인하면 이전 세션을 죽일 것이다. 보석 실제 통지 그는에 로그인하기 전에 현재의 세션을 죽이려는 것을 사용자.

  3. ==============================

    3.이것은 내가 중복 세션 문제를 해결하는 방법입니다.

    이것은 내가 중복 세션 문제를 해결하는 방법입니다.

    routes.rb

      devise_for :users, :controllers => { :sessions => "my_sessions" }
    

    my_sessions 컨트롤러

    class MySessionsController < Devise::SessionsController
      skip_before_filter :check_concurrent_session
    
      def create
        super
        set_login_token
      end
    
      private
      def set_login_token
        token = Devise.friendly_token
        session[:token] = token
        current_user.login_token = token
        current_user.save(validate: false)
      end
    end
    

    application_controller

      def check_concurrent_session
        if duplicate_session?
          sign_out_and_redirect(current_user)
          flash[:notice] = "Duplicate Login Detected"
        end
      end
    
      def duplicate_session?
        user_signed_in? && (current_user.login_token != session[:token])
      end
    

    사용자 모델 마이그레이션 이름 login_token를 통해 문자열 필드 추가

    이뿐만 아니라 그것을에서 기본 고안 세션 컨트롤러하지만 상속을 재정의합니다. 새 세션에 로그인 세션 토큰이 생성되고 사용자 모델에 login_token에 저장됩니다. 응용 프로그램 컨트롤러에서 우리는 밖으로 어떤 징후 check_concurrent_session를 호출하고 duplicate_session를 호출 한 후 CURRENT_USER를 리디렉션? 함수.

    그것은 그것에 대해 이동하는 가장 깨끗한 방법은 아니지만, 확실히 작동합니다.

  4. ==============================

    4.멀리 실제로 고안에 구현으로, 당신의 User.rb 모델이 추가합니다. 이런 식으로 뭔가가 자동으로 (검증되지 않은)을 로그 아웃합니다.

    멀리 실제로 고안에 구현으로, 당신의 User.rb 모델이 추가합니다. 이런 식으로 뭔가가 자동으로 (검증되지 않은)을 로그 아웃합니다.

      def token_valid?
         # Use fl00rs method of setting the token
         session[:token] == cookies[:token]
      end
    
      ## Monkey Patch Devise methods ##
      def active_for_authentication? 
        super && token_valid?
      end 
      def inactive_message 
       token_valid? ? super : "You are sharing your account." 
      end 
    
  5. ==============================

    5.나는 원래 게시물의 솔루션은 매우 나를 위해 작동하지 않은 것을 발견했다. 나는 첫 번째 사용자가 로그 아웃하고 로그 - 인 페이지되게 싶었다. 또한, sign_out_and_redirect (CURRENT_USER) 방법은 내가 예상대로 작동하지 않는 것 같습니다. 다음과 같이 해당 솔루션에 SessionsController 재정의를 사용하여 내가 사용 WebSocket을에 수정 :

    나는 원래 게시물의 솔루션은 매우 나를 위해 작동하지 않은 것을 발견했다. 나는 첫 번째 사용자가 로그 아웃하고 로그 - 인 페이지되게 싶었다. 또한, sign_out_and_redirect (CURRENT_USER) 방법은 내가 예상대로 작동하지 않는 것 같습니다. 다음과 같이 해당 솔루션에 SessionsController 재정의를 사용하여 내가 사용 WebSocket을에 수정 :

    def create
      super
      force_logout
    end
    
    private
    def force_logout
        logout_subscribe_address = "signout_subscribe_response_#{current_user[:id]}"
        logout_subscribe_resp = {:message => "#{logout_subscribe_address }: #{current_user[:email]} signed out."}
        WebsocketRails[:signout_subscribe].trigger(signout_subscribe_address, signout_subscribe_resp)
      end
    end
    

    모든 웹 페이지가 signout 채널에 가입했는지 확인과 같은 logout_subscribe_address 액션에 바인드. 내 응용 프로그램에서 각 페이지에는 유증 세션을 통해 클라이언트 밖으로 징후 조치를 파괴는 '로그 아웃'버튼을 가지고 있습니다. 웹 소켓 응답이 웹 페이지에서 트리거되면, 단순히이 버튼을 클릭 - signout 논리가 호출되고 첫 번째 사용자는 로그인 페이지로 표시됩니다.

    이 편견없이 강제 로그 아웃을 유발하기 때문에 login_token check_concurrent_session 및 모델 :이 솔루션은 또한 skip_before_filter을 필요로하지 않습니다.

    기록의 경우, devise_security_extension뿐만 아니라이 작업을 수행 할 수있는 기능을 제공하기 위해 나타납니다. 또한 (나는 아직 그 작업을 수행하는 방법을 알아 냈하지 않은 경우) 무슨 일이 일어 났는지에 대한 첫 번째 사용자에게 경고 적절한 경고를 넣습니다.

  6. ==============================

    6.사용자 당 사용 UNIQ IP를 추적 할 수 있습니다. 이제 다음, 그 IP가에 대한 분석을 실행 - 하나의 계정이 다른 나라에서 다른 ISP들에서 동시 로그인이있는 경우 공유는 분명하다. 공격이 적중 할 때마다 반드시 다른 IP 것 때문에 일부 ISP는 라운드 로빈 프록시를 사용 - 단순히 다른 IP를 가진 참고가 공유 고려하기에 충분한 근거가 없습니다.

    사용자 당 사용 UNIQ IP를 추적 할 수 있습니다. 이제 다음, 그 IP가에 대한 분석을 실행 - 하나의 계정이 다른 나라에서 다른 ISP들에서 동시 로그인이있는 경우 공유는 분명하다. 공격이 적중 할 때마다 반드시 다른 IP 것 때문에 일부 ISP는 라운드 로빈 프록시를 사용 - 단순히 다른 IP를 가진 참고가 공유 고려하기에 충분한 근거가 없습니다.

  7. ==============================

    7.당신이 안정적으로 계정을 공유하지 못하도록 할 수는 없지만, 당신이 (내 생각) 할 수있는 것은 하나 개의 사용자 존재가 동일한 계정에 동시에 로그온보다 더 방지 할 수 있습니다. 확실하지이 비즈니스 모델에 충분하지만 다른 답변에서 논의 된 많은 문제를 돌아 다니기 않는 경우. 몇 가지 메모가 여기에있다 - 나는 현재 베타 버전이며, 합리적으로 잘 작동하는 것 같다 뭔가를 구현했습니다

    당신이 안정적으로 계정을 공유하지 못하도록 할 수는 없지만, 당신이 (내 생각) 할 수있는 것은 하나 개의 사용자 존재가 동일한 계정에 동시에 로그온보다 더 방지 할 수 있습니다. 확실하지이 비즈니스 모델에 충분하지만 다른 답변에서 논의 된 많은 문제를 돌아 다니기 않는 경우. 몇 가지 메모가 여기에있다 - 나는 현재 베타 버전이며, 합리적으로 잘 작동하는 것 같다 뭔가를 구현했습니다

  8. from https://stackoverflow.com/questions/7068919/devise-limit-one-session-per-user-at-a-time by cc-by-sa and MIT license