J'essaie de donner aux utilisateurs de mon site Web des "points" ou des "crédits" pour avoir tweeté sur le nom de la marque.
J'ai le widget Twitter de fantaisie sur la vue appropriée ...
<p><a href="https://Twitter.com/share" class="Twitter-share-button" data-text="Check Out This Awesome Website Yay" data-via="BrandName" data-hashtags="ProductName">Tweet</a>
<div id="credited"></div>
<script>window.twttr = (function (d, s, id) {
var t, js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src= "https://platform.Twitter.com/widgets.js";
fjs.parentNode.insertBefore(js, fjs);
return window.twttr || (t = { _e: [], ready: function (f) { t._e.Push(f) } });
}(document, "script", "Twitter-wjs"));
</script>
J'ai le JS tout écrit et joli ...
function creditTweet() {
$.post(
"/credit_Tweet",
{},
function(result) {
var text;
if (result.status === "noop") {
text = "Thanks for sharing already!";
} else if (result.status === "ok") {
text = "5 Kredit Added";
}
$("#credited").html(text);
}
);
}
$(function() {
twttr.ready(function (twttr) {
window.twttr.events.bind('Tweet', creditTweet);
});
});
Maintenant, le problème est soit dans le contrôleur OR dans les routes (où je poste). Je pense que les routes sont très bien parce que le POST fonctionne presque) , car il s'agit de la description de l'erreur sur wikipedia - "422 Unprocessable Entity (WebDAV; RFC 4918) La demande était bien formée mais n'a pas pu être suivie en raison d'erreurs sémantiques."
Alors, voyez-vous quelque chose de mal avec mon code Ruby dans le contrôleur?
class SocialKreditController < ApplicationController
Tweet_CREDIT_AMOUNT = 5
def credit_Tweet
if !signed_in?
render json: { status: :error }
elsif current_user.Tweet_credited
Rails.logger.info "Not crediting #{ current_user.id }"
render json: { status: :noop }
else
Rails.logger.info "Crediting #{ current_user.id }"
current_user.update_attributes Tweet_credited: true
current_user.add_points Tweet_CREDIT_AMOUNT
render json: { status: :ok }
end
end
end
Et dans mes itinéraires.rb, c'est assez simple, donc je doute qu'il y ait quelque chose de mal ici ...
get 'social_kredit/credit_Tweet'
post '/credit_Tweet' => 'social_kredit#credit_Tweet'
Où oh où est cette erreur? Je ne connais clairement pas les requêtes HTTP.
Je l'ai fait fonctionner!
J'ai ajouté un ...
skip_before_action :verify_authenticity_token
au contrôleur.
Le problème a été détecté lors de l'extraction des journaux et du fait que le jeton CSRF n'a pas pu être vérifié.
ihaztehcodez (qui était actif pour la dernière fois en 2016, cela ne l'aidera donc pas à lui donner un coup de pouce) mentionne que le skip_before_action :verify_authenticity_token
la technique n'est pas aussi sûre car vous perdez la protection contre la contrefaçon.
ils mentionnent que la meilleure/sécurisée/'meilleure pratique', les solutions sont mentionnées ici AVERTISSEMENT: ne peut pas vérifier l'authenticité des jetons CSRF Rails
par exemple.
$.ajaxSetup({
headers: {
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
}
});
ou
$.ajax({ url: 'YOUR URL HERE',
type: 'POST',
beforeSend: function(xhr) {xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'))},
data: 'someData=' + someData,
success: function(response) {
$('#someDiv').html(response);
}
});
ou
mettre cela dans une demande ajax
headers: {
'X-Transaction': 'POST Example',
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
},
Même problème que j'ai rencontré. Il trie après l'ajout
skip_before_action: verify_authenticity_token
en haut de votre contrôleur où votre JS appelle ou envoie des données.
class UserController < ApplicationController
skip_before_action :verify_authenticity_token
def create
end
end
comme indiqué dans l'extrait de code.
Si vous incluez Rails meta data dans l'en-tête HTML avec <%= csrf_meta_tags %>
cela va générer ce qui suit.
<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="ihwlaOLL232ipKmWYaqbSZacpJegQqooJ+Cj9fLF2e02NTQw7P/MfQyRuzruCax2xYWtEHWsb/uqiiZP6NWH+Q==" />
Vous pouvez extraire le jeton CRSF des métadonnées et le transmettre à votre demande asynchrone. En utilisant la méthode native js fetch
, vous pouvez la passer en tant que x-csrf-token
entête.
Il s'agit d'un gestionnaire onSave réduit pour un composant React qui améliore un formulaire standard Rails.
onSaveHandler = (event) => {
const data = "Foo Bar";
const metaCsrf = document.querySelector("meta[name='csrf-token']");
const csrfToken = metaCsrf.getAttribute('content');
fetch(`/posts/${this.props.post_id}`, {
method: "PUT",
body: JSON.stringify({
content: data
}),
headers: {
'x-csrf-token': csrfToken,
'content-type': 'application/json',
'accept': 'application/json'
},
}).then(res => {
console.log("Request complete! response:", res);
});
}
La protection contre la contrefaçon est une bonne idée. De cette façon, nous restons en sécurité et ne plaisante pas avec notre configuration Rails.
En utilisant gem 'Rails', '~> 5.0.5'
& "react": "^16.8.6",