Hur man bygger ett diskret inloggningssystem i rader

Ett diskret inloggningssystem är ett som kommer ut ur användarens sätt. Det kommer att göra din ansökan trevligare och mer polerad. Denna artikel kommer att vägleda dig genom processen att konfigurera användarinloggningar och sedan ajaxify processen genom att flytta formuläret till en modalbox som kommunicerar med servern. Dessutom visar den här artikeln hur du skapar inställningen med jQuery och Prototype så att du kan välja ditt favoritbibliotek. Denna artikel förutsätter att du har erfarenhet av Rails och jQuery eller Prototype.


Du kan använda Adman65 / nät för en lyckad inloggning. Var noga med att använda dåliga uppgifter så att du kan se hur allt fungerar.

Vad vi gör



Komma igång

Vi ska börja med att skapa en dummy-applikation som har en offentlig och privat sida. Rotsadressen är den offentliga sidan. Det finns en inloggningslänk på den offentliga sidan. Om användaren loggar in med framgång, omdirigeras den till den privata sidan. Om inte, omdirigeras de tillbaka till inloggningsformuläret. Den privata sidan visar användarnamnet. Vi använder detta som utgångspunkt för att ajaxify webbplatsen.

Det första steget använder rails-kommandot för att generera en ny applikation, sedan installera och konfigurera authlogic.

$ cd till-a-katalog $ rails diskreta inloggning

Lägg till authlogic.

# /config/environment.rb config.gem "authlogic"

Installera nu pärlorna.

$ sudo pärla installera gemcutter $ sudo pärla tumble $ sudo rake gems: installera

Skapa sedan en användarmodell och lägg till de obligatoriska autonomiska kolumnerna för migreringen.

$ ./script/generate model Användare existerar app / modeller / existerar test / enhet / existerar test / fixtures / skapa app / models / user.rb skapa test / unit / user_test.rb skapa test / fixtures / users.yml skapa db / migrera skapa db / migrera / 20100102082657_create_users.rb

Lägg nu till kolumnerna till den nya migreringen.

klass CreateUsers < ActiveRecord::Migration def self.up create_table :users do |t| t.string :login, :null => false t.string: crypted_password,: null => false t.string: password_salt,: null => false t.string: persistence_token,: null => false t.timestamps slutänden def self.down drop_table:

Migrera databasen.

$ rake db: migrera

Inkluder authlogic i användarmodellen.

# /app/models/user.rb klass Användare < ActiveRecord::Base acts_as_authentic end

Nu kan vi skapa en användare. Eftersom det här är en demo-app krävs inte webbaserad funktionalitet för inloggning. Så öppna konsolen och skapa en användare:

$ ./script/console >> me = User.create (: login => 'Adman65',: password => 'netts',: password_confirmation => 'netuts')

Nu har vi en användare i systemet, men vi har ingen möjlighet att logga in eller logga ut. Vi behöver skapa modeller, controllers och synpunkter för detta. Authlogic har sin egen klass för att spåra inloggningar. Vi kan använda generatorn för det:

# skapa användarsessionen $ ./script/generate UserSession

Nästa måste vi generera den kontroller som kommer att logga in / logga ut användare. Du kan skapa sessioner som alla andra resurser i Rails.

# skapa sessionskontrollanten $ ./script/generate controller UserSessions

Ange nu dess innehåll till:

# /app/controllers/user_sessions_controller.rb klass UserSessionsController < ApplicationController def new @user_session = UserSession.new end def create @user_session = UserSession.new(params[:user_session]) if @user_session.save flash[:notice] = "Login successful!" redirect_back_or_default user_path else render :action => : Ny slutänden

Det ser ut precis som en kontroller som genererades via ställningar. Skapa nu användarens kontroller som har offentligt och privat innehåll. Generera en användare kontroller. Inuti kontrollenheten använder vi ett tidigare filter för att begränsa tillgången till de privata områdena. Indexåtgärden är offentlig och showen är privat.

# skapa användarnas kontroller $ ./script/generate controller användare

Uppdatera dess innehåll:

# /app/controllers/users_controller.rb klass UsersController < ApplicationController before_filter :login_required, :only => : visa def index end def visa @user = current_user slut privat def login_required om inte current_user flash [: error] = 'Du måste vara inloggad för att se den här sidan.' redirect_to new_user_session_path slutänden

