Zabezpieczenia forum przed spamem - ROR

od jakiegoś czasu morduje się z usuwaniem spamu z forum u mnie w firmie, napisanego w ROR… niestety żadnego zabezpieczenia nie ma tam, więc spamu nie brakuje… trochę nudzi mnie już usuwanie tego, więc myślę, że najwyższy czas spróbować wprowadzić jakieś zabezpieczenie, że gdy chce dodać jakis wpis to dodane zostanie dopiero jak przepiszę z obrazka jakiś kod…

fajnie by bylo gdybym potrafil na obrazku jakimś który byłby tłem (np.logo firmy) naniesione do przepisania potrzebne “znaki”… tutaj macie fajnie zrobione że mam wpisać dzień tygodnia żeby móc dodać ten wpis… coś takiego też by w pewien sposób załatwiało sprawę, ale jak byście mieli jakiś pomysł inny, to z chęcią posłucham RADY “STARSZYCH”…

dzięki z góry za odpowiedź…

Jest w railsach parę pluginów do tego: http://agilewebdevelopment.com/plugins/search?search=captcha
Osobiście z żadnego nie korzystałem, wystarczyło proste zabezpieczenie z sumą dwóch liczb:
2 + 6 = [form] ? (Odpowiedź wpisz słownie)
Działa bardzo dobrze i spam botów nie przepuszcza (przy około 300 próbach wysłania spamu dziennie, więc chyba dobry wynik). Osobiście jestem przeciwnikiem kodów obrazkowych. Po pierwsze i tak da się je złamać, a jak są zbyt wymyślne, to tylko użytkownika wkurza rozróżnianie między l (małe el) oraz I (duże I) i doszukiwanie się literek w gąszczu krzywych i kropek. Jak takie coś Ci wystarczy, to służę kodem.

no moze to i proste rozwiązanie… ale faktycznie jak zatrzyma spam to wystarczy… jak bedzie przepuszczal to cos innego bedzie trzeba zastosowac…

Alternatywa jest javascript ktory dodaje jakis magiczny input,
po submicie aplikacja sprawdza czy magiczne pole istnieje i podejmuje akcje czy zapisac forma, czy tez nie.

Minusem tego rozwiazania jest to ze klient bez wlaczonego javascriptu nie bedzie mogl skorzystac z formularza,
poniewaz magiczne pole mu sie nie “wyrenderuje”.
A boty jak wiadomo nie obslugują javascriptu(?) :wink:

Przyklad:

Formularz:

[code=ruby]<% form_for @foo do |f| %>

<% end %>[/code]
Javascript z kodem Rot13 ze strony: http://scott.yang.id.au/file/js/rot13.js

[code=javascript]Rot13 = {
map: null,

convert: function(a) {
    Rot13.init();
    var s = "";
    for (i=0; i < a.length; i++) {
        var b = a.charAt(i);
        s += ((b>='A' && b<='Z') || (b>='a' && b<='z') ? Rot13.map[b] : b);
    }
    return s;
},

init: function() {
    if (Rot13.map != null)
        return;

    var map = new Array();
    var s   = "abcdefghijklmnopqrstuvwxyz";

    for (i=0; i<s.length; i++)
        map[s.charAt(i)] = s.charAt((i+13)%26);
    for (i=0; i<s.length; i++)
        map[s.charAt(i).toUpperCase()] = s.charAt((i+13)%26).toUpperCase();

    Rot13.map = map;
},

write: function(a) {
    document.write(Rot13.convert(a));
}

}[/code]
A w kontrolerze, albo recznie sprawdzamy warunek params[:FY_bots].
Lub tez dodajemy odpowiednia walidacje w modelu(?) :slight_smile:

Mniej pracy niz przy captchy i nie wymaga imagemagicka.

tez ciekawe rozwiazanie… zobacze co mi pojdzie łatwiej :slight_smile: bezbolesniej…

Jakis plugin znalazlem do tego javascriptu, ale nie testowalem.

http://form-spam-protection.googlecode.com/svn/form_spam_protection/

Model:

[code=ruby]class BlogComment < ActiveRecord::Base
(…)
attr_accessor :user_captcha
attr_accessor :captcha
attr_accessor :sub_captcha_1
attr_accessor :sub_captcha_2

def validate
number = match_captcha(user_captcha)
if number.to_i != captcha.to_i
errors.add( captcha, “Wpisana liczba jest niepoprawna.”)
end
end

private
def match_captcha(text)
CAPTCHA_MAP.each do |pair|
return pair[1] if pair[0] == text
end
return -1
end

CAPTCHA_MAP = [
[“zero”, 0],
[“jeden”, 1],
[“dwa”, 2],
[“trzy”, 3],
[“cztery”,4],
[“pięć”, 5],
[“sześć”, 6],
[“siedem”, 7],
[“osiem”, 8],
[“dziewięć”,9],
[“dziesięć”,10],
[“jedenaście”, 11],
[“dwanaście”, 12],
[“trzynaście”, 13],
[“czternaście”, 14],
[“piętnaście”, 15],
[“szesnaście”, 16],
[“siedemnaście”, 17],
[“osiemnaście”, 18],
[“dziewiętnaście”, 19]
]
end[/code]
Controller:

[code=ruby] def new
if !params[:comment].nil?
@comment = @post.comments.build(params[:comment].merge(
{:captcha => nil, :user_captcha => nil}))
end
@sub_captcha_1 = rand( 6 ) + 1
@sub_captcha_2 = rand( 6 ) + 1
end

def create
@comment=@post.comments.build(params[:comment].merge({
:created_on=>Date.today, :captcha => params[:captcha]}))
if @comment.save
flash[:notice] = ‘Twój komentarz został zapisany. Dziękujemy.’
redirect_to blog_post_path(@post)
else
flash[:err] = ‘Twój komentarz nie został zapisany. Wypełnij wymagane pola.’
redirect_to blog_post_path(@post, :comment => params[:comment])
end
end[/code]
View

<% form_for( :comment, @comment, :url=>blog_comments_path(:blog_post_id=>post.id, :captcha => @sub_captcha_1 + @sub_captcha_2 ), do |f| %> (...) pola do wpisania komentarza <%= @sub_captcha_1.to_i %> + <%= @sub_captcha_2.to_i %> = <%= f.text_field :user_captcha, :size => 10%> ? (Odpowiedź wpisz słownie) <%=error_message_on "comment", "captcha" -%> <%= submit_tag "Zapisz komentarz" -%> <% end -%>
W skrócie: w kontrolerze tworzymy dwa sub kody i w formularzu przekazujemy ich sumę i tekst użytkownika, walidacja następuje w modelu.

Możesz też dodać zwykłe pole z tekstem “Nie edytować” i następnie ukryć je przy pomocy css (display:none). Następnie w kontrolerze sprawdzasz czy to pole zostało zedytowane. Boty przeważnie wypełniają wszystkie pola formularza, więc jak tekst pola został zmieniony to jest to spam

recaptcha
(jest wygodny plugin do railsów)
akismet
(korzysta z tego m.in. Mephisto - silnik blogowy napisany w RoR)

Fajne jest to, co Ronin w skrócie przedstawił, a co nazywa się “negatywną captchą”:
http://www.rorsecurity.info/journal/2008/4/4/webappsec-the-idea-of-negative-captchas.html
ogólnie warto się pobawić CSSem i javascriptem tak, żeby użytkownik nie widział w ogóle żadnego mechanizmu, a boty z kolei nie były w stanie go przejść.