{"id":1473,"date":"2025-03-24T08:50:38","date_gmt":"2025-03-23T23:50:38","guid":{"rendered":"https:\/\/dexall.co.jp\/articles\/?p=1473"},"modified":"2025-03-24T08:50:38","modified_gmt":"2025-03-23T23:50:38","slug":"%e3%80%90%e4%bf%9d%e5%ad%98%e7%89%88%e3%80%91ruby-on-rails%e3%81%ae%e3%82%bb%e3%83%83%e3%82%b7%e3%83%a7%e3%83%b3%e7%ae%a1%e7%90%86%e5%ae%8c%e5%85%a8%e3%82%ac%e3%82%a4%e3%83%89%ef%bc%9a%e5%ae%9f","status":"publish","type":"post","link":"https:\/\/dexall.co.jp\/articles\/?p=1473","title":{"rendered":"\u3010\u4fdd\u5b58\u7248\u3011Ruby on Rails\u306e\u30bb\u30c3\u30b7\u30e7\u30f3\u7ba1\u7406\u5b8c\u5168\u30ac\u30a4\u30c9\uff1a\u5b9f\u88c5\u304b\u3089\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u307e\u3067\u89e3\u8aac"},"content":{"rendered":"\n<div class=\"toc\"><br \/>\n<b>Warning<\/b>:  Undefined array key \"is_admin\" in <b>\/home\/xs392991\/dexall.co.jp\/public_html\/articles\/wp-content\/themes\/sango-theme\/library\/gutenberg\/dist\/classes\/Toc.php<\/b> on line <b>116<\/b><br \/>\n<br \/>\n<b>Warning<\/b>:  Undefined array key \"is_category_top\" in <b>\/home\/xs392991\/dexall.co.jp\/public_html\/articles\/wp-content\/themes\/sango-theme\/library\/gutenberg\/dist\/classes\/Toc.php<\/b> on line <b>121<\/b><br \/>\n<br \/>\n<b>Warning<\/b>:  Undefined array key \"is_top\" in <b>\/home\/xs392991\/dexall.co.jp\/public_html\/articles\/wp-content\/themes\/sango-theme\/library\/gutenberg\/dist\/classes\/Toc.php<\/b> on line <b>128<\/b><br \/>\n    <div id=\"toc_container\" class=\"sgb-toc--bullets js-smooth-scroll\" data-dialog-title=\"\u76ee\u6b21\">\n      <p class=\"toc_title\">\u76ee\u6b21 <\/p>\n      <ul class=\"toc_list\">  <li class=\"first\">    <a href=\"#i-0\">Ruby on Rails \u306e\u30bb\u30c3\u30b7\u30e7\u30f3\u7ba1\u7406\u3068\u306f<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-1\">\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u57fa\u672c\u6982\u5ff5\u3068\u91cd\u8981\u6027<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-2\">Rails \u304c\u30bb\u30c3\u30b7\u30e7\u30f3\u3092\u6271\u3046\u4ed5\u7d44\u307f<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-3\">Ruby on Rails \u3067\u306e\u30bb\u30c3\u30b7\u30e7\u30f3\u5b9f\u88c5\u65b9\u6cd5<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-4\">\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u8a2d\u5b9a\u3068\u521d\u671f\u5316<\/a>      <\/li>      <li>        <a href=\"#i-5\">\u30bb\u30c3\u30b7\u30e7\u30f3\u30c7\u30fc\u30bf\u306e\u4fdd\u5b58\u3068\u53d6\u5f97<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-6\">\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u6709\u52b9\u671f\u9650\u8a2d\u5b9a<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-7\">\u30bb\u30c3\u30b7\u30e7\u30f3\u30b9\u30c8\u30a2\u306e\u9078\u629e\u3068\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-8\">\u5229\u7528\u53ef\u80fd\u306a\u30b9\u30c8\u30a2\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u6bd4\u8f03<\/a>      <\/li>      <li>        <a href=\"#i-9\">\u74b0\u5883\u306b\u5fdc\u3058\u305f\u6700\u9069\u306a\u30b9\u30c8\u30a2\u306e\u9078\u629e<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-10\">\u30bb\u30c3\u30b7\u30e7\u30f3\u30b9\u30c8\u30a2\u306e\u8a2d\u5b9a\u65b9\u6cd5<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-11\">\u30bb\u30c3\u30b7\u30e7\u30f3\u3092\u4f7f\u3063\u305f\u8a8d\u8a3c\u306e\u5b9f\u88c5<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-12\">\u57fa\u672c\u7684\u306a\u30e6\u30fc\u30b6\u30fc\u8a8d\u8a3c\u306e\u5b9f\u88c5\u624b\u9806<\/a>      <\/li>      <li>        <a href=\"#i-13\">\u30bb\u30c3\u30b7\u30e7\u30f3\u30cf\u30a4\u30b8\u30e3\u30c3\u30af\u5bfe\u7b56<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-14\">\u30ed\u30b0\u30a2\u30a6\u30c8\u6a5f\u80fd\u306e\u5b9f\u88c5<\/a>      <\/li>    <\/ul>  <\/li>  <li>    <a href=\"#i-15\">\u30bb\u30c3\u30b7\u30e7\u30f3\u7ba1\u7406\u306e\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u5bfe\u7b56<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-16\">\u4e00\u822c\u7684\u306a\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u30ea\u30b9\u30af\u3068\u5bfe\u7b56<\/a>      <\/li>      <li>        <a href=\"#i-17\">\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u6697\u53f7\u5316\u3068\u4fdd\u8b77<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-18\">CSRF\u304b\u3089\u306e\u9632\u5fa1\u65b9\u6cd5<\/a>      <\/li>    <\/ul>  <\/li>  <li class=\"last\">    <a href=\"#i-19\">\u30bb\u30c3\u30b7\u30e7\u30f3\u7ba1\u7406\u306e\u30c8\u30e9\u30d6\u30eb\u30b7\u30e5\u30fc\u30c6\u30a3\u30f3\u30b0<\/a>    <ul class=\"menu_level_1\">      <li class=\"first\">        <a href=\"#i-20\">\u3088\u304f\u3042\u308b\u30a8\u30e9\u30fc\u3068\u89e3\u6c7a\u65b9\u6cd5<\/a>      <\/li>      <li>        <a href=\"#i-21\">\u30c7\u30d0\u30c3\u30b0\u306e\u65b9\u6cd5\u3068\u30c4\u30fc\u30eb<\/a>      <\/li>      <li class=\"last\">        <a href=\"#i-22\">\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u6700\u9069\u5316\u306e\u30dd\u30a4\u30f3\u30c8<\/a>      <\/li>    <\/ul>  <\/li><\/ul>\n      <a href=\"#\" class=\"sgb-toc-button js-toc-button\" rel=\"nofollow\" data-open-dialog=\"true\"><i class=\"fa fa-list\"><\/i><span class=\"sgb-toc-button__text\">\u76ee\u6b21\u3078<\/span><\/a>\n    <\/div><\/div><h2 class=\"wp-block-heading\" id=\"i-0\">Ruby on Rails \u306e\u30bb\u30c3\u30b7\u30e7\u30f3\u7ba1\u7406\u3068\u306f<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-1\">\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u57fa\u672c\u6982\u5ff5\u3068\u91cd\u8981\u6027<\/h3>\n\n\n\n<p>Web\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306b\u304a\u3051\u308b\u30bb\u30c3\u30b7\u30e7\u30f3\u7ba1\u7406\u306f\u3001\u30b9\u30c6\u30fc\u30c8\u30ec\u30b9\u306aHTTP\u30d7\u30ed\u30c8\u30b3\u30eb\u4e0a\u3067\u30e6\u30fc\u30b6\u30fc\u306e\u72b6\u614b\u3092\u7dad\u6301\u3059\u308b\u305f\u3081\u306e\u91cd\u8981\u306a\u6a5f\u80fd\u3067\u3059\u3002Ruby on Rails\u3067\u306f\u3001\u30bb\u30c3\u30b7\u30e7\u30f3\u3092\u4f7f\u7528\u3059\u308b\u3053\u3068\u3067\u3001\u30ea\u30af\u30a8\u30b9\u30c8\u9593\u3067\u30e6\u30fc\u30b6\u30fc\u306e\u60c5\u5831\u3092\u4fdd\u6301\u3057\u3001\u30b9\u30e0\u30fc\u30ba\u306a\u30e6\u30fc\u30b6\u30fc\u30a8\u30af\u30b9\u30da\u30ea\u30a8\u30f3\u30b9\u3092\u63d0\u4f9b\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<p>\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u4e3b\u306a\u7528\u9014\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30e6\u30fc\u30b6\u30fc\u8a8d\u8a3c\u72b6\u614b\u306e\u7ba1\u7406<\/li>\n\n\n\n<li>\u30b7\u30e7\u30c3\u30d4\u30f3\u30b0\u30ab\u30fc\u30c8\u306e\u60c5\u5831\u4fdd\u6301<\/li>\n\n\n\n<li>\u30e6\u30fc\u30b6\u30fc\u8a2d\u5b9a\u306e\u4e00\u6642\u4fdd\u5b58<\/li>\n\n\n\n<li>\u30de\u30eb\u30c1\u30b9\u30c6\u30c3\u30d7\u30d5\u30a9\u30fc\u30e0\u306e\u72b6\u614b\u7ba1\u7406<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-2\">Rails \u304c\u30bb\u30c3\u30b7\u30e7\u30f3\u3092\u6271\u3046\u4ed5\u7d44\u307f<\/h3>\n\n\n\n<p>Ruby on Rails\u3067\u306f\u3001\u30bb\u30c3\u30b7\u30e7\u30f3\u7ba1\u7406\u304c\u6a19\u6e96\u3067\u7d44\u307f\u8fbc\u307e\u308c\u3066\u304a\u308a\u3001\u4ee5\u4e0b\u306e\u4ed5\u7d44\u307f\u3067\u52d5\u4f5c\u3057\u307e\u3059\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u958b\u59cb<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># config\/initializers\/session_store.rb\nRails.application.config.session_store :cookie_store, key: '_your_app_session'<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u30c7\u30fc\u30bf\u306e\u4fdd\u5b58<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class ApplicationController &lt; ActionController::Base\n  def save_user_preference\n    session[:theme] = 'dark'  # \u30bb\u30c3\u30b7\u30e7\u30f3\u3078\u306e\u4fdd\u5b58\n    session[:language] = 'ja' # \u8907\u6570\u306e\u5024\u3092\u4fdd\u5b58\u53ef\u80fd\n  end\nend<\/pre>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3ID\u306e\u751f\u6210\u3068\u7ba1\u7406<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Rails\u306f\u81ea\u52d5\u7684\u306b\u4e00\u610f\u306e\u30bb\u30c3\u30b7\u30e7\u30f3ID\u3092\u751f\u6210<\/li>\n\n\n\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3ID\u306f\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u306e\u30af\u30c3\u30ad\u30fc\u306b\u4fdd\u5b58<\/li>\n\n\n\n<li>\u30c7\u30d5\u30a9\u30eb\u30c8\u3067\u306f\u30af\u30c3\u30ad\u30fc\u30b9\u30c8\u30a2\u3092\u4f7f\u7528<\/li>\n<\/ul>\n\n\n\n<p>\u30bb\u30c3\u30b7\u30e7\u30f3\u30c7\u30fc\u30bf\u306e\u4fdd\u5b58\u5834\u6240\uff08\u30b9\u30c8\u30a2\uff09\u306b\u306f\u4ee5\u4e0b\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u304c\u3042\u308a\u307e\u3059\uff1a<\/p>\n\n\n<div id=\"id-2001c5a6-089c-4c4a-b31c-bb368e6b3f15\">\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u30b9\u30c8\u30a2\u306e\u7a2e\u985e<\/th><th>\u7279\u5fb4<\/th><th>\u7528\u9014<\/th><\/tr><\/thead><tbody><tr><td>CookieStore<\/td><td>\u9ad8\u901f\u30fb\u30b7\u30f3\u30d7\u30eb<\/td><td>\u5c0f\u898f\u6a21\u30a2\u30d7\u30ea<\/td><\/tr><tr><td>CacheStore<\/td><td>\u9ad8\u901f\u30fb\u5927\u5bb9\u91cf<\/td><td>\u4e2d\u898f\u6a21\u30a2\u30d7\u30ea<\/td><\/tr><tr><td>ActiveRecordStore<\/td><td>\u6c38\u7d9a\u5316\u30fb\u7ba1\u7406\u5bb9\u6613<\/td><td>\u5927\u898f\u6a21\u30a2\u30d7\u30ea<\/td><\/tr><tr><td>RedisStore<\/td><td>\u9ad8\u901f\u30fb\u30b9\u30b1\u30fc\u30e9\u30d6\u30eb<\/td><td>\u5206\u6563\u30b7\u30b9\u30c6\u30e0<\/td><\/tr><\/tbody><\/table><\/figure>\n<\/div>\n\n\n<p>\u30bb\u30c3\u30b7\u30e7\u30f3\u30c7\u30fc\u30bf\u3078\u306e\u30a2\u30af\u30bb\u30b9\u65b9\u6cd5\uff1a<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># \u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u30fc\u5185\u3067\u306e\u30bb\u30c3\u30b7\u30e7\u30f3\u64cd\u4f5c\ndef show_session_data\n  @user_theme = session[:theme]      # \u30bb\u30c3\u30b7\u30e7\u30f3\u304b\u3089\u306e\u8aad\u307f\u53d6\u308a\n  session.delete(:theme)             # \u7279\u5b9a\u306e\u30ad\u30fc\u306e\u524a\u9664\n  session.clear                      # \u30bb\u30c3\u30b7\u30e7\u30f3\u5168\u4f53\u306e\u30af\u30ea\u30a2\n  reset_session                      # \u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u5b8c\u5168\u30ea\u30bb\u30c3\u30c8\nend<\/pre>\n\n\n\n<p>\u30bb\u30c3\u30b7\u30e7\u30f3\u7ba1\u7406\u306b\u304a\u3051\u308b\u91cd\u8981\u306a\u30dd\u30a4\u30f3\u30c8\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u30cf\u30a4\u30b8\u30e3\u30c3\u30af\u5bfe\u7b56<\/li>\n\n\n\n<li>CSRF\u4fdd\u8b77\u306e\u5b9f\u88c5<\/li>\n\n\n\n<li>\u9069\u5207\u306a\u6709\u52b9\u671f\u9650\u306e\u8a2d\u5b9a<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u30c7\u30fc\u30bf\u306e\u30b5\u30a4\u30ba\u5236\u9650<\/li>\n\n\n\n<li>\u9069\u5207\u306a\u30b9\u30c8\u30a2\u306e\u9078\u629e<\/li>\n\n\n\n<li>\u4e0d\u8981\u306a\u30bb\u30c3\u30b7\u30e7\u30f3\u30c7\u30fc\u30bf\u306e\u524a\u9664<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30b9\u30b1\u30fc\u30e9\u30d3\u30ea\u30c6\u30a3<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u5206\u6563\u30b7\u30b9\u30c6\u30e0\u3067\u306e\u5bfe\u5fdc<\/li>\n\n\n\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u30b9\u30c8\u30a2\u306e\u9078\u629e<\/li>\n\n\n\n<li>\u8ca0\u8377\u5206\u6563\u3078\u306e\u8003\u616e<\/li>\n<\/ul>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u57fa\u672c\u3092\u7406\u89e3\u3059\u308b\u3053\u3068\u3067\u3001Rails\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u5b89\u5168\u304b\u3064\u52b9\u7387\u7684\u306a\u30bb\u30c3\u30b7\u30e7\u30f3\u7ba1\u7406\u3092\u5b9f\u88c5\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-3\">Ruby on Rails \u3067\u306e\u30bb\u30c3\u30b7\u30e7\u30f3\u5b9f\u88c5\u65b9\u6cd5<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-4\">\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u8a2d\u5b9a\u3068\u521d\u671f\u5316<\/h3>\n\n\n\n<p>Rails \u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u30bb\u30c3\u30b7\u30e7\u30f3\u3092\u5229\u7528\u3059\u308b\u305f\u3081\u306e\u57fa\u672c\u7684\u306a\u8a2d\u5b9a\u3068\u521d\u671f\u5316\u65b9\u6cd5\u3092\u89e3\u8aac\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u30b9\u30c8\u30a2\u306e\u8a2d\u5b9a<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># config\/initializers\/session_store.rb\nRails.application.config.session_store :cookie_store, {\n  key: '_your_app_session',           # \u30bb\u30c3\u30b7\u30e7\u30f3\u30af\u30c3\u30ad\u30fc\u306e\u540d\u524d\n  expire_after: 24.hours,             # \u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u6709\u52b9\u671f\u9650\n  secure: Rails.env.production?,      # HTTPS\u9650\u5b9a\n  same_site: :lax                     # SameSite\u5c5e\u6027\u306e\u8a2d\u5b9a\n}<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u30fc\u3067\u306e\u8a2d\u5b9a<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># app\/controllers\/application_controller.rb\nclass ApplicationController &lt; ActionController::Base\n  # \u30bb\u30c3\u30b7\u30e7\u30f3\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8\u306e\u8a2d\u5b9a\n  before_action :check_session_timeout\n\n  private\n\n  def check_session_timeout\n    if session[:last_seen_at] &amp;&amp; session[:last_seen_at] &lt; 30.minutes.ago\n      reset_session\n      redirect_to login_path, alert: '\u30bb\u30c3\u30b7\u30e7\u30f3\u304c\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8\u3057\u307e\u3057\u305f'\n    end\n    session[:last_seen_at] = Time.current\n  end\nend<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-5\">\u30bb\u30c3\u30b7\u30e7\u30f3\u30c7\u30fc\u30bf\u306e\u4fdd\u5b58\u3068\u53d6\u5f97<\/h3>\n\n\n\n<p>\u30bb\u30c3\u30b7\u30e7\u30f3\u30c7\u30fc\u30bf\u306e\u52b9\u679c\u7684\u306a\u7ba1\u7406\u65b9\u6cd5\u3092\u7d39\u4ecb\u3057\u307e\u3059\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u57fa\u672c\u7684\u306a\u30c7\u30fc\u30bf\u306e\u4fdd\u5b58\u3068\u53d6\u5f97<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class UserPreferencesController &lt; ApplicationController\n  def update\n    # \u30bb\u30c3\u30b7\u30e7\u30f3\u3078\u306e\u30c7\u30fc\u30bf\u4fdd\u5b58\n    session[:theme] = params[:theme]\n    session[:language] = params[:language]\n    session[:notifications] = {\n      email: params[:email_notifications],\n      push: params[:push_notifications]\n    }\n\n    # \u30bb\u30c3\u30b7\u30e7\u30f3\u304b\u3089\u306e\u30c7\u30fc\u30bf\u53d6\u5f97\n    @current_theme = session[:theme]\n    @preferences = session[:notifications]\n  end\nend<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>\u8907\u96d1\u306a\u30aa\u30d6\u30b8\u30a7\u30af\u30c8\u306e\u53d6\u308a\u6271\u3044<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">class CartController &lt; ApplicationController\n  def add_item\n    # \u30ab\u30fc\u30c8\u306e\u521d\u671f\u5316\uff08\u5b58\u5728\u3057\u306a\u3044\u5834\u5408\uff09\n    session[:cart] ||= []\n\n    # \u5546\u54c1\u306e\u8ffd\u52a0\n    product = {\n      id: params[:product_id],\n      quantity: params[:quantity],\n      added_at: Time.current\n    }\n\n    session[:cart] &lt;&lt; product\n\n    # \u30ab\u30fc\u30c8\u306e\u5408\u8a08\u91d1\u984d\u306e\u8a08\u7b97\u3068\u4fdd\u5b58\n    total = calculate_cart_total(session[:cart])\n    session[:cart_total] = total\n  end\n\n  private\n\n  def calculate_cart_total(cart_items)\n    cart_items.sum { |item| item[:price] * item[:quantity] }\n  end\nend<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-6\">\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u6709\u52b9\u671f\u9650\u8a2d\u5b9a<\/h3>\n\n\n\n<p>\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u6709\u52b9\u671f\u9650\u3092\u9069\u5207\u306b\u7ba1\u7406\u3059\u308b\u3053\u3068\u306f\u3001\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u3068\u30e6\u30fc\u30b6\u30fc\u30a8\u30af\u30b9\u30da\u30ea\u30a8\u30f3\u30b9\u306e\u4e21\u9762\u3067\u91cd\u8981\u3067\u3059\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30b0\u30ed\u30fc\u30d0\u30eb\u306a\u6709\u52b9\u671f\u9650\u8a2d\u5b9a<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># config\/initializers\/session_store.rb\nRails.application.config.session_store :cookie_store, {\n  key: '_your_app_session',\n  expire_after: 12.hours,            # 12\u6642\u9593\u3067\u30bb\u30c3\u30b7\u30e7\u30f3\u671f\u9650\u5207\u308c\n  same_site: :strict,                # \u3088\u308a\u30bb\u30ad\u30e5\u30a2\u306aSameSite\u8a2d\u5b9a\n  secure: true                       # HTTPS\u5fc5\u9808\n}<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>\u52d5\u7684\u306a\u6709\u52b9\u671f\u9650\u7ba1\u7406<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># app\/controllers\/concerns\/session_management.rb\nmodule SessionManagement\n  extend ActiveSupport::Concern\n\n  included do\n    before_action :update_session_expiry\n  end\n\n  private\n\n  def update_session_expiry\n    return unless current_user\n\n    # \u30e6\u30fc\u30b6\u30fc\u306e\u6700\u7d42\u30a2\u30af\u30c6\u30a3\u30d6\u6642\u9593\u3092\u66f4\u65b0\n    session[:last_activity] = Time.current\n\n    # \u7279\u5b9a\u306e\u6761\u4ef6\u4e0b\u3067\u30bb\u30c3\u30b7\u30e7\u30f3\u671f\u9650\u3092\u5ef6\u9577\n    if should_extend_session?\n      session[:expires_at] = 8.hours.from_now\n    end\n  end\n\n  def should_extend_session?\n    return false unless session[:expires_at]\n    session[:expires_at] &lt; 2.hours.from_now\n  end\n\n  def session_expired?\n    session[:expires_at].present? &amp;&amp; session[:expires_at] &lt; Time.current\n  end\nend<\/pre>\n\n\n\n<p>\u5b9f\u88c5\u6642\u306e\u91cd\u8981\u306a\u30dd\u30a4\u30f3\u30c8\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30c7\u30fc\u30bf\u306e\u6574\u5408\u6027<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u30c7\u30fc\u30bf\u306e\u578b\u3092\u4e00\u8cab\u3055\u305b\u308b<\/li>\n\n\n\n<li>\u5fc5\u8981\u6700\u5c0f\u9650\u306e\u30c7\u30fc\u30bf\u306e\u307f\u3092\u4fdd\u5b58<\/li>\n\n\n\n<li>\u5b9a\u671f\u7684\u306a\u30af\u30ea\u30fc\u30f3\u30a2\u30c3\u30d7\u306e\u5b9f\u65bd<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30a8\u30e9\u30fc\u30cf\u30f3\u30c9\u30ea\u30f3\u30b0<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">def handle_session_data\n  begin\n    session[:complex_data] = process_data(params[:data])\n  rescue StandardError =&gt; e\n    logger.error \"\u30bb\u30c3\u30b7\u30e7\u30f3\u30c7\u30fc\u30bf\u51e6\u7406\u30a8\u30e9\u30fc: #{e.message}\"\n    flash[:error] = '\u30c7\u30fc\u30bf\u306e\u51e6\u7406\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f'\n    session[:complex_data] = nil\n  end\nend<\/pre>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li>\u5927\u898f\u6a21\u30c7\u30fc\u30bf\u306e\u53d6\u308a\u6271\u3044<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u30b5\u30a4\u30ba\u306e\u5236\u9650\uff084KB\uff09\u306b\u6ce8\u610f<\/li>\n\n\n\n<li>\u5fc5\u8981\u306b\u5fdc\u3058\u3066\u4e00\u6642\u30c7\u30fc\u30bf\u30b9\u30c8\u30a2\u306e\u4f7f\u7528<\/li>\n\n\n\n<li>\u5b9a\u671f\u7684\u306a\u30bb\u30c3\u30b7\u30e7\u30f3\u30c7\u30fc\u30bf\u306e\u6700\u9069\u5316<\/li>\n<\/ul>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u5b9f\u88c5\u65b9\u6cd5\u3092\u9069\u5207\u306b\u7d44\u307f\u5408\u308f\u305b\u308b\u3053\u3068\u3067\u3001\u5b89\u5168\u3067\u52b9\u7387\u7684\u306a\u30bb\u30c3\u30b7\u30e7\u30f3\u7ba1\u7406\u3092\u5b9f\u73fe\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-7\">\u30bb\u30c3\u30b7\u30e7\u30f3\u30b9\u30c8\u30a2\u306e\u9078\u629e\u3068\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-8\">\u5229\u7528\u53ef\u80fd\u306a\u30b9\u30c8\u30a2\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u6bd4\u8f03<\/h3>\n\n\n\n<p>Rails\u3067\u306f\u3001\u8907\u6570\u306e\u30bb\u30c3\u30b7\u30e7\u30f3\u30b9\u30c8\u30a2\u65b9\u5f0f\u304c\u63d0\u4f9b\u3055\u308c\u3066\u304a\u308a\u3001\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u8981\u4ef6\u306b\u5fdc\u3058\u3066\u6700\u9069\u306a\u3082\u306e\u3092\u9078\u629e\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<p>\u4e3b\u8981\u306a\u30bb\u30c3\u30b7\u30e7\u30f3\u30b9\u30c8\u30a2\u306e\u7279\u5fb4\u6bd4\u8f03\uff1a<\/p>\n\n\n<div id=\"id-f35838a3-093e-4ba2-a0f4-1ca855a4d0e6\">\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>\u30b9\u30c8\u30a2\u7a2e\u985e<\/th><th>\u30e1\u30ea\u30c3\u30c8<\/th><th>\u30c7\u30e1\u30ea\u30c3\u30c8<\/th><th>\u9069\u7528\u5834\u9762<\/th><\/tr><\/thead><tbody><tr><td>CookieStore<\/td><td>\u30fb\u8a2d\u5b9a\u304c\u7c21\u5358<br>\u30fb\u8ffd\u52a0\u30a4\u30f3\u30d5\u30e9\u4e0d\u8981<br>\u30fb\u9ad8\u901f<\/td><td>\u30fb\u30b5\u30a4\u30ba\u5236\u9650(4KB)<br>\u30fb\u30af\u30e9\u30a4\u30a2\u30f3\u30c8\u5074\u3067\u6539\u3056\u3093\u306e\u30ea\u30b9\u30af<\/td><td>\u5c0f\u898f\u6a21\u30a2\u30d7\u30ea\u3001\u30b7\u30f3\u30d7\u30eb\u306a\u30bb\u30c3\u30b7\u30e7\u30f3\u7ba1\u7406<\/td><\/tr><tr><td>ActiveRecordStore<\/td><td>\u30fb\u5927\u5bb9\u91cf\u30c7\u30fc\u30bf\u5bfe\u5fdc<br>\u30fb\u6c38\u7d9a\u5316\u304c\u5bb9\u6613<br>\u30fb\u30bb\u30c3\u30b7\u30e7\u30f3\u7ba1\u7406\u304c\u5bb9\u6613<\/td><td>\u30fbDB\u30a2\u30af\u30bb\u30b9\u306b\u3088\u308b\u9045\u5ef6<br>\u30fb\u5b9a\u671f\u7684\u306a\u30af\u30ea\u30fc\u30f3\u30a2\u30c3\u30d7\u304c\u5fc5\u8981<\/td><td>\u5927\u898f\u6a21\u30a2\u30d7\u30ea\u3001\u8907\u96d1\u306a\u30bb\u30c3\u30b7\u30e7\u30f3\u30c7\u30fc\u30bf<\/td><\/tr><tr><td>RedisStore<\/td><td>\u30fb\u9ad8\u901f<br>\u30fb\u30b9\u30b1\u30fc\u30e9\u30d6\u30eb<br>\u30fb\u30c7\u30fc\u30bf\u6c38\u7d9a\u5316<\/td><td>\u30fb\u8ffd\u52a0\u30a4\u30f3\u30d5\u30e9\u5fc5\u8981<br>\u30fb\u904b\u7528\u30b3\u30b9\u30c8\u5897\u52a0<\/td><td>\u9ad8\u30c8\u30e9\u30d5\u30a3\u30c3\u30af\u30a2\u30d7\u30ea\u3001\u5206\u6563\u30b7\u30b9\u30c6\u30e0<\/td><\/tr><tr><td>MemCacheStore<\/td><td>\u30fb\u9ad8\u901f<br>\u30fb\u5206\u6563\u5316\u5bb9\u6613<\/td><td>\u30fb\u30c7\u30fc\u30bf\u6c38\u7d9a\u5316\u306a\u3057<br>\u30fb\u30e1\u30e2\u30ea\u5236\u9650<\/td><td>\u30ad\u30e3\u30c3\u30b7\u30e5\u91cd\u8996\u306e\u30a2\u30d7\u30ea<\/td><\/tr><\/tbody><\/table><\/figure>\n<\/div>\n\n\n<h3 class=\"wp-block-heading\" id=\"i-9\">\u74b0\u5883\u306b\u5fdc\u3058\u305f\u6700\u9069\u306a\u30b9\u30c8\u30a2\u306e\u9078\u629e<\/h3>\n\n\n\n<p>\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306e\u7279\u6027\u306b\u57fa\u3065\u3044\u305f\u30b9\u30c8\u30a2\u9078\u629e\u306e\u30ac\u30a4\u30c9\u30e9\u30a4\u30f3\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u5c0f\u898f\u6a21\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u5411\u3051<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># config\/initializers\/session_store.rb\nRails.application.config.session_store :cookie_store, {\n  key: '_app_session',\n  expire_after: 24.hours,\n  secure: Rails.env.production?\n}<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>\u5927\u898f\u6a21\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u5411\u3051\uff08Redis\u4f7f\u7528\uff09<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># Gemfile\ngem 'redis-rails'\n\n# config\/initializers\/session_store.rb\nRails.application.config.session_store :redis_store, {\n  servers: [\n    { host: ENV['REDIS_HOST'], port: 6379, db: 0 },\n    { host: ENV['REDIS_REPLICA_HOST'], port: 6379, db: 0, role: 'replica' }\n  ],\n  expire_after: 24.hours,\n  key: '_app_session',\n  secure: true\n}<\/pre>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li>ActiveRecord\u3092\u4f7f\u7528\u3059\u308b\u5834\u5408<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># Gemfile\ngem 'activerecord-session_store'\n\n# config\/initializers\/session_store.rb\nRails.application.config.session_store :active_record_store, {\n  key: '_app_session',\n  expire_after: 24.hours,\n  secure: true,\n  cleanup_frequency: 24.hours\n}\n\n# \u30bb\u30c3\u30b7\u30e7\u30f3\u30c6\u30fc\u30d6\u30eb\u306e\u4f5c\u6210\n# rails generate active_record:session_migration<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-10\">\u30bb\u30c3\u30b7\u30e7\u30f3\u30b9\u30c8\u30a2\u306e\u8a2d\u5b9a\u65b9\u6cd5<\/h3>\n\n\n\n<p>\u5404\u30b9\u30c8\u30a2\u306e\u8a73\u7d30\u8a2d\u5b9a\u3068\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>RedisStore\u306e\u9ad8\u5ea6\u306a\u8a2d\u5b9a<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># config\/initializers\/session_store.rb\nrequire 'redis'\nrequire 'redis-store'\n\nRedis.current = Redis.new(\n  host: ENV['REDIS_HOST'],\n  port: 6379,\n  db: 0,\n  password: ENV['REDIS_PASSWORD'],\n  ssl: true,\n  timeout: 5.seconds,\n  reconnect_attempts: 3\n)\n\nRails.application.config.session_store :redis_store, {\n  redis: Redis.current,\n  expire_after: 12.hours,\n  key_prefix: 'app:session:',\n  secure: true,\n  throttle: { # \u30ec\u30fc\u30c8\u5236\u9650\u306e\u8a2d\u5b9a\n    min_requests: 2,\n    min_interval: 1.second\n  }\n}<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u6700\u9069\u5316\u306e\u305f\u3081\u306e\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># app\/controllers\/application_controller.rb\nclass ApplicationController &lt; ActionController::Base\n  include SessionOptimization\nend\n\n# app\/controllers\/concerns\/session_optimization.rb\nmodule SessionOptimization\n  extend ActiveSupport::Concern\n\n  included do\n    before_action :optimize_session_data\n  end\n\n  private\n\n  def optimize_session_data\n    # \u5927\u304d\u306a\u30bb\u30c3\u30b7\u30e7\u30f3\u30c7\u30fc\u30bf\u306e\u5727\u7e2e\n    if session[:large_data].present?\n      session[:large_data] = compress_data(session[:large_data])\n    end\n\n    # \u53e4\u3044\u30bb\u30c3\u30b7\u30e7\u30f3\u30c7\u30fc\u30bf\u306e\u524a\u9664\n    cleanup_old_session_data\n  end\n\n  def compress_data(data)\n    Base64.encode64(Zlib::Deflate.deflate(data.to_json))\n  end\n\n  def cleanup_old_session_data\n    expired_keys = session.keys.select { |k| k.start_with?('temp_') }\n    expired_keys.each { |k| session.delete(k) }\n  end\nend<\/pre>\n\n\n\n<p>\u5b9f\u88c5\u6642\u306e\u6ce8\u610f\u70b9\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u8003\u616e\u4e8b\u9805<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30d7\u30ed\u30c0\u30af\u30b7\u30e7\u30f3\u74b0\u5883\u3067\u306f\u5fc5\u305aSSL\/TLS\u3092\u4f7f\u7528<\/li>\n\n\n\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u30c7\u30fc\u30bf\u306e\u6697\u53f7\u5316<\/li>\n\n\n\n<li>\u9069\u5207\u306a\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8\u8a2d\u5b9a<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u6700\u9069\u5316<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u30c7\u30fc\u30bf\u306e\u6700\u5c0f\u5316<\/li>\n\n\n\n<li>\u9069\u5207\u306a\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u8a2d\u5b9a\uff08ActiveRecordStore\u4f7f\u7528\u6642\uff09<\/li>\n\n\n\n<li>\u5b9a\u671f\u7684\u306a\u30bb\u30c3\u30b7\u30e7\u30f3\u30af\u30ea\u30fc\u30f3\u30a2\u30c3\u30d7<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u904b\u7528\u7ba1\u7406<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30e2\u30cb\u30bf\u30ea\u30f3\u30b0\u306e\u5b9f\u88c5<\/li>\n\n\n\n<li>\u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u6226\u7565\u306e\u7b56\u5b9a<\/li>\n\n\n\n<li>\u30b9\u30b1\u30fc\u30ea\u30f3\u30b0\u8a08\u753b\u306e\u7acb\u6848<\/li>\n<\/ul>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u8003\u616e\u4e8b\u9805\u3092\u8e0f\u307e\u3048\u3066\u9069\u5207\u306a\u30bb\u30c3\u30b7\u30e7\u30f3\u30b9\u30c8\u30a2\u3092\u9078\u629e\u3059\u308b\u3053\u3068\u3067\u3001\u5b89\u5168\u3067\u52b9\u7387\u7684\u306a\u30bb\u30c3\u30b7\u30e7\u30f3\u7ba1\u7406\u3092\u5b9f\u73fe\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-11\">\u30bb\u30c3\u30b7\u30e7\u30f3\u3092\u4f7f\u3063\u305f\u8a8d\u8a3c\u306e\u5b9f\u88c5<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-12\">\u57fa\u672c\u7684\u306a\u30e6\u30fc\u30b6\u30fc\u8a8d\u8a3c\u306e\u5b9f\u88c5\u624b\u9806<\/h3>\n\n\n\n<p>\u30bb\u30c3\u30b7\u30e7\u30f3\u3092\u4f7f\u7528\u3057\u305f\u5b89\u5168\u306a\u8a8d\u8a3c\u30b7\u30b9\u30c6\u30e0\u306e\u5b9f\u88c5\u65b9\u6cd5\u3092\u89e3\u8aac\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u8a8d\u8a3c\u7528\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u4f5c\u6210<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># app\/controllers\/concerns\/authentication.rb\nmodule Authentication\n  extend ActiveSupport::Concern\n\n  included do\n    before_action :authenticate_user!\n    helper_method :current_user, :user_signed_in?\n  end\n\n  private\n\n  def authenticate_user!\n    unless user_signed_in?\n      store_location\n      redirect_to login_path, alert: '\u30ed\u30b0\u30a4\u30f3\u304c\u5fc5\u8981\u3067\u3059'\n    end\n  end\n\n  def current_user\n    @current_user ||= User.find_by(id: session[:user_id]) if session[:user_id]\n  end\n\n  def user_signed_in?\n    current_user.present?\n  end\n\n  def store_location\n    session[:return_to] = request.fullpath if request.get?\n  end\n\n  def after_sign_in_path\n    session.delete(:return_to) || root_path\n  end\nend<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u30b3\u30f3\u30c8\u30ed\u30fc\u30e9\u30fc\u306e\u5b9f\u88c5<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># app\/controllers\/sessions_controller.rb\nclass SessionsController &lt; ApplicationController\n  skip_before_action :authenticate_user!, only: [:new, :create]\n\n  def new\n  end\n\n  def create\n    user = User.find_by(email: params[:email])\n    if user&amp;.authenticate(params[:password])\n      create_user_session(user)\n      redirect_to after_sign_in_path, notice: '\u30ed\u30b0\u30a4\u30f3\u3057\u307e\u3057\u305f'\n    else\n      flash.now[:alert] = '\u30e1\u30fc\u30eb\u30a2\u30c9\u30ec\u30b9\u307e\u305f\u306f\u30d1\u30b9\u30ef\u30fc\u30c9\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093'\n      render :new\n    end\n  end\n\n  def destroy\n    destroy_user_session\n    redirect_to root_path, notice: '\u30ed\u30b0\u30a2\u30a6\u30c8\u3057\u307e\u3057\u305f'\n  end\n\n  private\n\n  def create_user_session(user)\n    reset_session # \u30bb\u30c3\u30b7\u30e7\u30f3\u30d5\u30a3\u30af\u30bb\u30fc\u30b7\u30e7\u30f3\u5bfe\u7b56\n    session[:user_id] = user.id\n    session[:user_agent] = request.user_agent\n    session[:last_seen_at] = Time.current\n  end\n\n  def destroy_user_session\n    reset_session\n  end\nend<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-13\">\u30bb\u30c3\u30b7\u30e7\u30f3\u30cf\u30a4\u30b8\u30e3\u30c3\u30af\u5bfe\u7b56<\/h3>\n\n\n\n<p>\u30bb\u30ad\u30e5\u30a2\u306a\u30bb\u30c3\u30b7\u30e7\u30f3\u7ba1\u7406\u306e\u305f\u3081\u306e\u5bfe\u7b56\u3092\u5b9f\u88c5\u3057\u307e\u3059\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u306e\u5f37\u5316<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># config\/initializers\/security_headers.rb\nRails.application.config.action_dispatch.default_headers = {\n  'X-Frame-Options' =&gt; 'SAMEORIGIN',\n  'X-XSS-Protection' =&gt; '1; mode=block',\n  'X-Content-Type-Options' =&gt; 'nosniff',\n  'X-Download-Options' =&gt; 'noopen',\n  'X-Permitted-Cross-Domain-Policies' =&gt; 'none',\n  'Referrer-Policy' =&gt; 'strict-origin-when-cross-origin'\n}<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u4fdd\u8b77\u30e2\u30b8\u30e5\u30fc\u30eb<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># app\/controllers\/concerns\/session_security.rb\nmodule SessionSecurity\n  extend ActiveSupport::Concern\n\n  included do\n    before_action :verify_session_integrity\n    before_action :update_session_activity\n  end\n\n  private\n\n  def verify_session_integrity\n    if session[:user_id].present?\n      # User-Agent \u306e\u691c\u8a3c\n      unless session[:user_agent] == request.user_agent\n        reset_session\n        redirect_to login_path, alert: '\u30bb\u30c3\u30b7\u30e7\u30f3\u304c\u7121\u52b9\u306b\u306a\u308a\u307e\u3057\u305f'\n      end\n\n      # \u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u6709\u52b9\u671f\u9650\u30c1\u30a7\u30c3\u30af\n      if session[:last_seen_at] &lt; 30.minutes.ago\n        reset_session\n        redirect_to login_path, alert: '\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u6709\u52b9\u671f\u9650\u304c\u5207\u308c\u307e\u3057\u305f'\n      end\n    end\n  end\n\n  def update_session_activity\n    session[:last_seen_at] = Time.current if user_signed_in?\n  end\nend<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-14\">\u30ed\u30b0\u30a2\u30a6\u30c8\u6a5f\u80fd\u306e\u5b9f\u88c5<\/h3>\n\n\n\n<p>\u5b89\u5168\u306a\u30ed\u30b0\u30a2\u30a6\u30c8\u51e6\u7406\u306e\u5b9f\u88c5\u65b9\u6cd5\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u57fa\u672c\u7684\u306a\u30ed\u30b0\u30a2\u30a6\u30c8\u6a5f\u80fd<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># app\/controllers\/sessions_controller.rb\ndef destroy\n  # \u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u5b8c\u5168\u306a\u524a\u9664\n  reset_session\n  # \u30aa\u30d7\u30b7\u30e7\u30f3\uff1a\u30ed\u30b0\u30a2\u30a6\u30c8\u6642\u523b\u306e\u8a18\u9332\n  current_user&amp;.update(last_sign_out_at: Time.current)\n  redirect_to root_path, notice: '\u30ed\u30b0\u30a2\u30a6\u30c8\u3057\u307e\u3057\u305f'\nend<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>\u9ad8\u5ea6\u306a\u30ed\u30b0\u30a2\u30a6\u30c8\u6a5f\u80fd\u306e\u5b9f\u88c5<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># app\/models\/user.rb\nclass User &lt; ApplicationRecord\n  has_many :active_sessions, dependent: :destroy\n\n  def invalidate_all_sessions!\n    active_sessions.destroy_all\n    update(session_version: session_version + 1)\n  end\nend\n\n# app\/controllers\/concerns\/session_management.rb\nmodule SessionManagement\n  extend ActiveSupport::Concern\n\n  included do\n    before_action :verify_session_version\n  end\n\n  private\n\n  def verify_session_version\n    if session[:user_id].present? &amp;&amp; current_user\n      stored_version = session[:session_version]\n      if stored_version != current_user.session_version\n        reset_session\n        redirect_to login_path, alert: '\u4ed6\u306e\u5834\u6240\u3067\u30ed\u30b0\u30a2\u30a6\u30c8\u3055\u308c\u307e\u3057\u305f'\n      end\n    end\n  end\n\n  def create_user_session(user)\n    reset_session\n    session[:user_id] = user.id\n    session[:session_version] = user.session_version\n    ActiveSession.create!(\n      user: user,\n      ip_address: request.remote_ip,\n      user_agent: request.user_agent\n    )\n  end\nend<\/pre>\n\n\n\n<p>\u5b9f\u88c5\u6642\u306e\u91cd\u8981\u306a\u30dd\u30a4\u30f3\u30c8\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u5bfe\u7b56<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u30d5\u30a3\u30af\u30bb\u30fc\u30b7\u30e7\u30f3\u5bfe\u7b56<\/li>\n\n\n\n<li>CSRF\u5bfe\u7b56\u306e\u5b9f\u88c5<\/li>\n\n\n\n<li>\u9069\u5207\u306a\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8\u8a2d\u5b9a<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30e6\u30fc\u30b6\u30fc\u30a8\u30af\u30b9\u30da\u30ea\u30a8\u30f3\u30b9<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30a8\u30e9\u30fc\u30e1\u30c3\u30bb\u30fc\u30b8\u306e\u9069\u5207\u306a\u8868\u793a<\/li>\n\n\n\n<li>\u30ea\u30c0\u30a4\u30ec\u30af\u30c8\u5148\u306e\u9069\u5207\u306a\u8a2d\u5b9a<\/li>\n\n\n\n<li>\u30ed\u30b0\u30a4\u30f3\u72b6\u614b\u306e\u7dad\u6301\uff08Remember Me\u6a5f\u80fd\uff09<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30c7\u30d0\u30c3\u30b0\u3068\u30c8\u30e9\u30d6\u30eb\u30b7\u30e5\u30fc\u30c6\u30a3\u30f3\u30b0<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30ed\u30b0\u306e\u9069\u5207\u306a\u8a18\u9332<\/li>\n\n\n\n<li>\u30a8\u30e9\u30fc\u30cf\u30f3\u30c9\u30ea\u30f3\u30b0<\/li>\n\n\n\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u72b6\u614b\u306e\u76e3\u8996<\/li>\n<\/ul>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u5b9f\u88c5\u306b\u3088\u308a\u3001\u30bb\u30ad\u30e5\u30a2\u3067\u4f7f\u3044\u3084\u3059\u3044\u8a8d\u8a3c\u30b7\u30b9\u30c6\u30e0\u3092\u69cb\u7bc9\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-15\">\u30bb\u30c3\u30b7\u30e7\u30f3\u7ba1\u7406\u306e\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u5bfe\u7b56<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-16\">\u4e00\u822c\u7684\u306a\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u30ea\u30b9\u30af\u3068\u5bfe\u7b56<\/h3>\n\n\n\n<p>Rails\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u306b\u304a\u3051\u308b\u30bb\u30c3\u30b7\u30e7\u30f3\u7ba1\u7406\u3067\u306e\u4e3b\u8981\u306a\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u30ea\u30b9\u30af\u3068\u305d\u306e\u5bfe\u7b56\u306b\u3064\u3044\u3066\u89e3\u8aac\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u30d5\u30a3\u30af\u30bb\u30fc\u30b7\u30e7\u30f3\u5bfe\u7b56<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># app\/controllers\/application_controller.rb\nclass ApplicationController &lt; ActionController::Base\n  before_action :ensure_session_security\n\n  private\n\n  def ensure_session_security\n    # \u30ed\u30b0\u30a4\u30f3\u6642\u306b\u5fc5\u305a\u65b0\u3057\u3044\u30bb\u30c3\u30b7\u30e7\u30f3\u3092\u751f\u6210\n    if session[:created_at].nil?\n      reset_session\n      session[:created_at] = Time.current\n    end\n\n    # \u5b9a\u671f\u7684\u306a\u30bb\u30c3\u30b7\u30e7\u30f3\u30ed\u30fc\u30c6\u30fc\u30b7\u30e7\u30f3\n    if session[:rotated_at].nil? || session[:rotated_at] &lt; 1.hour.ago\n      rotate_session\n    end\n  end\n\n  def rotate_session\n    old_session = session.to_h\n    reset_session\n    session.update(old_session)\n    session[:rotated_at] = Time.current\n  end\nend<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8\u306e\u5b9f\u88c5<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># app\/controllers\/concerns\/session_timeout.rb\nmodule SessionTimeout\n  extend ActiveSupport::Concern\n\n  included do\n    before_action :check_session_timeout\n  end\n\n  private\n\n  def check_session_timeout\n    return unless session[:last_activity]\n\n    if session_expired?\n      reset_session\n      redirect_to login_path, alert: '\u30bb\u30c3\u30b7\u30e7\u30f3\u304c\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8\u3057\u307e\u3057\u305f'\n    else\n      session[:last_activity] = Time.current\n    end\n  end\n\n  def session_expired?\n    session[:last_activity] &lt; 30.minutes.ago\n  end\nend<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-17\">\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u6697\u53f7\u5316\u3068\u4fdd\u8b77<\/h3>\n\n\n\n<p>\u30bb\u30c3\u30b7\u30e7\u30f3\u30c7\u30fc\u30bf\u3092\u5b89\u5168\u306b\u4fdd\u8b77\u3059\u308b\u305f\u3081\u306e\u5b9f\u88c5\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u306e\u6697\u53f7\u5316\u8a2d\u5b9a<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># config\/initializers\/session_store.rb\nRails.application.config.session_store :cookie_store, {\n  key: '_app_session',\n  secure: Rails.env.production?,\n  expire_after: 12.hours,\n  same_site: :strict,\n  httponly: true,\n  secret: ENV['SESSION_SECRET_KEY']\n}\n\n# \u6697\u53f7\u5316\u30ad\u30fc\u306e\u30ed\u30fc\u30c6\u30fc\u30b7\u30e7\u30f3\nRails.application.config.action_dispatch.encrypted_cookie_salt = ENV['COOKIE_SALT']\nRails.application.config.action_dispatch.encrypted_signed_cookie_salt = ENV['SIGNED_COOKIE_SALT']<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>\u6a5f\u5bc6\u30c7\u30fc\u30bf\u306e\u4fdd\u8b77<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># app\/controllers\/concerns\/sensitive_data_protection.rb\nmodule SensitiveDataProtection\n  extend ActiveSupport::Concern\n\n  private\n\n  def store_sensitive_data(key, value)\n    # \u6a5f\u5bc6\u30c7\u30fc\u30bf\u306e\u6697\u53f7\u5316\n    encrypted_data = encrypt_data(value)\n    session[key] = encrypted_data\n  end\n\n  def retrieve_sensitive_data(key)\n    return nil unless session[key]\n    decrypt_data(session[key])\n  end\n\n  def encrypt_data(data)\n    cipher = OpenSSL::Cipher.new('AES-256-GCM')\n    cipher.encrypt\n    cipher.key = ENV['DATA_ENCRYPTION_KEY']\n    iv = cipher.random_iv\n    cipher.auth_data = \"\"\n    encrypted = cipher.update(data.to_json) + cipher.final\n    tag = cipher.auth_tag\n    Base64.strict_encode64([encrypted, iv, tag].pack('m*m*m*'))\n  end\n\n  def decrypt_data(encrypted_data)\n    encrypted, iv, tag = Base64.strict_decode64(encrypted_data).unpack('m*m*m*')\n    decipher = OpenSSL::Cipher.new('AES-256-GCM')\n    decipher.decrypt\n    decipher.key = ENV['DATA_ENCRYPTION_KEY']\n    decipher.iv = iv\n    decipher.auth_tag = tag\n    decipher.auth_data = \"\"\n    JSON.parse(decipher.update(encrypted) + decipher.final)\n  end\nend<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-18\">CSRF\u304b\u3089\u306e\u9632\u5fa1\u65b9\u6cd5<\/h3>\n\n\n\n<p>CSRF\u30a2\u30bf\u30c3\u30af\u304b\u3089\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3092\u4fdd\u8b77\u3059\u308b\u5b9f\u88c5\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>CSRF\u5bfe\u7b56\u306e\u57fa\u672c\u8a2d\u5b9a<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># app\/controllers\/application_controller.rb\nclass ApplicationController &lt; ActionController::Base\n  protect_from_forgery with: :exception\n\n  # CSRF\u30c8\u30fc\u30af\u30f3\u306e\u691c\u8a3c\u3092\u53b3\u683c\u5316\n  before_action :verify_same_origin_request\n\n  private\n\n  def verify_same_origin_request\n    if request.headers['X-Requested-With'] != 'XMLHttpRequest'\n      raise ActionController::InvalidAuthenticityToken unless valid_authenticity_token?(session, form_authenticity_param)\n    end\n  end\nend<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>API\u30a8\u30f3\u30c9\u30dd\u30a4\u30f3\u30c8\u3067\u306eCSRF\u4fdd\u8b77<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># app\/controllers\/api\/base_controller.rb\nmodule Api\n  class BaseController &lt; ApplicationController\n    protect_from_forgery with: :null_session\n    before_action :verify_api_token\n\n    private\n\n    def verify_api_token\n      unless valid_api_token?\n        render json: { error: '\u7121\u52b9\u306aAPI\u30c8\u30fc\u30af\u30f3' }, status: :unauthorized\n      end\n    end\n\n    def valid_api_token?\n      request.headers['X-API-Token'] == session[:api_token]\n    end\n  end\nend<\/pre>\n\n\n\n<p>\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u5b9f\u88c5\u306e\u30d9\u30b9\u30c8\u30d7\u30e9\u30af\u30c6\u30a3\u30b9\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u8a2d\u5b9a<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u9069\u5207\u306a\u30bb\u30c3\u30b7\u30e7\u30f3\u6709\u52b9\u671f\u9650\u306e\u8a2d\u5b9a<\/li>\n\n\n\n<li>\u30bb\u30ad\u30e5\u30a2\u306a\u30af\u30c3\u30ad\u30fc\u8a2d\u5b9a\u306e\u4f7f\u7528<\/li>\n\n\n\n<li>\u9069\u5207\u306a\u30c9\u30e1\u30a4\u30f3\u5236\u9650\u306e\u8a2d\u5b9a<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30c7\u30fc\u30bf\u4fdd\u8b77<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u6a5f\u5bc6\u60c5\u5831\u306e\u6697\u53f7\u5316<\/li>\n\n\n\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u30c7\u30fc\u30bf\u306e\u6700\u5c0f\u5316<\/li>\n\n\n\n<li>\u9069\u5207\u306a\u30a2\u30af\u30bb\u30b9\u5236\u5fa1<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30e2\u30cb\u30bf\u30ea\u30f3\u30b0\u3068\u76e3\u67fb<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u30a2\u30af\u30c6\u30a3\u30d3\u30c6\u30a3\u306e\u30ed\u30b0\u8a18\u9332<\/li>\n\n\n\n<li>\u4e0d\u6b63\u30a2\u30af\u30bb\u30b9\u306e\u691c\u77e5<\/li>\n\n\n\n<li>\u5b9a\u671f\u7684\u306a\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u76e3\u67fb<\/li>\n<\/ul>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u5bfe\u7b56\u3092\u9069\u5207\u306b\u5b9f\u88c5\u3059\u308b\u3053\u3068\u3067\u3001\u30bb\u30ad\u30e5\u30a2\u306a\u30bb\u30c3\u30b7\u30e7\u30f3\u7ba1\u7406\u3092\u5b9f\u73fe\u3067\u304d\u307e\u3059\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-19\">\u30bb\u30c3\u30b7\u30e7\u30f3\u7ba1\u7406\u306e\u30c8\u30e9\u30d6\u30eb\u30b7\u30e5\u30fc\u30c6\u30a3\u30f3\u30b0<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-20\">\u3088\u304f\u3042\u308b\u30a8\u30e9\u30fc\u3068\u89e3\u6c7a\u65b9\u6cd5<\/h3>\n\n\n\n<p>Rails\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u3067\u306e\u30bb\u30c3\u30b7\u30e7\u30f3\u7ba1\u7406\u306b\u304a\u3044\u3066\u906d\u9047\u3059\u308b\u4e00\u822c\u7684\u306a\u554f\u984c\u3068\u305d\u306e\u89e3\u6c7a\u65b9\u6cd5\u3092\u89e3\u8aac\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u304c\u4e88\u671f\u305b\u305a\u5931\u52b9\u3059\u308b\u554f\u984c<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># config\/initializers\/session_store.rb\n# \u30bb\u30c3\u30b7\u30e7\u30f3\u30b9\u30c8\u30a2\u306e\u8a2d\u5b9a\u3092\u78ba\u8a8d\nRails.application.config.session_store :cookie_store, {\n  key: '_app_session',\n  expire_after: 24.hours,\n  secure: Rails.env.production?,\n  same_site: :lax\n}\n\n# app\/controllers\/application_controller.rb\nclass ApplicationController &lt; ActionController::Base\n  # \u30bb\u30c3\u30b7\u30e7\u30f3\u72b6\u614b\u3092\u30ed\u30b0\u306b\u8a18\u9332\n  before_action :log_session_state\n\n  private\n\n  def log_session_state\n    Rails.logger.debug \"Session ID: #{session.id}\"\n    Rails.logger.debug \"Session Data: #{session.to_h}\"\n    Rails.logger.debug \"Cookie Data: #{cookies.to_h}\"\n  end\nend<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u30c7\u30fc\u30bf\u306e\u6574\u5408\u6027\u30a8\u30e9\u30fc<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># app\/controllers\/concerns\/session_recovery.rb\nmodule SessionRecovery\n  extend ActiveSupport::Concern\n\n  included do\n    rescue_from ActionDispatch::Session::SessionError, with: :handle_session_error\n  end\n\n  private\n\n  def handle_session_error(exception)\n    Rails.logger.error \"\u30bb\u30c3\u30b7\u30e7\u30f3\u30a8\u30e9\u30fc: #{exception.message}\"\n    reset_session\n    redirect_to root_path, alert: '\u30bb\u30c3\u30b7\u30e7\u30f3\u3092\u30ea\u30bb\u30c3\u30c8\u3057\u307e\u3057\u305f'\n  end\n\n  def verify_session_integrity\n    if session[:user_id] &amp;&amp; !User.exists?(session[:user_id])\n      reset_session\n      redirect_to login_path, alert: '\u30bb\u30c3\u30b7\u30e7\u30f3\u304c\u7121\u52b9\u306b\u306a\u308a\u307e\u3057\u305f'\n    end\n  end\nend<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-21\">\u30c7\u30d0\u30c3\u30b0\u306e\u65b9\u6cd5\u3068\u30c4\u30fc\u30eb<\/h3>\n\n\n\n<p>\u30bb\u30c3\u30b7\u30e7\u30f3\u95a2\u9023\u306e\u554f\u984c\u3092\u30c7\u30d0\u30c3\u30b0\u3059\u308b\u305f\u3081\u306e\u30c6\u30af\u30cb\u30c3\u30af\u3068\u30c4\u30fc\u30eb\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30c7\u30d0\u30c3\u30b0\u7528\u30d8\u30eb\u30d1\u30fc\u306e\u5b9f\u88c5<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># app\/helpers\/session_debug_helper.rb\nmodule SessionDebugHelper\n  def debug_session_info\n    return unless Rails.env.development?\n\n    content_tag :div, class: 'debug-info' do\n      content_tag :pre do\n        [\n          \"Session ID: #{session.id}\",\n          \"Session Data: #{session.to_h}\",\n          \"Session Options: #{session.options}\",\n          \"Cookie Data: #{cookies.to_h}\"\n        ].join(\"\\n\")\n      end\n    end\n  end\nend<\/pre>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u30e2\u30cb\u30bf\u30ea\u30f3\u30b0<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># config\/initializers\/session_monitoring.rb\nmodule SessionMonitoring\n  class SessionSubscriber &lt; ActiveSupport::LogSubscriber\n    def session_accessed(event)\n      return unless logger.debug?\n\n      debug \"  Session accessed: #{event.payload[:key]}\"\n      debug \"  Duration: #{event.duration.round(1)}ms\"\n    end\n\n    def session_stored(event)\n      return unless logger.debug?\n\n      debug \"  Session stored: #{event.payload[:key]}\"\n      debug \"  Size: #{event.payload[:size]} bytes\"\n    end\n  end\nend\n\nSessionMonitoring::SessionSubscriber.attach_to :action_controller<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"i-22\">\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u6700\u9069\u5316\u306e\u30dd\u30a4\u30f3\u30c8<\/h3>\n\n\n\n<p>\u30bb\u30c3\u30b7\u30e7\u30f3\u7ba1\u7406\u306e\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u3092\u5411\u4e0a\u3055\u305b\u308b\u305f\u3081\u306e\u30dd\u30a4\u30f3\u30c8\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u30c7\u30fc\u30bf\u306e\u6700\u9069\u5316<\/li>\n<\/ol>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\"># app\/controllers\/concerns\/session_optimization.rb\nmodule SessionOptimization\n  extend ActiveSupport::Concern\n\n  private\n\n  def optimize_session_data\n    # \u5927\u304d\u306a\u30c7\u30fc\u30bf\u306e\u5727\u7e2e\n    if session[:large_data].present? &amp;&amp; session[:large_data].size &gt; 1.kilobyte\n      session[:large_data] = compress_session_data(session[:large_data])\n    end\n\n    # \u4e0d\u8981\u306a\u30c7\u30fc\u30bf\u306e\u524a\u9664\n    cleanup_temporary_session_data\n  end\n\n  def compress_session_data(data)\n    ActiveSupport::Gzip.compress(data.to_json)\n  end\n\n  def cleanup_temporary_session_data\n    session.keys.each do |key|\n      session.delete(key) if key.start_with?('temp_')\n    end\n  end\nend<\/pre>\n\n\n\n<p>\u30c8\u30e9\u30d6\u30eb\u30b7\u30e5\u30fc\u30c6\u30a3\u30f3\u30b0\u306e\u30c1\u30a7\u30c3\u30af\u30ea\u30b9\u30c8\uff1a<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u8a2d\u5b9a\u306e\u78ba\u8a8d<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u30b9\u30c8\u30a2\u306e\u8a2d\u5b9a<\/li>\n\n\n\n<li>\u30bf\u30a4\u30e0\u30a2\u30a6\u30c8\u8a2d\u5b9a<\/li>\n\n\n\n<li>\u30bb\u30ad\u30e5\u30ea\u30c6\u30a3\u8a2d\u5b9a<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30c7\u30fc\u30bf\u306e\u6574\u5408\u6027\u30c1\u30a7\u30c3\u30af<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u30c7\u30fc\u30bf\u306e\u691c\u8a3c<\/li>\n\n\n\n<li>\u30e6\u30fc\u30b6\u30fc\u8a8d\u8a3c\u72b6\u614b\u306e\u78ba\u8a8d<\/li>\n\n\n\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3ID\u306e\u691c\u8a3c<\/li>\n<\/ul>\n\n\n\n<ol class=\"wp-block-list\">\n<li>\u30d1\u30d5\u30a9\u30fc\u30de\u30f3\u30b9\u30e2\u30cb\u30bf\u30ea\u30f3\u30b0<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u30bb\u30c3\u30b7\u30e7\u30f3\u30b5\u30a4\u30ba\u306e\u76e3\u8996<\/li>\n\n\n\n<li>\u30a2\u30af\u30bb\u30b9\u983b\u5ea6\u306e\u5206\u6790<\/li>\n\n\n\n<li>\u30ec\u30b9\u30dd\u30f3\u30b9\u30bf\u30a4\u30e0\u306e\u8a08\u6e2c<\/li>\n<\/ul>\n\n\n\n<p>\u3053\u308c\u3089\u306e\u5bfe\u7b56\u3068\u30c4\u30fc\u30eb\u3092\u6d3b\u7528\u3059\u308b\u3053\u3068\u3067\u3001\u30bb\u30c3\u30b7\u30e7\u30f3\u95a2\u9023\u306e\u554f\u984c\u3092\u52b9\u679c\u7684\u306b\u7279\u5b9a\u3057\u89e3\u6c7a\u3067\u304d\u307e\u3059\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Warning: Undefined array key &#8220;is_admin&#8221; in \/home\/xs392991\/dexall.co.jp\/public_html\/articles\/wp-content\/themes\/ &#8230; <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":{"0":"post-1473","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-ruby","7":"nothumb"},"_links":{"self":[{"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts\/1473","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1473"}],"version-history":[{"count":1,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts\/1473\/revisions"}],"predecessor-version":[{"id":1474,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=\/wp\/v2\/posts\/1473\/revisions\/1474"}],"wp:attachment":[{"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1473"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1473"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dexall.co.jp\/articles\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1473"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}