Du bör märka att current_user är en odefinierad metod vid denna punkt. Definiera dessa metoder i ApplicationController. Öppna applikationscontroller.rb och uppdatera innehållet:

# Application Controller Class ApplicationController < ActionController::Base helper :all # include all helpers, all the time protect_from_forgery # See ActionController::RequestForgeryProtection for details # From authlogic filter_parameter_logging :password, :password_confirmation helper_method :current_user_session, :current_user private def current_user_session @current_user_session ||= UserSession.find end def current_user @current_user ||= current_user_session && current_user_session.user end end

Vid denna tidpunkt är modellerna och kontrollerna komplett, men vyer är inte. Vi måste skapa synpunkter för ett inloggningsformulär och det offentliga och privata innehållet. Vi använder gyllene generatorer för att skapa en grundläggande layout.

$ sudo pärla installera nifty-generatorer $ ./script/generate nifty_layout

Det är dags att skapa inloggningsformuläret. Vi kommer att använda en partiell för detta eftersom vi i framtiden använder partiet för att bara göra inloggningsformuläret i modalkassen. Här är koden för att skapa inloggningsformuläret. Det är exakt detsamma som om du skapade ett blogginlägg eller någon annan modell.

# skapa inloggningsvisningarna # /app/views/user_sessions/_form.html.erb <% form_for(@user_session, :url => user_session_path) gör | form | %> <%= form.error_messages %> 

<%= form.label :login %> <%= form.text_field :login %>

<%= form.label :password %> <%= form.password_field :password %>

<%= form.submit 'Login' %> <% end %>

Rendera partiet i den nya vyn:

# /app/views/user_sessions/new.html.erb <% title 'Login Please' %> <%= render :partial => 'form'%>

Skapa några grundläggande sidor för det offentliga och privata innehållet. Indexåtgärden visar offentligt innehåll och visar privat innehåll.

# skapa den publika offentliga sidan # /app/views/users/index.html.erb <% title 'Unobtrusive Login' %> 

Public Facing Content

<%= link_to 'Login', new_user_session_path %>

Och för den privata sidan:

# skapa den privata sidan för dummy # /app/views/users/show.html.erb <% title 'Welcome' %> 

Hej <%=h @user.login %>

<%= link_to 'Logout', user_session_path, :method => : ta bort%>

Ta bort filen /public/index.html och starta servern. Du kan nu logga in och logga ut från programmet.

$ ./script/server

Här är några skärmdumpar av demo-applikationen. Den första är den offentliga sidan.

Nu inloggningsformuläret

Och den privata sidan

Och slutligen nekas åtkomst när du försöker besöka http: // localhost: 3000 / user

AJAX-inloggningsprocessen

Innan vi fortsätter måste vi förstå hur servern och webbläsaren ska arbeta tillsammans för att slutföra processen. Vi vet att vi måste använda vissa JavaScript för modalboxen och servern att validera inloggningar. Låt oss vara tydliga på hur det här ska fungera. Användaren klickar på inloggningslänken, sedan visas en modalbox med inloggningsformuläret. Användaren fyller i formuläret och omdirigeras antingen till den privata sidan, eller modalboxen uppdateras med ett nytt inloggningsformulär. Nästa fråga är hur du uppdaterar modalboxen eller berätta för webbläsaren vad du ska göra efter att användaren skickat formuläret? Rails har response_to block. Med response_to kan du berätta för regulatorn att göra annat innehåll om användaren begärde XML, HTML, JavaScript, YAML etc. Så när användaren skickar formuläret kan servern returnera vissa JavaScript för att kunna köras i webbläsaren. Vi använder det här för att göra en ny form eller omdirigering. Innan vi dyker djupare, låt oss gå över processen i ordning.

  1. Användaren går till den offentliga sidan
  2. Användaren klickar på inloggningslänken
  3. Modalbox visas
  4. Användaren fyller i formuläret
  5. Form skickas till servern
  6. Server returnerar JavaScript för körning
  7. Browser kör JavaScript som antingen omdirigerar eller uppdaterar modalboxen.

