質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby on Rails 4

Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

Q&A

解決済

1回答

2120閲覧

どうしてもsessionを使ったコメントの作成方法がうまく実装できない

NaojirouHisada

総合スコア60

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

Ruby on Rails 4

Ruby on Rails4はRubyによって書かれたオープンソースのウェブフレームワークです。 Ruby on Railsは「設定より規約」の原則に従っており、効率的に作業を行うために再開発を行う必要をなくしてくれます。

0グッド

0クリップ

投稿2016/05/16 16:37

編集2016/05/17 02:35

###やりたいこと
現在Facebookのようなアプリを作成中です。
コメントの表示・投稿・保存の機能は既に実装していますが、
現在hiddenフィールドを使用してるので、セキュリティー
を考えてsessionによる外部キーの値の挿入を行いたい。

###具体的にやりたいこと
_comment.html.erbで現在は、
hideenに @micropost.id を入れて、
Comment.createメソッドに送信して、
どの記事に対するコメントなのか識別していますが、
この 個々の@micropost.id をsessionを使ってComment.createメソッドに値を引き回し、
どの記事に対するコメントなのか識別したいです。

現状@micropostIds = Micropost.where(user_id: @user.id).select(:id)
でユーザに属する記事の一覧は取得できるのですが、
それをコメント記事が送信された際に、
どの記事に対するコメントなのか識別できないのに、困っております。
###背景
ネットの記事やある講師から、
hiddenフィールドはセキュリティー上良くないため、あまり使わないよう言われていた。
その際、sessionを使った方法をするとよいと書かれていました。
そのため、sessionを使用しようと思いました。
###問題点
コントローラ内で、
記事の複数のIdを取得することができたので、
可逆方式を使って暗号化し、
hiddenに入れてかつ、validationを試みましたが、
どうしても特定の値をcommentコントローラに渡せません。

Railsガイドや、
他のsession使用のサイトを見たのですが、
どれもユーザのように1つしかないもののsessionの使い方ばかりで、
記事のように複数の中から特定のものを持ってくるのはありませんでした。

また、
Ruby on Rails4アプリケーションプログラミングの本を読み返して、
試行錯誤したのですが、
結局2週間経っても
未だに解決できません(^^;)

###ソースコード
コメントの投稿フォームはshow.html.erbにレンダーする形で表示します。

show.html.er <%= @user.first_kanji%> <%= link_to '基本情報編集' ,edit_user_path(@user) %> <%= render 'follow_form' if logged_in? %> <hr /> <% if @user.microposts.any? %> <%= render partial: 'microposts/micropost', collection: @microposts %> <% end %>
class UsersController < ApplicationController before_action :set_user, only: [:show , :edit , :update ] def show @user = User.find(params[:id]) session[:other_user_id] = nil @microposts = @user.microposts @comments = @user.comments.build @micropostIds = Micropost.where(user_id: @user.id).select(:id) session[:micropost] = @micropostIds @replay = Replay.new if current_user.follower_relationships.any? if @user.id == current_user.id @follower_relationships = current_user.follower_relationships.find_by( params[:followed_id] == current_user.id) else @follower_relationships = current_user.follower_relationships.find_by(params[:follow_id] == @user.id , params[:followed_id] == current_user.id) end end if current_user.following_relationships.any? if @user.id == current_user.id @following_relationships = current_user.following_relationships.find_by(params[:follow_id] == current_user.id ) else @following_relationships = current_user.following_relationships.find_by(params[:follow_id] == current_user.id , params[:followed_id] == @user.id ) end end end
comments.controller.rb class CommentsController < ApplicationController before_action :logged_in_user def create @user = User.find(params[:user_id]) @micropost = Micropost.find(params[:micropost_id]) @comment = current_user.comments.build(comment_params) @comment.micropost = @micropost if @comment.save @succeed = true else flash[:danger] = 'missing' end end private def comment_params params.require(:comment).permit(:content) end end
_micropost.html.erb <div id="micropost<%=micropost.id %>"> <% @micropost = micropost %> <p><%= micropost.user.first_kanji %> <%= micropost.user.last_kanji %>さん<br /> <%= micropost.content %> <% if current_user.following?(@user) && @following_relationships.status == 1 || current_user.follower?(@user) && @follower_relationships.status == 1 %> <%= render partial:'shared/comment_form' , locals:{comments: @micropost.comments} %> <% end %> <div id="comments<%=micropost.id %>"> <%= render partial: 'comments/comment' ,collection: @micropost.comments %> </div> <%- if current_user == micropost.user %> <%= link_to "削除", micropost , method: :delete , data:{confirm: "削除してよろしいですか?"} %> <% end %> </div> <hr />
_comment_form.html.erb <%= form_for(@comments,remote: true) do |f| %> <%= f.text_field :content , class: "comment_field" %> <%= hidden_field_tag :micropost_id , @micropost.id %> <%= hidden_field_tag :user_id , current_user.id %> <%= f.submit 'コメントする' %> <% end %>

