fix cookie
This commit is contained in:
parent
2528857aa7
commit
91f8230e28
|
@ -34,12 +34,48 @@ class Roda
|
||||||
# Proxies the request, forwarding all headers except +Host+ which is
|
# Proxies the request, forwarding all headers except +Host+ which is
|
||||||
# rewritten to be the destination host. The response headers, body and
|
# rewritten to be the destination host. The response headers, body and
|
||||||
# status are returned to the client.
|
# status are returned to the client.
|
||||||
|
def verify_and_decrypt_session_cookie(cookie, secret_key_base)
|
||||||
|
cookie = CGI.unescape(cookie)
|
||||||
|
|
||||||
|
#################
|
||||||
|
# generate keys #
|
||||||
|
#################
|
||||||
|
encrypted_cookie_salt = 'encrypted cookie' # default: Rails.application.config.action_dispatch.encrypted_cookie_salt
|
||||||
|
encrypted_signed_cookie_salt = 'signed encrypted cookie' # default: Rails.application.config.action_dispatch.encrypted_signed_cookie_salt
|
||||||
|
iterations = 1000
|
||||||
|
key_size = 64
|
||||||
|
secret = OpenSSL::PKCS5.pbkdf2_hmac_sha1(secret_key_base, encrypted_cookie_salt, iterations, key_size)[0, OpenSSL::Cipher.new('aes-256-cbc').key_len]
|
||||||
|
sign_secret = OpenSSL::PKCS5.pbkdf2_hmac_sha1(secret_key_base, encrypted_signed_cookie_salt, iterations, key_size)
|
||||||
|
|
||||||
|
##########
|
||||||
|
# Verify #
|
||||||
|
##########
|
||||||
|
data, digest = cookie.split('--')
|
||||||
|
raise 'invalid message' unless digest == OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA1.new, sign_secret, data)
|
||||||
|
# you better use secure compare instead of `==` to prevent time based attact,
|
||||||
|
# ref: ActiveSupport::SecurityUtils.secure_compare
|
||||||
|
|
||||||
|
###########
|
||||||
|
# Decrypt #
|
||||||
|
###########
|
||||||
|
encrypted_message = Base64.strict_decode64(data)
|
||||||
|
encrypted_data, iv = encrypted_message.split('--').map{|v| Base64.strict_decode64(v) }
|
||||||
|
cipher = OpenSSL::Cipher.new('aes-256-cbc')
|
||||||
|
cipher.decrypt
|
||||||
|
cipher.key = secret
|
||||||
|
cipher.iv = iv
|
||||||
|
decrypted_data = cipher.update(encrypted_data)
|
||||||
|
decrypted_data << cipher.final
|
||||||
|
|
||||||
|
Marshal.load(decrypted_data)
|
||||||
|
end
|
||||||
def proxy
|
def proxy
|
||||||
client = NetX::HTTPUnix.new(_sock_url)
|
client = NetX::HTTPUnix.new(_sock_url)
|
||||||
request_class = Net::HTTP.const_get(:"#{env['REQUEST_METHOD'].to_s.downcase.capitalize}")
|
request_class = Net::HTTP.const_get(:"#{env['REQUEST_METHOD'].to_s.downcase.capitalize}")
|
||||||
req = request_class.new(_proxy_url.to_s, _proxy_headers)
|
req = request_class.new(_proxy_url.to_s, _proxy_headers)
|
||||||
env_body = env["rack.input"].read
|
env_body = env["rack.input"].read
|
||||||
env_content_type = env['CONTENT_TYPE']
|
env_content_type = env['CONTENT_TYPE']
|
||||||
|
secret_key_base = YAML.load(File.read(File.expand_path("../../../../config/secrets.yml",__FILE__)))['production']['secret_key_base']
|
||||||
unless env_body.nil?
|
unless env_body.nil?
|
||||||
req.body = env_body
|
req.body = env_body
|
||||||
end
|
end
|
||||||
|
@ -48,6 +84,21 @@ class Roda
|
||||||
end
|
end
|
||||||
f_response = client.request(req)
|
f_response = client.request(req)
|
||||||
f_response.content_length = nil #prevent duplicate header Content-Length and content-length
|
f_response.content_length = nil #prevent duplicate header Content-Length and content-length
|
||||||
|
# if env['REQUEST_METHOD'].to_s.downcase == 'post'
|
||||||
|
# cookie = f_response['set-cookie'].to_s.split(/[;,]\s?/).map do |s|
|
||||||
|
# k,v = s.split('=', 2)
|
||||||
|
# [k, v.to_s]
|
||||||
|
# end.to_h
|
||||||
|
# puts ["cookie", cookie]
|
||||||
|
# if cookie['_orbit_store_session']
|
||||||
|
# secret_key_base = YAML.load(File.read(File.expand_path("../../../../config/secrets.yml",__FILE__)))['production']['secret_key_base']
|
||||||
|
# puts verify_and_decrypt_session_cookie(cookie['_orbit_store_session'], secret_key_base) rescue {}
|
||||||
|
# puts "---------------------------------"
|
||||||
|
# print f_response.get_fields('set-cookie') #['set-cookie']
|
||||||
|
# puts nil
|
||||||
|
# puts "================================="
|
||||||
|
# end
|
||||||
|
# end
|
||||||
_respond(f_response)
|
_respond(f_response)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -104,9 +155,20 @@ class Roda
|
||||||
def _respond(proxied_response)
|
def _respond(proxied_response)
|
||||||
response.status = proxied_response.code.to_i
|
response.status = proxied_response.code.to_i
|
||||||
proxied_response
|
proxied_response
|
||||||
.each_header.to_h
|
.to_hash
|
||||||
.reject { |k, v| k.downcase == 'transfer-encoding' }
|
.reject { |k, v| k.downcase == 'transfer-encoding' }
|
||||||
.each { |k, v| response[k] = v }
|
.each { |k, v| response[k] = v.join("\n") }
|
||||||
|
# cookie = proxied_response['set-cookie'].to_s.split('; ').map{|s| k,v = s.split('='); [k, v.to_s]}.to_h
|
||||||
|
# if cookie['_orbit_store_session']
|
||||||
|
# secret_key_base = YAML.load(File.read(File.expand_path("../../../../config/secrets.yml",__FILE__)))['production']['secret_key_base']
|
||||||
|
# puts verify_and_decrypt_session_cookie(cookie['_orbit_store_session'], secret_key_base) rescue {}
|
||||||
|
# end
|
||||||
|
# puts proxied_response
|
||||||
|
# .each_header.to_h
|
||||||
|
# proxied_response['set-cookie'].split('; ').map do |s|
|
||||||
|
# k,v = s.split('=')
|
||||||
|
# response.set_cookie(k,v)
|
||||||
|
# end
|
||||||
response.write(proxied_response.body)
|
response.write(proxied_response.body)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
# Be sure to restart your server when you modify this file.
|
||||||
|
require 'rack/utils'
|
||||||
|
module Rack
|
||||||
|
module Utils
|
||||||
|
def self.set_cookie_header!(header, key, value)
|
||||||
|
case value
|
||||||
|
when Hash
|
||||||
|
domain = "; domain=" + value[:domain] if value[:domain]
|
||||||
|
path = "; path=" + value[:path] if value[:path]
|
||||||
|
max_age = "; max-age=" + value[:max_age] if value[:max_age]
|
||||||
|
expires = "; expires=" +
|
||||||
|
rfc2822(value[:expires].clone.gmtime) if value[:expires]
|
||||||
|
secure = "; secure" if value[:secure]
|
||||||
|
httponly = "; HttpOnly" if value[:httponly]
|
||||||
|
same_site =
|
||||||
|
case value[:same_site]
|
||||||
|
when false, nil
|
||||||
|
nil
|
||||||
|
when :none, 'None', :None
|
||||||
|
'; SameSite=None'
|
||||||
|
when :lax, 'Lax', :Lax
|
||||||
|
'; SameSite=Lax'
|
||||||
|
when true, :strict, 'Strict', :Strict
|
||||||
|
'; SameSite=Strict'
|
||||||
|
else
|
||||||
|
raise ArgumentError, "Invalid SameSite value: #{value[:same_site].inspect}"
|
||||||
|
end
|
||||||
|
value = value[:value]
|
||||||
|
end
|
||||||
|
value = [value] unless Array === value
|
||||||
|
cookie = escape(key) + "=" +
|
||||||
|
value.map { |v| escape v }.join("&") +
|
||||||
|
"#{domain}#{path}#{max_age}#{expires}#{secure}#{httponly}#{same_site}"
|
||||||
|
|
||||||
|
case header["Set-Cookie"]
|
||||||
|
when nil, ''
|
||||||
|
header["Set-Cookie"] = cookie
|
||||||
|
when String
|
||||||
|
header["Set-Cookie"] = [header["Set-Cookie"], cookie].join("\n")
|
||||||
|
when Array
|
||||||
|
header["Set-Cookie"] = (header["Set-Cookie"] + [cookie]).join("\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
#Orbit::Application.config.session_store :cookie_store, key: '_orbit_store_session', expire_after: 1.week, same_site: :lax, path: "/", httponly: true
|
||||||
|
Orbit::Application.config.session_store :cookie_store, key: '_orbit_store_session', same_site: :lax, path: "/", httponly: true
|
Loading…
Reference in New Issue