Det är den höga nivån. Här är implementeringen på låg nivå.

  1. Användaren besöker den offentliga sidan
  2. Den offentliga sidan har några JavaScript som körs när DOM är klart som bifogar JavaScript till inloggningslänken. Det javscript gör en XMLHTTPRequest (XHR från och med nu) till servern för vissa JavaScript. JavaScript anger modalboxens innehåll i formuläret HTML. JavaScript gör också något väldigt viktigt. Det binder formulärets inlämning till en XHR med POST-data till formulärets åtgärd. Detta gör det möjligt för användaren att fortsätta fylla inloggningsformuläret inuti modalkassen.
  3. Modalboxen har nu formen och kräver JavaScript
  4. Användarklick "Logga in"
  5. Funktionen Submit () kallas som gör en POST XHR till formulärets handling med dess data.
  6. Server genererar antingen JavaScript för formuläret eller omdirigeringen
  7. Webbläsaren tar emot JavaScript och kör det. Webbläsaren uppdaterar antingen modalkassen eller omdirigerar användaren genom window.location.

Tar en topp på AJAX Ready Controller

Låt oss ta en titt på den nya strukturen för UserSessions-kontrollen.

klass UserSessionsController < ApplicationController layout :choose_layout def new @user_session = UserSession.new end def create @user_session = UserSession.new(params[:user_session]) if @user_session.save respond_to do |wants| wants.html  redirect_to user_path(@user_session.user)  wants.js  render :action => : omdirigering # JavaScript för att göra omdirigeringsänden, annars svara för att | vill | wants.html render: new wants.js # default till create.js.erb slutänden slut privat def choose_layout (request.xhr?)? noll: "ansökan" slutet

Som du kan se är strukturen annorlunda. Inne i, om spara, annars villkorligt, är svaret till att göra det rätta innehållet. want.xx där xx är en innehållstyp. Som standard Prototype och jQuery begär text / JavaScript. Detta motsvarar wants.js. Vi är redo att komma igång på AJAX-delen. Vi kommer inte använda några plugins utom de för modala lådor. Vi använder Facebox för jQuery och ModalBox för Prototype.

Prototyp

Rails har byggt in stöd för Prototype. Järnvägets JavaScript-hjälpare är Ruby-funktioner som genererar JavaScript som använder Prototype. Denna teknik är känd som RJS (Ruby JavaScript). Ett exempel är remote_form_for som fungerar som standarden för_för lägger till att vissa JS är bundna till onsubmit som skickar till formuläret till dess åtgärd med hjälp av dess metod med dess data. Jag kommer inte använda RJS i den här artikeln eftersom jag vill demonstrera vanilj JS. Jag tror att genom att använda ren JS och eliminera JS-hjälparna kommer artikeln att vara mer tillgänglig av mindre erfarna utvecklare. Med detta sagt kan du enkelt genomföra dessa steg med hjälp av RJS / Prototype-hjälpare om du väljer.

Att lägga till prototyp till programmet är väldigt enkelt. När du använder rails-kommandot skapas det prototyp och scriptaculous-filer i / public / JavaScripts. Inklusive dem är lätt. Öppna upp /app/views/layouts/application.erb och lägg till den här raden inuti huvudetiketten:

<%= JavaScript_include_tag :defaults %>

JavaScript_include_tag skapar skript taggar för standardfiler i / offentliga / JavaScripts, viktigast prototype.js, effects.js och application.js. effects.js är scriptaculous. application.js är en fil som du kan använda för att behålla programspecifik JS. Nu behöver vi ett modalbox-plugin. Vi ska använda detta. Det är en mycket trevlig modalbox plugin inspirerad av OSX. Källan är värd på GitHub, så du måste klona och flytta filerna i din projektkatalog. Till exempel:

$ cd-kod $ git klon git: //github.com/okonet/modalbox.git $ cd modalbox # flytta filerna i rätt kataloger. # flytta modalbox.css till / public / stylesheets # flytta modalbox.js till / public / JavaScripts # flytta spinner.gif till / public / images

Lägg nu in stilarken och JavaScript i din ansökan.

 <%= stylesheet_link_tag 'application' %> <%= stylesheet_link_tag 'modalbox' %> <%= JavaScript_include_tag :defaults %> <%= JavaScript_include_tag 'modalbox'%>

Låt oss nu få in vår länk för inloggning för att öppna en modalbox. För att göra detta måste vi lägga till lite JavaScript som körs när DOM är klart som fäster modalboxen till vår länk. När användaren klickar på inloggningslänken gör webbläsaren en GET till / user_sessions / new som innehåller inloggningsformuläret. Inloggningslänken använder # login-länkväljaren. Uppdatera inloggningslänken för att använda det nya idet i /app/views/users/index.html.erb. Ändra länken_för att fungera så här:

