2016-03-12 1 views
0

J'ai une application fonctionnant sur les rails, qui est un blog avec des commentaires et un vote haut/bas. Le composant mobile permet aux utilisateurs de se connecter/se déconnecter, de consulter les articles et de faire des conversions upvote/downvote, et de ne pas ajouter d'articles ou de commentaires à ce stade.Agit comme votable JSON put

J'ai mis en place la connexion JSON avec la gemme simple auth jeton et je peux obtenir les articles et leurs upvotes/downvotes qui travaillent tous, mais voici mon problème:

Comment puis-je publier les valeurs JSON retour? J'ai mon code json qui fonctionne dans Android pour afficher ou pousser les valeurs json mais comment puis-je construire la chaîne correcte pour repousser? Quels sont les paramètres corrects à remettre?

Merci beaucoup.

Ceci est des rails journal du serveur:

Le upvote html qui fonctionne:

Started PUT "/articles/5/like" for 137.147.172.125 at 2016-03-12 09:34:43 +0000 
Cannot render console from 137.147.172.125! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255 
Processing by ArticlesController#upvote as HTML 
    Parameters: {"authenticity_token"=>"4eC8xgC+1CBb51gKO7ZRzjL1BGOF6TYTnbqQcJ3evxvpmGcguYHBNYSn9v3LJMfoo3F29frntwzgyLoeI9oaLg==", "id"=>"5"} 
    User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]] 
    Article Load (0.1ms) SELECT "articles".* FROM "articles" WHERE "articles"."id" = ? ORDER BY "articles"."created_at" DESC LIMIT 1 [["id", 5]] 
    (0.3ms) SELECT COUNT(*) FROM "votes" WHERE "votes"."votable_id" = ? AND "votes"."votable_type" = ? AND "votes"."voter_id" = ? AND "votes"."voter_type" = ? AND "votes"."vote_scope" IS NULL [["votable_id", 5], ["votable_type", "Article"], ["voter_id", 1], ["voter_type", "User"]] 
    (0.2ms) begin transaction 
    SQL (0.6ms) INSERT INTO "votes" ("votable_id", "votable_type", "voter_id", "voter_type", "vote_flag", "vote_weight", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?, ?, ?, ?) [["votable_id", 5], ["votable_type", "Article"], ["voter_id", 1], ["voter_type", "User"], ["vote_flag", "t"], ["vote_weight", 1], ["created_at", "2016-03-12 09:34:43.393685"], ["updated_at", "2016-03-12 09:34:43.393685"]] 
    (11.4ms) commit transaction 
Redirected to https://completerubyonrailscourse-adam1st.c9users.io/articles/5 
Completed 302 Found in 187ms (ActiveRecord: 13.2ms) 

C'est quand mon code Android tente de pousser les données JSON au serveur rails:

Started PUT "/articles/5/like" for 49.199.131.149 at 2016-03-12 10:20:16 +0000 
Cannot render console from 49.199.131.149! Allowed networks: 127.0.0.1, ::1, 127.0.0.0/127.255.255.255 
Processing by ArticlesController#upvote as JSON 
    Parameters: {"votes"=>{"votable_id"=>"5", "votable_type"=>"Article", "voter_id"=>"1", "voter_type"=>"User", "vote_flag"=>"t", "vote_weight"=>"1", "created_at"=>"2016-03-12 21:20:13.679000", "updated_at"=>"2016-03-12 21:20:13.679000"}, "id"=>"5", "article"=>{}} 
Can't verify CSRF token authenticity 
Completed 401 Unauthorized in 2ms (ActiveRecord: 0.0ms) 

Alors, comment puis-je obtenir cela dans les données json? Parameters:{"authenticity_token"=>"4eC8xgC+1CBb51gKO7ZRzjL1BGOF6TYTnbqQcJ3evxvpmGcguYHBNYSn9v3LJMfoo3F29frntwzgyLoeI9oaLg==", "id"=>"5"}

À partir du contrôleur d'articles:

before_action :authenticate_user!, :except => [:index, :show] 
before_filter :set_article, only: [:show, :edit, :update, :destroy, :upvote, :downvote] 
. 
. 
.  
def upvote 
     @article.upvote_by current_user 
     flash[:success] = "Successfully liked" 
     respond_to do |format| 
      format.html {redirect_to :back } 
      format.json { render json: { count: @article.liked_count } } 
     end 
     end 
     def downvote 
     @article.downvote_by current_user 
     flash[:success] = "Successfully disliked" 
     respond_to do |format| 
      format.html {redirect_to :back } 
      format.json { render json: { count: @article.disliked_count } } 
     end 
     end 

De l'show.html.erb qui concerne le vote:

<%= link_to like_article_path(@article), method: :put, class: 'voting' do %> 
    <i class="fa fa-thumbs-up"></i> 
    <%= @article.get_upvotes.size %> 
<% end %> 
<%= link_to dislike_article_path(@article), method: :put, class: 'voting' do %> 
    <i class="fa fa-thumbs-down"></i> 
    <%= @article.get_downvotes.size %> 
