improve cookie based session with decorator pattern
play

Improve Cookie- based Session with Decorator Pattern @ ConFoo - PowerPoint PPT Presentation

Improve Cookie- based Session with Decorator Pattern @ ConFoo Montreal 2018-03-08 by Jian Weihang Improve Cookie-based Session with Decorator Pattern 1 Bonjour! Improve Cookie-based Session with Decorator Pattern 2 Jian Weihang


  1. Improve Cookie- based Session with Decorator Pattern @ ConFoo Montreal 2018-03-08 by Jian Weihang Improve Cookie-based Session with Decorator Pattern 1

  2. Bonjour! Improve Cookie-based Session with Decorator Pattern 2

  3. ��� Jian Weihang Improve Cookie-based Session with Decorator Pattern 3

  4. @tonytonyjan Improve Cookie-based Session with Decorator Pattern 4

  5. Taiwan Improve Cookie-based Session with Decorator Pattern 5

  6. Improve Cookie-based Session with Decorator Pattern 6

  7. Improve Cookie-based Session with Decorator Pattern 7

  8. Improve Cookie-based Session with Decorator Pattern 8

  9. $ gem install taiwan Improve Cookie-based Session with Decorator Pattern 9

  10. Tech Leader Improve Cookie-based Session with Decorator Pattern 10

  11. Ruby Developer since 2010 Improve Cookie-based Session with Decorator Pattern 11

  12. Maintainer of exif and jaro_winkler Improve Cookie-based Session with Decorator Pattern 12

  13. Published a book in 2015 Improve Cookie-based Session with Decorator Pattern 13

  14. Improve Cookie- based Session with Decorator Pattern Improve Cookie-based Session with Decorator Pattern 14

  15. Outline • Introduction of Decorator Pattern • Security of Rack::Session::Cookie • Encryption of Rack::Session::Cookie Improve Cookie-based Session with Decorator Pattern 15

  16. Decorator Pattern Improve Cookie-based Session with Decorator Pattern 16

  17. Decorator Pattern Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality. — Design Patterns by the Gang of Four Improve Cookie-based Session with Decorator Pattern 17

  18. Using Inheritance class CoffeeWithSugar < Coffee def cost super + 0.2 end end class CoffeeWithMilkAndSugar < Coffee def cost super + 0.4 + 0.2 end end Improve Cookie-based Session with Decorator Pattern 18

  19. What's the problem? • Cannot customize during runtime. • Cannot control how and when to decorate a component. • ex. double milk? • It is tightly coupled. Improve Cookie-based Session with Decorator Pattern 19

  20. What's the problem? • Cannot customize during runtime. • Cannot control how and when to decorate a component. • ex. double milk? • It is tightly coupled. Improve Cookie-based Session with Decorator Pattern 20

  21. What's the problem? • Cannot customize during runtime. • Cannot control how and when to decorate a component. • ex. double milk? • It is tightly coupled. Improve Cookie-based Session with Decorator Pattern 21

  22. Decorator Pattern in Ruby class Milk def initialize(coffee); @coffee = coffee end def cost; @coffee.cost + 0.4 end end class Sugar def initialize(coffee); @coffee = coffee end def cost; @coffee.cost + 0.2 end end coffee = Coffee.new # coffee.cost = 2.0 Sugar.new(Milk.new(coffee)).cost # 2.6 Sugar.new(Sugar.new(coffee)).cost # 2.4 Improve Cookie-based Session with Decorator Pattern 22

  23. Benefits • Plain Old Ruby Object. • Can be wrapped infinitely. • Can use same decorator more than once on component. • Can customize in runtime. Improve Cookie-based Session with Decorator Pattern 23

  24. Benefits • Plain Old Ruby Object. • Can be wrapped infinitely. • Can use same decorator more than once on component. • Can customize in runtime. Improve Cookie-based Session with Decorator Pattern 24

  25. Benefits • Plain Old Ruby Object. • Can be wrapped infinitely. • Can use same decorator more than once on component. • Can customize in runtime. Improve Cookie-based Session with Decorator Pattern 25

  26. Benefits • Plain Old Ruby Object. • Can be wrapped infinitely. • Can use same decorator more than once on component. • Can customize in runtime. Improve Cookie-based Session with Decorator Pattern 26

  27. class Additive def initialize(coffee) @coffee = coffee end def cost raise NotImplementedError end end class Salt < Additive def cost @coffee.cost + 0.1 end end Improve Cookie-based Session with Decorator Pattern 27

  28. Rack Improve Cookie-based Session with Decorator Pattern 28

  29. Is Rack::Session::Cookie secure? Improve Cookie-based Session with Decorator Pattern 29

  30. Simple HTTP Server require 'rack' app = lambda do |env| session = env['rack.session'] session[:name] = 'tonytonyjan' session[:age] = 28 [200, {}, ['it works']] end app = Rack::Builder.app(app) do use Rack::Session::Cookie, secret: 'secret' end Rack::Handler::WEBrick.run app, Port: ARGV[0] Improve Cookie-based Session with Decorator Pattern 30

  31. Experiment Improve Cookie-based Session with Decorator Pattern 31

  32. Decode Marshal.load( Base64.decode64( URI.decode_www_form_component(cookie) .split('--') .first ) ) Improve Cookie-based Session with Decorator Pattern 32

  33. Structure of Rack Cookie Session +------------- uri encode --------------+ | +------ base64 ------+ +- hex -+ | | | +- Marshal.dump -+ | | | | | | | object | | "--" | mac | | | | +----------------+ | | | | | +--------------------+ +-------+ | +---------------------------------------+ Improve Cookie-based Session with Decorator Pattern 33

  34. Decode and Verify def decode_cookie(cookie, secret) cookie = URI.decode_www_form_component(cookie) data, hmac = cookie.split('--') computed_hmac = OpenSSL::HMAC.hexdigest( OpenSSL::Digest::SHA1.new, secret, data ) raise 'invalid hmac' unless computed_hmac == hmac Marshal.load(Base64.decode64(data)) end Improve Cookie-based Session with Decorator Pattern 34

  35. Is Rack::Session::Cookie secure? Improve Cookie-based Session with Decorator Pattern 35

  36. Not Exactly Improve Cookie-based Session with Decorator Pattern 36

  37. Rack::Session::Cookie • Sign with HMAC-SHA1. • No encryption. Improve Cookie-based Session with Decorator Pattern 37

  38. Rack::Session::Cookie • Sign with HMAC-SHA1. • No encryption. Improve Cookie-based Session with Decorator Pattern 38

  39. Rack::Session::Cookie • Sign with HMAC-SHA1. • No encryption. Improve Cookie-based Session with Decorator Pattern 39

  40. Sinatra Improve Cookie-based Session with Decorator Pattern 40

  41. Sinatra Official Document Improve Cookie-based Session with Decorator Pattern 41

  42. require 'sinatra' set :sessions, true set :session_secret, 'set secret' get '/' do session = env['rack.session'] session[:name] = 'tonytonyjan' session[:age] = 28 'Hello world!' end Improve Cookie-based Session with Decorator Pattern 42

  43. Experiment Improve Cookie-based Session with Decorator Pattern 43

  44. Improve Cookie-based Session with Decorator Pattern 44

  45. Improve Cookie-based Session with Decorator Pattern 45

  46. Rails Improve Cookie-based Session with Decorator Pattern 46

  47. Convention over Configuration Improve Cookie-based Session with Decorator Pattern 47

  48. Structure of Rails Cookie +-------------------- uri encode -------------------+ | +------------ base64 ------------+ +- hex -+ | | | +- base64 -+ +- base64 -+ | | | | | | | JSON | "--" | iv | | "--" | mac | | | | +----------+ +----------+ | | | | | +--------------------------------+ +-------+ | +---------------------------------------------------+ Improve Cookie-based Session with Decorator Pattern 48

  49. Decode with ActiveSupport require 'uri' require 'json' require 'active_support' def verify_and_decrypt_session_cookie(cookie, secret_key_base) cookie = URI.decode_www_form_component(cookie) salt = 'encrypted cookie' signed_salt = 'signed encrypted cookie' key_generator = ActiveSupport::KeyGenerator.new(secret_key_base, iterations: 1000) secret = key_generator.generate_key(salt)[0, ActiveSupport::MessageEncryptor.key_len] sign_secret = key_generator.generate_key(signed_salt) encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret, serializer: JSON) encryptor.decrypt_and_verify(cookie) end Pure Ruby Version: https://goo.gl/vuQPkr Improve Cookie-based Session with Decorator Pattern 49

  50. Encryption in Rack::Session::Cookie Improve Cookie-based Session with Decorator Pattern 50

  51. require 'rack' require 'action_dispatch' secret_key_base = '...secret_key_base...' key_generator = ActiveSupport::KeyGenerator.new(secret_key_base, iterations: 1000) app = lambda do |env| env['action_dispatch.secret_key_base'] = secret_key_base env['action_dispatch.cookies_serializer'] = :json env['action_dispatch.signed_cookie_salt'] = 'signed cookie' env['action_dispatch.encrypted_cookie_salt'] = 'encrypted cookie' env['action_dispatch.encrypted_signed_cookie_salt'] = 'signed encrypted cookie' env['action_dispatch.key_generator'] = key_generator session = env['rack.session'] session[:name] = 'tonytonyjan' session[:age] = 28 [200, {}, ['it works']] end app = Rack::Builder.app(app) do use ActionDispatch::Cookies use ActionDispatch::Session::CookieStore, key: '_myapp_session' end Improve Cookie-based Session with Decorator Pattern 51

  52. Cons • ActionDispatch is fat. • Stack too deep. Improve Cookie-based Session with Decorator Pattern 52

  53. Cons • ActionDispatch is fat. • Stack too deep. Improve Cookie-based Session with Decorator Pattern 53

Recommend


More recommend