<%= link_to 'Login', new_user_session_path, :id => 'login-link'%>

Det ger oss en # login-länk. Nu för att JavaScript ska bifoga en modalbox. Lägg till den här JS i /public/JavaScripts/application.js

document.observe ('dom: loaded', funktion () $ ('login-link'). observera ("klicka", funktion (händelse) event.stop (); Modalbox.show (this.href, : 'Logga in', bredd: 500););)

Det finns några enkla JS för när användaren klickar på länken öppnas en modalbox med länkens href. Se dokumentationen för modalboxen om du vill ha mer anpassning. Här är en skärmdump:

Observera att inuti modalkassen ser väldigt ut som vår standardsida. Rails använder vår applikationslayout för alla HTML-svar. Eftersom våra XHRs vill ha HTML-fragment, är det meningslöst att göra utan layouter. Hänvisa till exempelkontrollen. Jag introducerade en metod för att bestämma layouten. Lägg till det i UserSessionsController för att inaktivera layout för XHRs.

klass UserSessionsController < ApplicationController layout :choose_layout def new @user_session = UserSession.new end def create @user_session = UserSession.new(params[:user_session]) if @user_session.save flash[:notice] = "Login successful!" redirect_to user_path else render :action => : Ny slutänden def förstör current_user_session.destroy flash [: notice] = "Logga ut lyckad!" redirect_to root_path sluta privat def choose_layout (request.xhr?)? noll: "ansökan" slutet

Uppdatera sidan och klicka på länken du borde få något så här:

Fyll i formuläret och se vad som händer. Om du fyller i från med dålig info, omdirigeras du utanför modalboxen. Om du loggar in korrekt ändras du normalt. Enligt kraven ska användaren kunna fylla i formuläret om och om igen inuti modalkassen tills de loggar in korrekt. Hur kan vi uppnå detta? Som beskrivits tidigare måste vi använda AJAX för att skicka in data till servern, använd sedan JavaScript för att uppdatera modalkassen med formuläret eller omdirigera. Vi vet att modalboxen gör en GET för HTML. Efter att ha visat den ursprungliga modalboxen måste vi skriva JS som gör att formuläret skickar in sig AJAX-stil. Detta gör att formuläret kan skicka sig in i modalkassen. Att helt enkelt lägga till den här koden efter att modalboxen heter kallas inte för att XHR kanske inte har slutförts. Vi måste använda Modalboxs afterLoad-återuppringning. Här är den nya koden:

document.observe ('dom: loaded', funktion () $ ('login-link'). observera ("klicka", funktion (händelse) event.stop (); Modalbox.show (this.href, : 'Logga in', bredd: 500, afterLoad: function () $ ('new_user_session'). Observera ("skicka", funktion (händelse) event.stop (); this.request ();) ;);)

Form # -förfrågan är en bekväm metod för serialisering och inlämning av formuläret via en Ajax.Request till webbadressen till formulärets åtgärdsattribut-vilket är exakt vad vi vill ha. Nu kan du fylla i formuläret inom modal utan att stänga det. Klientsidan är nu klar. Vad sägs om serverns sida? Klienten skickar en POST som vill ha JS tillbaka. Servern måste besluta att antingen returnera JavaScript för att uppdatera formuläret eller göra omdirigering. I UserSessionsController använder vi response_to för att hantera JS-förfrågan och en villkorlig att returnera rätt JS. Låt oss börja med att hantera det misslyckade inloggningsfallet. Servern måste returnera JS som uppdaterar formuläret och berättar den nya blanketten att skicka över ajax. Vi lägger denna mall i /app/views/users_sessions/create.js.erb. Här är strukturen för den nya skapa åtgärden:

def skapa @user_session = UserSession.new (params [: user_session]) om @ user_session.save flash [: notice] = "Logga in lyckad!" redirect_to user_path else respond_to do | vill | wants.html render: new wants.js # create.js.erb slutet slutet

Låt oss nu fylla i create.js.erb:

$ (MB_content). Uppdatering ("<%= escape_JavaScript(render :partial => 'form')%> "); Modalbox.resizeToContent (); $ ('new_user_session'). observera (" skicka ", funktion (händelse) event.stop (); this.request (););

Först uppdaterar vi innehållet till den nya formuläret. Sedan ändrar vi modalboxen. Därefter ajaxifieras formuläret som tidigare. Voilla, du kan fylla i formuläret så många gånger du vill.

Nästa måste vi hantera omdirigeringsfallet. Skapa en ny fil i /app/views/users_sessions/redirect.js.erb:

 window.location =”<%= user_path %>”;

Nu uppdaterar du skapningsåtgärden för att hantera omdirigeringsprocessen:

def skapa @user_session = UserSession.new (params [: user_session]) om @ user_session.save respond_to do | vill | wants.html flash [: notice] = "Logga in lyckad!" redirect_to user_path sluta wants.js render: redirect sluta svara igen för att | vill | wants.html render: new wants.js # create.js.erb slutet slutet

Och det är allt! Nu försöker du logga in med rätt uppgifter och du omdirigeras till den privata sidan. För vidare inlärning, försök att lägga till en spinnare och en anmälan som säger till användaren att formuläret skickas eller omdirigeras. Applikationen fungerar fortfarande om användaren har JavaScript inaktiverat också.

jQuery

Eftersom jag redan har täckt prototypprocessen, så kommer jag inte att gå in i samma detalj som tidigare. Istället kommer jag att flytta snabbt och beskriva alternativa JavaScript för att lägga till programmet. JQuery vesion kommer att ha exakt samma struktur som prototypversionen. Allt vi behöver ändra är vad som finns i application.js, create.js.erb och i JavaScript / css ingår.

Det första vi behöver göra är att ladda ner jQuery och Facebox. Flytta jQuery till / public / JavaScripts som jquery.js. För facebox flyttar bilderna till / public / images /, stylesheets till / public / stylesheets, och slutligen JS in / public / JavaScripts. Uppdatera nu /app/views/layouts/application.html.erb för att återspegla ändringarna:

 <%= h(yield(:title) || "Untitled") %> <%= stylesheet_link_tag 'facebox' %> <%= stylesheet_link_tag 'application' %> <%= JavaScript_include_tag 'jquery' %> <%= JavaScript_include_tag 'facebox' %> <%= JavaScript_include_tag 'application' %> 

Facebox levereras med ett standardformat som förutsätter att du har dina bilder i / facebox. Du måste uppdatera dessa väljare i facebox.css som så:

#facebox .b bakgrund: url (/images/b.png);  #facebox .tl background: url (/images/tl.png);  #facebox .tr bakgrund: url (/images/tr.png);  #facebox. bl background: url (/images/bl.png);  #facebox .br bakgrund: url (/images/br.png); 

Nu bifogar vi ansiktsbox till inloggningslänken. Öppna upp /public/JavaScripts/application.js och använd det här:

$ (dokument) .ready (funktion () $ ('# login-link'). facebox (loadingImage: '/images/loading.gif', closeImage: '/images/closelabel.gif',); );

Jag åsidosätter standardinställningarna för bilderna för att återspegla den nya bildvägen. Börja skära och gå över till indexsidan. Du borde se en fin ansiktsbox med inloggningsformuläret:

Nästa sak vi måste göra är att ange formuläret för att skicka in sig via AJAX. Precis som tidigare måste vi använda återuppringningar för att köra kod efter att modalboxen är klar. Vi använder jQuerys postmetod för XHR-förfrågan. Facebox har en efterkrok som vi kan använda. application.js:

$ (dokument) .ready (funktion () $ ('# login-link'). facebox (loadingImage: '/images/loading.gif', closeImage: '/images/closelabel.gif'; $ (dokument) .bind ("reveal.facebox", funktion () $ ('# new_user_session'). Skicka (funktion () $ .post (this.action, $ (this) .serialize (), null, " script "); return false;);););

Uppdatering av create.js.erb ska vara lätt nog. Vi måste uppdatera innehållslådans innehåll och omformulera formuläret igen. Här är koden:

$ ('# facebox .content'). html ("<%= escape_JavaScript(render :partial => "form")%> "); $ ('# new_user_session'). Skicka (funktion () $ .post (this.action, $ (this) .serialize (), null," script "); returnera false; );

Och det är allt! Här är den slutliga produkten:

Hämtar koden

Du kan få koden här. Det finns grenar för varje bibliotek så att du kan kolla in prototypen eller jQuery-versionerna. Några frågor, kommentarer, oro? Tack igen för att läsa!

  • Följ oss på Twitter, eller prenumerera på Nettuts + RSS-flödet för de bästa webbutvecklingsstudierna på webben.