<% end %> 

code Android PUT (certaines valeurs codées en dur pour les tests):

private class VoteTask extends UrlJsonAsyncTask { 
     public VoteTask(Context context) { 
      super(context); 
     } 

     @Override 
     protected JSONObject doInBackground(String... urls) { 
      HttpClient client = new DefaultHttpClient(); 
      HttpPut put = new HttpPut(urls[0]); 
      JSONObject holder = new JSONObject(); 
      JSONObject voteObj = new JSONObject(); 
      String response = null; 
      JSONObject json = new JSONObject(); 

      try { 
       try { 
        // setup the returned values in case 
        // something goes wrong 
        json.put("success", false); 
        json.put("info", "Something went wrong. Retry!"); 
        // add the user email and password to 
        // the params 
        voteObj.put("votable_id",articleId); 
        voteObj.put("votable_type", "Article"); 
        voteObj.put("voter_id", "1"); 
        voteObj.put("voter_type", "User"); 
        voteObj.put("vote_flag", "t"); 
        voteObj.put("vote_weight", "1"); 
        voteObj.put("created_at", strDate); 
        voteObj.put("updated_at", strDate); 
        holder.put("votes", voteObj); 
        StringEntity se = new StringEntity(holder.toString()); 
        put.setEntity(se); 

        // setup the request headers 
        put.setHeader("Accept", "application/json"); 
        put.setHeader("Content-Type", "application/json"); 

        response = String.valueOf(client.execute(put)); 
        json = new JSONObject(response); 

       } catch (IOException e) { 
        e.printStackTrace(); 
        Log.e("IO", "" + e); 
       } 
      } catch (JSONException e) { 
       e.printStackTrace(); 
       Log.e("JSON", "" + e); 
      } 

      return json; 
     } 

Répondre

0

Je suis allé à l'git d'authentification par jeton simple https://github.com/gonzalo-bulnes/simple_token_authentication et vu cela.

Méthode d'authentification 2: Demande d'en-têtes

Vous pouvez également utiliser les en-têtes de demande (ce qui peut être plus simple lors de l'authentification contre une API):

X-utilisateur Email [email protected]

X-User-Token 1G8_s7P-V-4MGojaKD7a

alors j'ai mis cela dans ma tâche de vote dans les en-têtes avant d'effectuer mon vote et cela a fonctionné.

private class VoteTask extends UrlJsonAsyncTask { 
     public VoteTask(Context context) { 
      super(context); 
     } 

     @Override 
     protected JSONObject doInBackground(String... urls) { 
      DefaultHttpClient webClient = new DefaultHttpClient(); 
      HttpPut put = new HttpPut(urls[0]); 
      JSONObject holder = new JSONObject(); 
      JSONObject voteObj = new JSONObject(); 
      String response = null; 
      JSONObject json = new JSONObject(); 

      try { 
       try { 
        // setup the returned values in case 
        // something goes wrong 
        json.put("success", false); 
        json.put("info", "Something went wrong. Retry!"); 

        //get stored values to prove the user is authorised 
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); 
        String id = sharedPreferences.getString("userId", "default value"); 
        String authToken = sharedPreferences.getString("AuthToken", "default value"); 
        String email = sharedPreferences.getString("email", "default value"); 

        voteObj.put("votable_id",articleId); 
        voteObj.put("votable_type", "Article"); 
        voteObj.put("voter_id", id); 
        voteObj.put("voter_type", "User"); 
        voteObj.put("vote_flag", voteFlag); 
        voteObj.put("vote_weight", "1"); 
        holder.put("votes", voteObj); 
        holder.put("article", articleId); 
        StringEntity se = new StringEntity(holder.toString()); 
        put.setEntity(se); 

        // setup the request headers 
        put.setHeader("Accept", "application/json"); 
        put.setHeader("Content-Type", "application/json"); 
        // add email and auth token to validate 
        put.setHeader("X-User-Email", email); 
        put.setHeader("X-User-Token", authToken); 

        //response = webClient.execute(put); 
        //json = new JSONObject(response); 
        response = String.valueOf(webClient.execute(put)); 
        json = new JSONObject(response); 


       } catch (HttpResponseException e) { 
        e.printStackTrace(); 
        Log.e("ClientProtocol", "" + e); 
        json.put("info", "Email and/or password are invalid. Retry!"); 
       } catch (IOException e) { 
        e.printStackTrace(); 
        Log.e("IO", "" + e); 
       } 
      } catch (JSONException e) { 
       e.printStackTrace(); 
       Log.e("JSON", "" + e); 
      } 

      return json; 
     } 
0

Ajoutez ceci dans votre application_controller.rb fichier

protect_from_forgery with: :null_session, if: Proc.new { |c| c.request.format == 'application/json' } 
+0

Merci, mais je reçois toujours le même problème: ne peut pas vérifier l'authenticité jeton CSRF Terminé 401 non autorisé à 2ms (ActiveRecord: 0.0ms) Pouvez-vous expliquer un peu plus loin? –