このような場合、
javascript等で送信時に値を設定するみたいなことを
するのでしょか??

お手数おかけしますが、
アドバイス宜しくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

rifuch

2016/05/16 23:40

すみませんが、例示されたソースで言うと、どの値の引き回しで困っているのでしょうか? 具体的に教えてください。
guest

回答1

0

ベストアンサー

根本的な問題点は、なぜhidden_field(パラメータで渡す)のがセキュリティ上好ましくなく、sessionを使うべきなのか、という事だと思います。
hidden_fieldを利用する(パラメータで渡す)場合、渡す値を改竄される可能性があるためかと思います。
で、秘匿したかったり、改竄されたくない情報は、あらかじめsessionに入れておいて、その値を利用すれば、1回のリクエストでは改竄不可能なので、セキュリティが高まるよね、という事だと思うんです。

行われている事は、ログインしているuserが閲覧可能なmicropostを取得し、その一つに対してcommentをpostする、という事だと思います。

この場合、commentを投稿する対象のmicropostのidは、事前にわかっている訳ではないので、あらかじめsessionに格納は出来ません。
micropost.idはパラメータで渡すしかないのですが、これそのものは問題ではないと思います。
micropostを閲覧できるか、あるいはコメントを投稿できるかのチェックは、ログインしているユーザーによって判別してフィルタリングすれば良いからです。

例示されたコードもそのようにしているようで、
CommentControllerのlogged_in_userですでに確定しているcurrent_userのcommentsとして処理されています。
(hidden_fieldのuser_idは使われてないですよね?CommentsController::createで取得した@userはどこにも使われてないかと)
こうしておけば、仮に閲覧権限やコメント投稿権限がないmicropostのIDを渡されたとしても、事前にフィルタリングして防御が可能です。

私だったら、こんな感じで書くでしょうか。

Ruby

1_comment_form.html.erb 2<%= form_for(@comments,remote: true) do |f| %> 3 <%= f.text_field :content , class: "comment_field" %> 4 <%= f.hidden_field :micropost_id , @micropost.id %> 5 <%= f.submit 'コメントする' %> 6<% end %> 7 8comments.controller.rb 9class CommentsController < ApplicationController 10 before_action :logged_in_user 11 12 def create 13 @comment = current_user.comments.build(comment_params) 14 if @comment.save 15 @succeed = true 16 else 17 flash[:danger] = 'missing' 18 end 19 end 20 21 private 22 def comment_params 23 params.require(:comment).permit(:content, :micropost_id) 24 end 25end

投稿2016/05/17 03:20

rifuch

総合スコア1901

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

NaojirouHisada

2016/05/17 06:26

rifuchさんアドバイスありがとうございます。 hiddenではなくsessionを選択する理由および、行おうとしていることはrifuchさんが言われた通りのことを考えておりました。 なるほど、そこは盲点でした! たとえば、友達管理のテーブルが存在した場合、 友達管理のidでフィルタリングかけるようにすれば、 悪意あるユーザは投稿できないようになるわけですね! はい! 実際にはユーザIDをhiddenにはいれません。 記述ミスです(^^;) 丁寧なアドバイスありがとうございます!! rifuchさんのアドバイスで浮かんだ疑問なのですが、 hiddenを改ざんされ他のユーザへの記事に投稿される対策はわかったのですが、 hiddenを同一ユーザの別の記事にコメントされるのを避けたい場合は、 さらに記事の内容をパラメータとして送信し、検証するという感じなのでしょうか?
rifuch

2016/05/17 09:11

記事毎に権限設定があるのであれば、micropost_idから取得したmicropostインスタンスに対して権限を問い合わせるような設計が良さそうです。 micropostモデルクラスに、権限ありなしを判別するメソッドを入れる感じでしょうか。 @micropost.commentable?(current_user) みたいな。 あるいはいっそのこと、micropostクラスにadd_comment(params, author)みたいなメソッドを定義してあげて、権限チェックと合わせてcommentを追加するとか。 ただ、このやり方だとmicropostコントローラが肥大化する懸念はありますね。
NaojirouHisada

2016/05/17 09:49

丁寧な説明ありがとうございます! rifuchさんの意見を参考に判別メソッドなどの工夫をして、 同一ユーザの別の記事にコメントを避けるようにしてみます! まだまだ力不足なため、 質問することがあると思いますが、 その際はまたよろしくお願いします。(^^) 本当にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問