`
peryt
  • 浏览: 55710 次
  • 来自: ...
最近访客 更多访客>>
社区版块
存档分类
最新评论
  • waiting: 既然都指定了dataType为'script'那就不必特别在b ...
    jQuery

9.3 sign in success.

 
阅读更多

1. we will first finish the create action:

 

def create
    user = User.authenticate(params[:session][:email],
                             params[:session][:password])
    if user.nil?
      flash.now[:error] = "Invalid email/password combination."
      @title = "Sign in"
      render 'new'
    else
      sign_in user
      redirect_to user
    end
  end

 

for the below, we will write sign_in method!!!

 

2. start from TDD again!!!

 

describe SessionsController do
  .
  .
  .
  describe "POST 'create'" do
    .
    .
    .
    describe "with valid email and password" do

      before(:each) do
        @user = Factory(:user)
        @attr = { :email => @user.email, :password => @user.password }
      end

      it "should sign the user in" do
        post :create, :session => @attr
        # Fill in with tests for a signed-in user.
      end

      it "should redirect to the user show page" do
        post :create, :session => @attr
        response.should redirect_to(user_path(@user))
      end
    end
  end
end

 

3. in this section, we will need some methods that are need to in both controller and view, 

for view, we can define the method in SessionHelpr, (the method in all helpers are viewable for all views.)

to make controller see this method, we just need to include this module into the controller.

 

class ApplicationController < ActionController::Base
  protect_from_forgery
  include SessionsHelper
end

 

4. session and cookies:

 

 

Because HTTP is a stateless protocol, web applications requiring user signin must implement a way to track each user’s progress from page to page. One technique for maintaining the user signin status is to use a traditional Rails session (via the special session function) to store a remember token equal to the user’s id:

  session[:remember_token] = user.id 
This session object makes the user id available from page to page by storing it in a cookie that expires upon browser close. On each page, the application can simply call
  User.find_by_id(session[:remember_token])
  to retrieve the user. Because of the way Rails handles sessions, this process is secure; if a malicious user tries to spoof the user id, Rails will detect a mismatch based on a special session id generated for each session.

but if we want a permanant token, so that it still work after browser close, then just include user id in the session[:remember_token] is not secure enough, hacker can use user.id to do bad, so we can include user.salt
[user.id, user.salt]
also, a permanant token has another security hole, hacker can get it by inspecting the user browser cookie.
the solution is when user change his password, we change the cookie.

4. now we are ready to implement the sign_in function:

a. we will put place a remember_token as a cookie on the user's browser.
b. app will use this token to find the user record from database when user move from page to page.
c. session will have a current_user.

module SessionHelper
    def sign_in(user)
        cookies.permanent.signed[:remember_token] = [user.id, user.salt]
        self.current_user = user
    end
end
 this part of code revealed the cookies utility supplied by rails.
we can use cookies as if it were a hash.
each element in the cookie is itself a hash of two elements, a value and an optional expired data.

for example:
cookies[:remember_token] = {:value => user.id, :expires => 20.years.from_now.utc}

then we can retrieve the user in this way:
User.find_by_id(cookies[:remember_token])
of course, cookies is not a real hash, since assigning to cookies actually saves a piece of text on the browser, but the beauty of rails is let you forget about the detail, and concentrate on writing the app. 

since just using user.id is not secure, before rails 3, rails use a secure token associated with the user model.
since this is so commen, rails 3 now implements it for us using:
cookies.permanent.signed[:remember_token] = [user.id, user.salt]
 using permanent, cause rails to set the expiration to 20.years.from_now.
and signed makes the cookie secure, so that the user's id is never exposed in the browser.


5. since ruby class is open, rails add many handy method to ruby classes:

1. year.from_now
10.weeks.ago

1. kilobyte ===> 1024
5.megabytes  ====> 5242880
These two are useful when validate the file size of uploads, like images.


6. current user.

now we will look at how to get and set session's current user.

self.current_user = user
since this method is shared by the controller, so the self is the controller object.

the purpose of this line is to create current user, accessible in both controllers and views.

so that we can use <%= current_user.name %> directly in views, and
redirect_to current_user
 

ok TDD first:
it "should sign the user in" do
    post :create, :session => @attr
    controller.current_user.should == @user
    controller.should be_signed_in
end
 
note, 
controller.should be_signed_in 
 is equivalent to
controller.signed_in?.should be_true 
now, we can implement 
self.current_user = user
so we need to define a function, which is an assignment.
def current_user=(user)
	@current_user = user
end
and very natrual, we need to define a get method too:
def current_user
	@current_user
end
if we did this, it is actually equivalent of using:
attr_accessor :current_user
but this is not what we want, because @current_user will disappear for next request which will generate a new controller object.

to fix this, we need to get the user from the token in the cookie in the get method.

def current_user
  @current_user ||= user_from_remember_token
end

private
  def user_from_remember_token
    User.authenticate_with_salt(*remember_token)
  end
  
  def remember_token
    cookies.signed[:remember_token] || [nil, nil]
  end

end
 
a. in this part of code, there is one totally new thing:

*remember_token

the "*" operator, allows us to use a two element array as an argument to a method expectiong two vars.

so 
def foo(bar, baz)
  bar + baz
end

foo(*[1,2])
====> 3
 the reason of using  "*" is that 

authenticate_with_salt in general should accept two arguments.
(id, user_salt)

b. another thing is:
cookies.signed[:remember_token] || [nil, nil]
 
c. the next step is to define the 

authenticate_with_salt method in user.rb

def self.authenticate_with_salt(id, cookie_salt)
	user = find_by_id(id)
	(user && user.salt == cookie_salt) ? user : nil
end
 
(user && user.salt == cookie_salt) ? user : nil

this is very traditional rails code, you really should get used to it!!! 

 

d. we still need to define the signed_in method.

 

def signed_in?

!current_user.nil?

end

分享到:
评论

相关推荐

    openssh-9.3p1-1.el7.x86-64.tar.gz

    openssh-9.3p1-1.el7.src.rpm openssh-9.3p1-1.el7.x86_64.rpm openssh-askpass-9.3p1-1.el7.x86_64.rpm openssh-askpass-gnome-9.3p1-1.el7.x86_64.rpm openssh-clients-9.3p1-1.el7.x86_64.rpm openssh-debuginfo-...

    openssh9.3p2-el7.x64 rpm安装包

    《OpenSSH 9.3p2-el7.x64 RPM 安装详解》 OpenSSH 是一个用于在不同网络之间安全地传输数据的开源软件套件。它提供了SSH(Secure SHell)协议的实现,包括客户端和服务端。在这个场景中,我们关注的是OpenSSH 9.3p2...

    openssh-9.3p2-1.x86-64.rpm

    《OpenSSH 9.3p2 RPM包在openEuler 20.03 LTS-SP2环境中的应用与安全》 OpenSSH是开源社区开发的一款用于网络服务的安全通信工具,它提供了加密的网络连接,使得远程登录和其他网络服务能够在不安全的网络环境中...

    centos7-openssh-9.3p2-1.el7.x86-64

    openssh-9.3p2-1.el7.x86_64.rpm openssh-clients-9.3p2-1.el7.x86_64.rpm openssh-debuginfo-9.3p2-1.el7.x86_64.rpm openssh-server-9.3p2-1.el7.x86_64.rpm 等四个文件,下载后移至服务器,使用: yum -y local...

    openssh 9.3p2-el7.zip

    《OpenSSH 9.3p2在Red Hat Enterprise Linux 7上的应用与配置详解》 OpenSSH,全称为Open Source Secure Shell,是基于SSH协议的开源实现,为Linux和Unix系统提供安全的远程登录和文件传输功能。OpenSSH 9.3p2是其...

    openssh-9.3p2-1.an8.x86-64.rpm

    Anolis龙蜥8.6版本 针对openssh漏洞 cve-2020-15778 cve-2023-38480 自制rpm包离线升级openssh由8.0p1到9.3p2 4个安装包之1

    scrt-x64-bsafe.9.3.0.2905.exe

    scrt-x64-bsafe.9.3.0.2905.exe

    AltiumDesignerSummer9Build9.3.1.19182Crack.rar

    AltiumDesignerSummer9Build9.3.1.19182Crack.rar

    Tina90-TI_zh.9.3.150.328安装包.zip

    《Tina90-TI_zh.9.3.150.328安装包:深入了解Tina软件的应用与安装》 Tina90-TI_zh.9.3.150.328是一款针对电子工程师设计的专业仿真软件,由Texas Instruments(TI)公司开发,旨在为用户提供一个强大的电路分析和...

    glibc-2.17-326.el7_9.3.i686.rpm

    Centos7 el7.x86_64 官方离线安装包,安装指令为 sudo rpm -ivh glibc-2.17-326.el7_9.3.i686.rpm

    openssh-9.3p2-1.el9.x86-64.tgz

    《OpenSSH 9.3p2在CentOS 9及Red Hat 9.x上的更新与安全强化》 OpenSSH(Open Source Secure Shell)是广泛应用于Linux和Unix系统中的开源安全套接字层(Secure Socket Layer,SSL)网络协议,提供加密的远程登录和...

    AltiumDesignerSummer9Build9.3.1.19182Crack

    破解AD09的压缩包仅适用于Build 9.3.1.19182 2.破解已去除标题上的Not signed in 3.局域网内用同一license不再提示冲突 4.仅供学习研究使用,勿用于非法用途。

    scrt-sfx-x64-bsafe.9.3.2.2978.exe

    scrt-sfx-x64-bsafe.9.3.2.2978.exe

    scrt-sfx-x64-bsafe.9.3.1.2929.exe

    scrt-sfx-x64-bsafe.9.3.1.2929.exe

    openssh-server-9.3p2-1.an8.x86-64.rpm

    Anolis龙蜥8.6版本 针对openssh漏洞 cve-2020-15778 cve-2023-38480 自制rpm包离线升级openssh由8.0p1到9.3p2 4个安装包之4

    EhLib_9.3_Build_9.3.011

    EhLib 9.3 Build 9.3.011 Evaluation version. -------------------------------------------- The Library contains components and classes for Borland Delphi versions 7, 9, Developer Studio 2006, Delphi ...

    openssh-9.3p2升级包(openssh、zlib、openssl)

    包含openssh升级到openssh-9.3p2的所有包,其内容如下: - openssh-9.3p2.tar.gz - openssl-1.0.2o.tar.gz - zlib-1.2.11.tar.gz 解决漏洞: - OpenSSH 安全漏洞(CVE-2023-38408) - OpenSSH远程代码执行漏洞(CVE-...

    scrt-x64-bsafe.9.3.2.2978.exe

    scrt-x64-bsafe.9.3.2.2978.exe

    openssh-9.3p2-1-el7-x86-64 RPM包

    《OpenSSH 9.3p2-1 RPM包在Linux环境中的应用与升级》 OpenSSH,全称为Open Source Secure Shell,是Linux/Unix环境中广泛使用的安全网络协议,用于实现远程登录、文件传输等任务。它提供了加密的安全连接,确保了...

    UltraISOV9.3.6.2766 免注册版

    UltraISOV9.3.6.2766 免注册版

Global site tag (gtag.js) - Google Analytics