将来を見据えたウェブ・アプリケーションの構築:The Codestのエキスパート・チームによる洞察
The Codestが、最先端技術を駆使してスケーラブルでインタラクティブなウェブアプリケーションを作成し、あらゆるプラットフォームでシームレスなユーザー体験を提供することにどのように秀でているかをご覧ください。The Codestの専門知識がどのようにデジタルトランスフォーメーションとビジネス...
For an experienced developer, this text may not be surprising at all, but I think that plenty of articles I’ve read about the CORS setup in Rails were saying something like: use rack-cors, allow any host to access the API, and (optionally): you should consider something different (than allowing any host) in production.
The proposed コード was always close to the one below:
config/initializers/cors.rb
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins ''
resource '', headers: :any, methods: :any
end
end
and, unfortunately, these texts were hardly explaining to us what to actually do in production.
I’m pretty OK with copy-pasting (I’m sometimes joking that companies could hire a Stack Overflow copy-paster), as far as there’s a “think and adjust” moment between “copy” and “paste”. So, I’d like to elaborate a little bit on what we’re doing here and how it works in real life.
I hope you don’t mind me starting with a short introduction to honor theory and then passing on to the Rails examples.
Let’s start from the beginning. To explain things better, I’ve split the introduction into three parts. The first part will outline what’s an origin – the key term for what we are discussing here. The second is about SOP, just a short description. And the last part speaks about the CORS
そのものだ。
According to the MDN Web Docs:
– Web content’s origin is defined by the scheme (protocol), host (domain), and port of the URL used to access it. Two objects have the same origin only when the scheme, host, and port all match (source)
That seems pretty clear, doesn’t it? Let’s analyze two examples from MDN, just in case.
http://example.com/app1/index.html
, http://example.com/app2/index.html
The 2 above have the same origin because:
http://www.example.com
, http://myapp.example.com
These 2 have different origin because the domains (www.example.com
, myapp.example.com
) are different.
I hope it’s clear enough. If not, please go to the MDN Web Docs for more examples.
MDN Web Docs say (source):
– The same-origin policy is a critical security mechanism that restricts how a document or script loaded from one origin can interact with a resource from another origin. It helps isolate potentially malicious documents, reducing possible attack vectors.
– Cross-origin writes are typically allowed. Examples are links, redirects, and form submissions.
– Cross-origin embedding is typically allowed.
– Cross-origin reads are typically disallowed, but read access is often leaked by embedding.
Use CORS
to allow cross-origin access
Well, as you can see, there is a lot about cross-origin behavior in the definitions of SOP. That’s ok. All we should know now is that the same origin has more privileges and we can loosen the rules for cross-origins by using CORS. And here the next section comes in.
Basing on MDN’s words:
That’s still not enough. What was not said there explicitly is that the most important header when using CORS
は Access-Control-Allow-Origin
:
Access-Control-Allow-Origin
response header indicates whether the response can be shared with requesting code from the given origin (source).Well, that should be it. In real life, when configuring CORS
, we typically configure the ACAO
header first.
That’s it when it comes to definitions. Let’s circle back to Rails and real-life examples.
We will definitely use rack-cors (like we were told to). Let’s recall the first snippet, the one that is most often provided in other articles:
config/initializers/cors.rb
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins ''
resource '', headers: :any, methods: :any
end
end
The number of options is vast or even infinite but let’s consider those two:
If you’re facing the first option, you probably could go with origins
‘*’ – you want others to build a client on the top of your API, and don’t know who they are, right?
If you are developing the latter, you probably don’t want everyone to make cross-origin requests to your API. You rather want to:
We will be still using rack-cors (like we were told to) – but our way.
Let’s use 2 ENV variables: ALLOWED_ORIGINS
for literal origin definitions (an asterisk or actual URL) and ALLOWED_ORIGIN_REGEXPS
for the patterns.
config/initializers/cors.rb
frozenstringliteral: true
toregexp = ->(string) { Regexp.new(string) }
hosts = [
*ENV.fetch('ALLOWEDORIGINS').split(','),
*ENV.fetch('ALLOWEDORIGINREGEXPS').split(';').map(&to_regexp)
]
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins(*hosts)
resource '*',
methods: %i[get post put patch delete options head],
headers: :any
end
end
This should give you enough flexibility to define proper values in your development, staging and production environments.
Let’s sum up all of the above in key points:
CORS
,That’s it. Have a nice day! 🙂
続きを読む