Yunosuke Minegishi
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Make a copy
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Engagement control Make a copy Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    ## 2021年8月23日(月)現場Rails Chapter6-7 セキュリティを強化する ### Railsの代表的なセキュリティ機能 - StrongParameters - CSRF対策 - インジェクション対策 ## Strong Prametersとは 想定通りのパラメータかどうかをホワイトリスト方式(リストにないアプリケーションやプログラムは起動しないよう制限を設け、リストにあるアプリケーションやプログラムのみを実行します。 リストに入っていないものはブロックし、一切使用しないことで危険性を回避する)でチェックする機能。 <span style="color: red; ">**※ホワイトリストはブラックリストの逆のものというイメージを持つ。**</span> ### マスアサイメント機能とは マスアサイメント機能とは、モデルからインスタンスを生成するときに、インスタンスに複数の属性を一括代入できる機能です。 ざっくり言うと、複数のキーワード引数に値を渡すこと。登録、更新を一括でできてしまう機能をマスアサイメント機能という。 つまり、登録更新処理またはインスタンス生成時(newする時)どちらでも属性を一括代入できる。 ```ruby Person.new(name: 'hoge', age: 24) person.update(name: 'hoge', age: 24) ``` DBにないカラムをnewの引数で指定すると、エラーが起こる。 以下の例の場合、Taskオブジェクトを生成する際に、nameとdescriptionという2つの属性に値を一括で代入している。 ```ruby= task = Task.new(name: 'ラーメン食べたい', description: '今すぐ食べたい') ``` ![](https://i.imgur.com/kjhfTgc.png) ### 許可される型 [Railsガイド Action Controllerの概要 4.5.1 許可済みスカラー値より](https://railsguides.jp/action_controller_overview.html#%E8%A8%B1%E5%8F%AF%E6%B8%88%E3%81%BF%E3%82%B9%E3%82%AB%E3%83%A9%E3%83%BC%E5%80%A4) `params.permit(:id)` - String - Symbol - NilClass - Numeric - TrueClass - FalseClass - Date - Time - DateTime - StringIO - IOActionDispatch::Http::UploadedFile - Rack::Test::UploadedFile 「paramsの値には許可されたスカラー値の配列を使わなければならない」=>以下のようにキーに空の配列を対応付けられる `params.permit(id: [])` ### Strong parametersの基本構文 ``` ruby #controller内定義 private def user_params params.require(:キー(モデル名)).permit(:カラム名1,:カラム名2,・・・).merge(カラム名: 入力データ) end ``` ### requireメソッド params内の特定のキーに紐付く値だけを抽出する事ができます。そのため、引数には取り出したい値のキーを指定する必要があります。requireに設定した値が見つからない場合は、例外を発生させます。 ```ruby= #キー値userに対するデータを抽出したい場合 params.require(:user).permit(・・・略・・・) ``` ### permitメソッド 許可された値のみを取得することができます。  そのため、permitメソッドの引数には登録を許可する全てのカラム名を指定しておく必要があります。もし、許可されいないカラムがparams内に存在した場合、そのデータは取得されず無視されます。 ```ruby= #Userモデルに存在するnameおよび、emailカラムのみ入力を受け付けたい場合(他のカラム(admin)は受け付けないたくない) params.require(:user).permit(:name,:email) ``` ## mergeメソッド mergeメソッドを使用することでハッシュ同士を結合することができます。 例えば、paramsに含まれない値をストロングメソッドに加えたい場合などに、ストロングパラメータの後に記述することができます。 ```ruby= #paramsのkeyとvalueに含まれていないものを追加したい場合、mergeを使う params.require(:user).permit(:name,:email).merge(user_id: current_user.id) ``` ↓チェリー本 P163 mergeの例文 ```ruby= h = { us: 'dollar', india: 'rupee'} { japan: 'yen' }.merge(h) #=> {:japan=>"yen", :us=>"dollar", :india=>"rupee"} ``` ### 一次元ハッシュと2次元ハッシュ ```ruby= #1次元ハッシュ {key1: value1, key2: value2} #2次元ハッシュ {key1: value1, key2: {key3: value3}} #一次元ハッシュの場合=>URL params.permit(:キー名) # 二次元ハッシュの場合=>モデル params.require(:モデル名).permit(:キー名) ``` requireとpermitメソッドとmergeメソッドのめっちゃわかりやすい例↓ ```ruby= #keyであるboardのvalueをハッシュの形で指定している。mergeで追加されるのは、boardのvalueの部分。 params.require(:board).permit(:body).merge(user_id: current_user.id) {"body"=>"abc", "user_id"=>5} #=>{board:{body: value1, user_id: value2}} ``` ## privateメソッド privateメソッド配下に記述したメソッドは、クラス外からのアクセスができません。 基本的にストロングパラメータは、クラス外からのアクセスをさせないようにprivateメソッド配下に書く。 ## CSRF - CSRFとは、ユーザーがログイン済みのアプリケーションに対して、悪意のあるリクエストを飛ばすこと。 - RailsにおけるCSRF対策はHTTPメソッドのGET以外を使用することで、自動的にパラメーターにセキュリティートークンを持たせることで実現している。 ### CSRF攻撃例 攻撃例: Amazon会員の太郎さん。ブラウザ操作でログアウトしていない状況で、悪意あるサイトにアクセスしました。 そこには「こちらをクリックすると懸賞にワンクリックで応募できます」の文字と、ボタンがあり、太郎さんはそのボタンをクリックしました。 しかし、そのボタンはAmazon会員を解約する`href="...../delete"`みたいなURLが仕込まれており、太郎さんは意図せずAmazon会員を解約してしまいました。 ### Ajax JavaScriptの値を明示的にRails側に渡したい場合は、jQueryでajaxメソッドを使用するのが良い。(jQuery.ajax())ただし、jQueryをrails-ujsの前に読み込んでおく必要がある。 「Rails.ajax()」関数を利用することでトークン付きのAjaxリクエストを行うことが出来る。 #### **Ajax**とは? JavaScriptでサーバー側との通信を「**非同期**」で行い、通信結果によって「動的にページの一部だけ書き換える手法のこと」です。JavaScript以外にもXMLやDOMなど「既存の機能」を組み合わせて実現します。 例)twitterのいいね機能 ページ全体の更新を行うのではなく、読み込みたい部分だけの通信を行うことで、いいね部分だけ更新することができる。通信の無駄がない!対して、**同期通信**は更新をしなくて良い部分も更新してしまうので無駄が多い! ### POSTリクエスト Railsのルーティングの文脈での「DELETE」「PATCH」「PUT」なども、ここでいうPOSTリクエストに該当します。 ## 参照 Railsガイド StrobngParameters https://railsguides.jp/action_controller_overview.html#strong-parameters 【Rails】requireとpermitメソッド https://qiita.com/morikuma709/items/2dc20d922409ae7ce216 【Ruby on Rails】ストロングパラメータって何なの? https://qiita.com/ozackiee/items/f100fd51f4839b3fdca8 チェリー本p163 pikawakaさんブログ https://pikawaka.com/rails/permit Railsのセッション管理には何が最適か https://qiita.com/shota_matsukawa_ga/items/a21c5cf49a1de6c9561a 初心者目線でAjaxの説明 https://qiita.com/hisamura333/items/e3ea6ae549eb09b7efb9 Railsガイド 「Rails セキュリティガイド -クロスサイトリクエストフォージェリ (CSRF)-」 https://railsguides.jp/security.html#%E3%82%AF%E3%83%AD%E3%82%B9%E3%82%B5%E3%82%A4%E3%83%88%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%83%95%E3%82%A9%E3%83%BC%E3%82%B8%E3%82%A7%E3%83%AA-csrf Railsのセッション管理には何が最適か https://qiita.com/shota_matsukawa_ga/items/a21c5cf49a1de6c9561a ## 2021年8月24日 現場Rails Chapter6-7-3 インジェクションに注意する ## インジェクション Webアプリケーションに悪意のあるスクリプトやパラメータを入力し、それが評価される時の権限で、実行させる攻撃。ユーザーがデータを入力するところは注意が必要! - XXS(クロスサイトスクリプティング) - SOLインジェクション - rubyコードインジェクション - コマンドラインインジェクション ### XXS ユーザーに表示するコンテンツに悪意のあるスクリプト(主にJavaScript)を仕掛け、悪意のある操作を行う攻撃方法 [ブラウザ画面参考例: 実際にサンプルページで確認してみた!クロスサイトスクリプティング(XSS)の危険性!](https://eit.systems/danger-of-cross-site-scripting/) [情報漏洩の参考図: クロスサイトスクリプティングとは?仕組みと事例から考える対策](https://cybersecurity-jp.com/security-measures/18427) 例:`&`,`"`,`<`,`>` → `&amp;`,`&quot;`,`&lt;`,`&gt;` **Railsのviewファイルはデフォルトでエスケープされる。** ### エスケープとは HTML文の中では「<」「>」「&」「"」といった文字は特別な意味を持ちます。その為、HTMLタグを含む文字列をそのまま出力してしまうと違う意味になってしまいます。その為、特別の意味を持つ文字が含まれる文字列を文字列として出力されたい場合には、特別な意味を持つ文字をエスケープした上で出力する必要があります。 <span style="color: red; ">**※Railsのビューではユーザーの入力した文字列を出力する際に自動的にHTMLをエスケープする。 ※エスケープした場合が文字列で表示される。**</span> エスケープする。 ↓ htmlタグなどを特殊文字に置き換える。特殊文字に置き換えることによって、画面上にhtmlタグを文字列として出力できる(画面上にはhtmlタグが見えてるけど、そのhtmlタグは文字列として認識されている。そのhtmlに意味はない)。 エスケープしない。 ↓ htmlをダイレクトに受け取る。htmlとして受け取るので、画面上でhtmlが実行される。 ### SQLインジェクション アプリケーションが想定しないSQL文を実行させることにより、データベースシステムを不正に操作する攻撃方法。 Railsではクエリメソッドに対して、ハッシュ形式で条件指定をすることで安全に処理をしてくれる。 ```ruby users = User.where(name: params[:name]) ``` 実行したい内容がハッシュ形式で記述できない場合(クエリメソッドにSQL文を直接記述したい場合)は文字列を直接埋め込むのではなくて、**プレースホルダー**を利用する。 ```ruby users = User.where(`name = ?`, params[:name]) ``` params[:name]が`?`に代入されるイメージ。その際にエスケープ処理を行ってくれる。 ### SQL: WHERE 1 の意味 ```ruby= #SELECT * FROM table_name;と同じ意味になる #つまり、以下のWhere以降はTrueになる条件式になる。 SELECT * FROM table_name WHERE 1 SELECT * FROM table_name WHERE 1 = 1 ``` これは、 - WHERE 1 →MySQLでは整数の1はTRUEと等価である。 - WHERE 1 = 1  →(1 = 1) を評価すると当然TRUEなので WHERE 1とWHERE 1 = 1は全く同じ結果となる。 つまり、WHEREで指定する条件が必ず真であるならば、すべての行が選択されるので、WHERE を指定しない、SELECT * FROM table_name;と結果は同じになる。 ### エスケープ処理を行わず(スキップして)出力する方法 Railsでは、HTML特殊文字は自動的にエスケープされるようになりました。自動でエスケープ処理が行われのは便利なのですが、エスケープ処理を行いたくない場合もあります。<span style="color: red; ">文字列ではなく、HTMLやJSタグとしてつまりコードとして認識させたい場合に**エスケープをスキップする**処理を行う。</span> 例)エスケープされない→ htmlをダイレクトに受け取る。htmlとして受け取るので、htmlが実行される。 #### ①Stringクラスで用意されているhtml_safeメソッドを用いる方法 ただし、nil には html_safe メソッドが存在しないため、例外が起きてしまう。 ```ruby= 文字列.html_safe ``` #### ②ActionView::Helpers::OutputSafetyHelperクラスで用意されているrawメソッドを用いる方法 この方法では、nilの例外が起きない。また、raw ヘルパーを使うことで、エスケープ処理の回避が明確になるのも利点の一つ。 ```ruby= #rawメソッドを使うことで引数に指定された文字列はエスケープ処理がされずに出力される raw(文字列) ``` #### ③Slimの==を用いる方法 この方法だと、nil の例外は起きない。また、エスケープ処理の回避が明確になる。 ```ruby= #=(単一等号)はescape_htmlメソッドによるHTMLエスケープが行われます div = "<a href='https://google.com'>Google</a>" #==(二重等号)を用いて、HTMLエスケープを行いたくない場合 div == "<a href='https://google.com'>Google</a>" ``` #### まとめ Slimの==を用いる方法が一番良いとされる方法である。 ### Sanitize ある程度タグをそのまま出したいものの危険なタグは出力しないようにしたい場合に用いる。ホワイトリスト形式で制限する。ホワイトリストフィルタでは特定の値のみが許可され、それ以外の値はすべて拒否されます。 **sanitize(サニタイズ)とは** 危険なコードやデータを変換または除去して無力化する処理です。 ```ruby= sanitize(文字列 [, オプション]) ``` #### オプション :tags - 許可するHTMLタグ名 :attributes - 許可するHTML属性名 :scrubber - スクラブ指定 scrubberはより自由に許可するタグや属性をカスタマイズできる。 ## 参照 HTML特殊文字のエスケープ https://www.javadrive.jp/rails/template/index7.html 【Ruby】array.map(&:method)を理解する https://qiita.com/k-penguin-sato/items/420d7487b28b5d58cac4 SQLデータ分析入門#3『WHERE句を理解する』 https://qiita.com/piyoSakai/items/44bc21178349103e2d45 エラーの向こうへ SQL:WHERE 1 の意味 https://tech.mktime.com/entry/32 大ちゃんの駆け出し技術ブログ https://sakitadaiki.hatenablog.com/entry/2021/02/04/082402 Pikawaka 【Rails】 whereメソッドを使って欲しいデータの取得をしよう! https://pikawaka.com/rails/where クロスサイトスクリプティング https://www.tohoho-web.com/ex/xss.html rawヘルパー https://railsdoc.com/page/raw ビューについて -Rails ドキュメント-の結果をエスケープしないで出力 https://railsdoc.com/view RailsのHTMLテンプレートエンジン、Slimの基本的な記法 https://qiita.com/mom0tomo/items/999f806d083569529f81 サニタイズ https://railsdoc.com/page/sanitize html_safe、raw、「<%==」の比較 https://qiita.com/iwamot/items/74c2bd9ebd3ac6458837 おもしろwebサービス開発日記 -h以外のサニタイズ系メソッド- https://blog.willnet.in/entry/20080826/1219760222 Sanitize https://api.rubyonrails.org/classes/ActionView/Helpers/SanitizeHelper.html ## 2021年8月25日 現場Rails Chapter6-7-3 インジェクションに注意する(Rubyコードインジェクションから) ### sendとevalってなに?? **send**メソッドは、引数で渡された文字列のメソッドを呼び出して実行します。 しかし、渡される引数に危険な値が渡される可能性があるため、条件分岐させてホワイトリスト形式で特定の文字列のみ許可してあげる方が安全です。 (ホワイトリスト方式は原則許可せず、許可するリストをこちらで指定するため、ブラックリスト方式よりも原則漏れが起きづらいという特徴があります。) sendメソッドは動的なメソッド呼び出しができて便利だが、セキュリティ面を考慮し、**外部の入力に依存する値は渡さない**(特に、ユーザーからの入力をそのままsendに引き渡すと、意図せぬ範囲のデータやプライベートメソッドにまで影響が及ぶ可能性があるため)ようにします。 ```ruby= #sendメソッド #第二引数で呼び出したメソッドに与える引数を渡しています。 send("メソッド名", "引数") ``` **eval**メソッドも、第一引数で文字列を渡すことができますが、渡された文字列のコードをそのまま実行することができます。しかし、sendメソッド同様に悪意のあるコードを渡されて、プログラムを実行される恐れがあります。 ```ruby= #evalメソッド eval('rubyコード') ``` ### sendの使用例 チェリー本P420 ``` ruby= str = 'a,b,c' # str.upcaseを呼ぶのと同じ str.send('upcase') #=> "A,B,C" # str.split(',')を呼ぶのと同じ str.send('split',',') #=> ["a","b","c"] ``` ### evalの使用例 チェリー本P420 ``` ruby= # 文字列としてRubyのコードを記述する code = '[1,2,3].map { |in| n * 10 }' #evalメソッドに渡すと、文字列がRubyのコードとして実行される eval(code) #=> [10,20,30] ``` eval攻撃例(予想) `eval(params[:hoge])` 上記のparams[:hoge]に、「データベースのUsersテーブルにあるメールアドレスを1行ずつfuga変数に配列として代入し、その後fuga変数を外部(悪意を持った者のメールアドレスetc)に送信する」みたいな記述を渡してしまうと、それが実行されてしまう危険性がある。 ```ruby= # ユーザー全件削除 params[:hoge] = User.destroy_all eval(params[:hoge]) ``` 大事なことは、**ユーザーから渡された生の値をそのまま使わない**ことです。 sendメソッドやevalメソッドを使う場合、ストロングパラメータのような、**ユーザーから渡された値を評価する仕組み**を作る必要があると思われます。 ### コマンドラインインジェクション コントローラーにコマンドライン(例: mkdir hogefuga)などを組み込んだ際に注意する必要があります。 `@group = mkdir #{params[:input]}` (←使用イメージ) (params[:input]で送られた値のファイルを作成及びそれを@groupに代入) バッククォートで囲まれた文字列はコマンドとして出力されます。 ```ruby= `date` %x{ date } ``` > バッククォートで囲まれた文字列は、ダブルクォートで囲まれた文字列と同様にバックスラッシュ記法 の解釈と式展開 が行なわれた後、コマンドとして実行され、その標準出力が文字列として与えられます。コマンドは評価されるたびに実行されます。コマンドの終了ステータスを得るには、$? を参照します。 %記法 による別形式のコマンド出力もあります。 ![](https://i.imgur.com/kCPmTf2.png) **考え方はストロングパラメータの時と同じで良いと思います。生の値をそのまま使うのはご法度です。** ### Content Security Policy(CSP) HTTPリクエスト⇔HTTPレスポンスのやり取りの中で、約束事をホワイトリスト形式でブラウザに伝えるイメージです。 > クロスサイトスクリプティング (XSS) やデータインジェクション攻撃などのような、特定の種類の攻撃を検知し、影響を軽減するために追加できるセキュリティレイヤーです。CSP を有効にするには、ウェブサーバーから Content-Security-Policy HTTP ヘッダーを返すように設定する必要があります。 CSPの適用前に通信のコネクション自体確立していて、データ送受信(HTTPリクエストを送信する)段階で、ヘッダーにContent-Security-Policyを組み込むことにより攻撃の軽減(想定しないユーザーのパケット傍受などを防ぐ)を目指しています。 #### CSPを適用すると、、、 > CSP の第一の目的は XSS 攻撃の軽減と報告です。 XSS 攻撃とは、サーバーから取得したコンテンツをブラウザーが信頼する性質を悪用した攻撃です。サーバー管理者が CSP を利用する場合、実行を許可するスクリプトの正しいドメインをブラウザーに向けて指定することにより、 XSS の発生する箇所を削減・根絶することができます。 CSP をサポートするブラウザーは、サーバーから指定された許可リストに載っているドメインのスクリプトのみ実行し、他のスクリプトはすべて無視します。 #### CSP適用方法 メッセージヘッダーにcontent-security-policyが追加されるイメージ ![](https://i.imgur.com/Lvi55BP.png) ```ruby= #CSPの適用 #config/initializers/content_security_policy.rbに記述 Rails.application.config.content_security_policy do |policy| policy.default_src :self, :https # サイト自身のドメインとHTTPSを使用した全ドメインを許可する policy.style_src :self, :https, :unsafe_inline # インラインの<style>要素を許可(危険) ... end ``` ```ruby= # コントローラで設定をカスタマイズするには、content_security_policyメソッドを使用 class ArticlesController < ApplicationController content_security_policy do |policy| policy.upgrade_insecure_requests true # httpをhttpsへリダイレクト(対応ブラウザの場合) end end ``` **※ドメイン** = インターネット上に存在するコンピュータやネットワークを識別するためのコンピュータの名前のことを言います。ネットワーク上の住所を表すイメージです。ドメイン名は重複することない一意な名前になるように管理されています。 ### ディレクティブとは ディレクティブとは、和訳すると**指示文**です。 コンピュータプログラムのソースコードに記述される要素の一つで、そのコードを解釈・変換するソフトウェア(コンパイラやプリプロセッサなど)への指示や指定などを与えるためのものです。 ```ruby= #ディレクティブの構文例 #このように<%@ %> で囲い、ページの先頭に記述します。 <%@ ディレクティブ名 属性名1="値1" 属性名2="値2" ... %> ``` ## 参照 【Ruby on Rails】sendメソッドのいろんな書き方 https://qiita.com/ngron/items/05d3a9624c2c3ec5dbb6 Kernel.#eval公式 https://docs.ruby-lang.org/ja/latest/method/Kernel/m/eval.html exitメソッド https://techacademy.jp/magazine/20564 rubyで使うリテラル https://docs.ruby-lang.org/ja/latest/doc/spec=2fliteral.html Rubyのsendメソッドを使用するメリットと注意点 https://qiita.com/hogucc/items/79da134520ee731fe298 Linuxコマンドを連続して実行する https://webkaru.net/linux/execute-combine-multiple-commands/ git logのオプション https://atmarkit.itmedia.co.jp/ait/articles/2004/09/news018.html パケットとは https://www.otsuka-shokai.co.jp/words/packet.html Ruby on Rails 5.2の新機能(Active Storage, Content Security Policyなど) https://qiita.com/ryohashimoto/items/75f48fa5a3846c58f735 コンテンツセキュリティポリシー (CSP) https://developer.mozilla.org/ja/docs/Web/HTTP/CSP ディレクティブとは https://www.javadrive.jp/servlet/jsp_directive/index1.html ## 2021年8月26日 現場Rails Chapter6-8 アセットパイプライン(その①) **アセットパイプライン**とは、gem `sprockets-rails`を活用して、アセット(CSS, JavaScript, 画像etc)を効率的にまとめた上で、軽量化・高速化・変更反映化を実現してくれます。流れとしては以下の順で行います。 1. 高級言語(CoffeeScript,ERB,Slimなど)のコンパイル 2. アセットの連結(複数のjsファイルをapplication.jsにまとめる) 3. アセットの最小化(スペース、改行などを削除してファイルを最小化する) 4. ダイジェストの付与(コードの内容からハッシュ値をファイル名の末尾に付与) *ダイジェスト:`application-xxxxx.js`の「xxxxx」部分。 アセットに変更があると、ダイジェスト値も変化→ブラウザに残っているダイジェスト値と比較→再読込を実行するかを判定します。 ## 環境により挙動が変わる development環境とproduction環境で、それぞれの目的に応じた挙動をします。 ### development環境 - 高級言語のコンパイルとダイジェストの付与は自動で行われます。 - <span style="color: red; ">**アセットの連結と最小化はしません**</span>。デバッグのしやすさを考慮したためです。 development環境下で**デバッグモードをオフ**にする際は、以下の設定をする必要があります。 ```ruby= config.assets.debug = false ``` ### production環境 - 高級言語のコンパイル・アセットの連結・アセットの最小化・ダイジェストの付与**全て行われます**。 ### マニフェストファイル(/application.拡張子) マニフェストファイルには、個別に分類した.CSSや.JSファイルをどのように連結するのかを**ディレクティブ**(指示文)として記述しています。CSSやJSなどアセットごとに**マニュフェストファイル**が作られます。また、**アセットパイプライン実行後の連結結果**もマニュフェストファイルに記述されます。 ```ruby= app/assets/javascript/application.js app/assets/stylesheets/application.css ``` ### マニフェストファイルの書き方 application.jsファイル上では、`//=`で始まる行をディレクティブ(指示文)として扱います。ディレクティブに指定したファイルは**マニフェストファイル**の位置からは見当たらないが、Sprocketsのアセットファイルにアクセスするためのパスを管理する(**アセットパス**)機能を使って、パスを検索しています。 ```ruby= //= require rails-ujs //= require activestorage //= require turbolinks //= require_tree . #「require_tree.」は指定されたディレクトリ配下のの全ファイルの内容を結合します。 #「.」を指定していると、application.jsが配置されているディレクトリ配下が対象となります。 ``` appplication.**scss**ファイル上では、`@import`を使ってファイルを読み込ませます。 ```ruby= @import "bootstrap"; @import "tasks"; ``` ## 参照 Railsガイド アセットパイプライン https://railsguides.jp/asset_pipeline.html Railsガイド アセットパイプライン -デバッグをオフにする- https://railsguides.jp/asset_pipeline.html#%E3%83%87%E3%83%90%E3%83%83%E3%82%B0%E3%82%92%E3%82%AA%E3%83%95%E3%81%AB%E3%81%99%E3%82%8B ## 2021年8月27日 現場Rails Chapter6-8 アセットパイプライン(その②) ### 探索パスについて マニフェストファイルがファイルを探しに行くためのパスを**探索パス**と言います。 マニフェストファイルは**デフォルト**で以下のパスを探しに行きます。 - app/assets/* - lib/assets/* - vendor/assets/* 上記以外のパスを参照したい場合、**config/initializers/assets.rb**に以下の1文を記述します。この1文を記述することで、`node_modules`ディレクトリを探索パスとして設定できます。 ```ruby= Rails.application.ocnfig.assets.paths << Rails.root.join('node_modules') ``` コンソール上で探索パスを確認するには、 ```ruby= puts Rails.application.ocnfig.assets.paths ``` で確認することができます。 ### アセットの設定 **config/initializers/assets.rb** =全ての環境に共通する設定を記述するファイルです。 ```ruby= #config/initializers/assets.rb内に記述 #defaultで設定されているもの #アセットのバージョンを設定する※ Rails.application.config.assets.version = '1.0' #検索パスにnode_moduleを追加 Rails.application.config.assets.paths << Rails.root.join('node_modules') #プリコンパイルするファイルを設定 Rails.application.config.assets.precompile += %w( admin.js admin.css ) マニフェストファイル以外でプリコンパイルするファイルを配列で設定 ``` **config/environments/*** =環境別の設定をconfig/environments以下のファイルに記述します。**development**環境と**production**環境の違いもここに記述します。 ```ruby= #config/environments/以下に記述 #デバックモードで動作する(アセットの連結や前処理を行わない) #defaultでdevelopment環境でのみ有効 config.assets.debug = true #アセットへのリクエストに関するログを減らす。(処理を早くするため) #defalutではdevelopment環境で有効 config.assets.quiet = true #JSとCSSの圧縮方法 #defaultではproduction環境でのみ設定されている config.aseets.js_compressor = :uglifier config.assets.css_compressor = :sass #プリコンパイル済みのアセットが存在しないときに、自動でコンパイルを行わない config.assets.compile = false #アセットファイルを配信するサーバーを設定 config.action_controller.aseet_host = 'サーバーURL' ``` ※プリコンパイル=前処理(preprocess)を行うプログラムのことで、コンパイラの前処理を行います。 #### **アセットのバージョンを指定するとは?** コンパイル時のダイジェストの生成をする(ファイル名の末尾にハッシュを付与する)フェーズで特定の文字列の情報を持たせることができます。そうすることで、バージョン管理の概念を持たせることができます。以下のように**config/initializers/assets.rb**の中に記載することができます。 ```ruby= Rails.application.config.assets.version = '1.0' ``` バージョンを変更すると、変更前のアセットは使用できなくなることに注意します。ただ、あくまで、ハッシュ情報に文字列を持たせているだけなので、文字列が一致すれば使用することはできます。 ## 参照 Rails Guide Configuring Rails Applications https://guides.rubyonrails.org/configuring.html What does config.assets.version do in Rails? - stack overflow https://stackoverflow.com/questions/13873176/what-does-config-assets-version-do-in-rails アセットのバージョンを設定する https://railsguides.jp/asset_pipeline.html#%E5%8F%A4%E3%81%84%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B3%E3%81%AErails%E3%81%8B%E3%82%89%E3%82%A2%E3%83%83%E3%83%97%E3%82%B0%E3%83%AC%E3%83%BC%E3%83%89%E3%81%99%E3%82%8B アセットパイプライン動的コンパイル https://railsguides.jp/asset_pipeline.html#%E5%8B%95%E7%9A%84%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%AB ## 2021年8月28日(土)現場Rails Chapter6-9 production環境でアプリケーションを立ち上げる ### プリコンパイルとは Railsにおける**プリコンパイル**とは、あらかじめ**アセットパイプライン**を実行して**静的ファイル**を生成しておくことを指します。 プリコンパイルされたファイルは**public/assets**ディレクトリの配下に配置されます。 上記における、「静的ファイル」と「プリコンパイルされたファイル」は同じで、**application-asdkljahsoiueraqwrufga8923479q37f89qw4.js**のようなファイル名になります。 ```ruby #プリコンパイルする $ bin/rails assets:precompile #プリコンパイル後に、public/aseets/配下のフォルダにプリコンパイルされたファイルが生成される。フォルダ内のファイルを確認。 $ ls public/assets/application-asdkljahsoiueraqwrufga8923479q37f89qw4.js ``` 例) 100m走を行う場合、スタートの合図と同時に走り出せるように、着替えて靴をはいてスタートする姿勢までの準備をしておくのがプリコンパイルによるpublic配下にファイルが移動した状態です。しかし、これをしていないとスタートの合図がなってから着替えて靴を履くという準備が始まってしまう為に初動が遅れる事態になるから、本番環境ではプリコンパイルを行う必要があると考えられます。 開発環境ではデバッグのしやすさを考慮してプリコンパイルは行われません。 ### 開発環境と本番環境におけるプリコンパイルの挙動の違い 開発環境ではコンパイル時にデフォルトでアセットの連結と最小化を行いません。これをサッカーの試合を例えると、ユニフォームを着ることで観客が視認出来るように配慮しますが、練習(開発環境)では背番号をつける必要は特にありません。汚れたら洗濯(デバッグ)する必要もでてきますし、着替える手間もあります。 プリコンパイルの実行は試合(本番環境)に備えてユニフォームを用意してコートに立つ準備を行うことを指します。 ```ruby= # trueにするとAssetPipeLineが常に実行されるので、リクエストのたびに毎回毎回静的ファイルを生成してしまう。 # 開発時には便利だがメモリを余分に消費したり、パフォーマンスが低下してしまう。 config.assets.compile = false ``` ## 参照 「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典 https://wa3.i-3-i.info/word16767.html A visual guide to Webpacker https://rossta.net/blog/visual-guide-to-webpacker.html アセットのプリコンパイル https://railsguides.jp/asset_pipeline.html#%E3%82%A2%E3%82%BB%E3%83%83%E3%83%88%E3%82%92%E3%83%97%E3%83%AA%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%AB%E3%81%99%E3%82%8B ## 2021年8月30日(月)現場Rails Chapter6-9-2 静的ファイルのサーバーを設定する、秘密情報の管理 ### 動的なファイルと静的なファイル **assets**配下のファイルは**動的ファイル**として扱われ、アセットパイプラインを通して静的なファイルへとコンパイルされ、publicディレクトリの配下に生成されます。 404や500のエラーページは、もともと**静的ファイル**として**public**配下に置かれています。アセットパイプラインでは、**動画コンテンツ**を読み込まないので、動画は**public**配下に設置します。 Railsのコントローラーのアクションを通じて、viewを表示する場合、全て、**動的ページ**になります。コントローラーのアクションで処理されて作られるコンテンツが動的ページです。 例)見た目上では、同じ"Hello World"と表示されているページでも毎回コントローラーのアクションが同じ動的ページを毎回作って配信しているイメージ。   対して、**アクション**を経由せず、直接**webサーバー**から受け取るコンテンツは**静的ページ**になります。そのため、public配下に静的ページを設置しておく必要があります。 publicに配置されているものは、**静的ページ**と捉えて良いです。 ![](https://i.imgur.com/dHPpEZU.png) 静的とは、ボールを投げたら壁に当たって跳ね返ってくる様子で、動的のイメージはキャッチボールのイメージです。 ## 秘密情報の管理 秘密情報はRails5.2から**Credentials**という仕組みで管理されています。 管理したい秘密情報は**yaml形式**で記述し**credentials.yml.enc**の形で管理されます。それにアクセスするための鍵となるのが**master.key**です。 これらは**rails new**したタイミングで自動生成されます。 production環境用の秘密情報は**credentials.yml.enc**に常に暗号化された状態で保存されます。 **master.keyファイル**か**RAILS_MASTER_KEY 環境変数**からキー情報を取り出して秘密情報を復号して利用します。 暗号化された内容はコマンドを実行して閲覧したり、編集することが出来ます。 **master.key**はrailsアプリ作成時に「**.gitignore**」ファイルに記述済みとなっています。「.gitignore」ファイルに、Githubにアップロードしたくないファイルの名前を書くことで、Githubにアップロードされません。「ignore」は英単語で「無視する」という意味なので、「.gitignore」ファイルがこのような機能になります。 ```ruby= #Credentialファイルの中身をCatコマンドで見てみる $ cat config/credentials.yml.enc Q+GBLmbxagoirjyHWkJDdaMdg0cJR...#=>暗号化された状態で、秘密情報が保存されている #ただ、中身を見るだけだと、暗号化された文字列の羅列が見えるだけで何が書いてあるかわからないので、 #credentialファイルの中身を復号して閲覧する $ bin/rails credentials:show #Credentialsファイルの編集 #credentials.yml.encの内容は暗号化されてるため、エディタなどで直接ファイルを開いて編集することはできません。 #コマンドでエディターを指定して、編集する #エディターにviを利用して、credentials.yml.encを編集する場合 $ EDITOR="vi" bin/rails credentials:edit #編集後のファイルを保存すると、再び暗号化して、config/credentials.yml.encとして保存される #=>New credentials encrypted and saved!というメッセージが表示される #credentials.yml.encファイルに設定された秘密情報の読み取り方法 #credentials.yml.encファイルのawsのaccess_key_idをキーとする値を取得 irb(main):001:0>Rails.application.credentials.aws[:access_key_id] => 123 ``` ## 参考 Rails5.2から追加された credentials.yml.enc のキホン https://qiita.com/NaokiIshimura/items/2a179f2ab910992c4d39 ## 2021年8月31日(火)現場Rails Chapter7 ## 7-1-1 ## f.hidden_field f.hidden_fieldとは、画面に表示されないinputタグを生成するメソッドです。このinputタグには値が保持されています。既に決まった値をユーザーから見えない形で送信する際に使います。f.hidden_fieldの代表的な使用例は、確認画面のフォームです。 ↓Rails: How do I use hidden_field in a form_for?の引用 - f.hidden_field ```ruby= <%= f.hidden_field :some_column %> ``` - 上のf.hidden_fieldで生成されるHTML ```ruby= <input type="hidden" id="request_some_column" name="request[some_column]" value="#{@request.some_column}" /> ``` ### valid? >バリデーションが実行された結果 ```ruby= @task.valid? # =>false @task.errors # =>バリデーションにはじかれた内容が入る @task.errors.full_messages # =>エラーメッセージを文章化し、配列で表現 ``` valid?メソッドで、検証が通るか通らないかを確かめています。 ```ruby= true→検証が通る false→検証が通らない ``` #### ↓現場で使えるRuby on Rails P287引用 ```ruby= Rails.application.routes.draw do root to: 'tasks#index' resources :tasks do post :confirm, action: :comfirm_new, on: :new end end ``` 基本的にonオプションはmemberやcollectionなどをresourecesの配下などでネストさせた場合にブロック(do ~ end)の省略をするときに使うものですが、今回におけるonオプションはnewアクションに続くURLとして"tasks/new/confirm"のような形のURLの形式にしたいために、postメソッドの引数で:confirmを明示的に指定します。 ## 参照 <INPUT type="hidden"> http://www.htmq.com/html/input_hidden.shtml Rails: How do I use hidden_field in a form_for? https://stackoverflow.com/questions/3131982/rails-how-do-i-use-hidden-field-in-a-form-for

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully