Soru - Cevap Bölümü
/ Kategori: Programlama
Oturum açma ile ilgili. Kullanıcı kullanıcı adı ve şifresi ile bir bilgisayarda oturum açtığında, aynı kullanıcı adı ve şifre ile başka bir bilgisayarda oturum açmasını nasıl engelleyebiliriz.
Ya da bir önceki nin kapanmasını nasıl sağlayabilriz. Bir çok çözüm düşündüm ancak Application faaliyet alanının doğasını tam olarak çözememem nedeniyle başarısız oldum.
Düşüncem şu yönde idi.
Kullanıcılar sisteme giriş yaptıklarında Application faaliyet alanında oturum açan kullanıcıların bilgilerini tutan bir havuz oluşturmayı planladım. Kullanıcı ile bağlantılı bir veriyi burada saklamayı düşündüm.
Kullanıcı giriş yapmayı denediğinde -örneğin kullanıcı adını Application da depolamış isem- havuz içerisinde bulunan kayıtlar arasında bir kontrol yaparak kullanıcı girişine izin vermeyi yada kısıtlama getirmeyi planlıyordum. içinden çıkamağıdım nokta kullanıcılar siteyi terk ettiklerinde yani oturumları kapandığında, oluşması gerekli olayları hayal edememiş olmam.
Bir de diyelim 30-40 bin kullanıcının online olması olası bir uygulamada bu şekilde Application faaliyet alanına yüklenmenin ColdFusion’un doğası üzerinde yapacağı etkiden tedirgin oldum.
Yani kısaca yapamadım.
Cevaplar
( Faydalı Cevapları Göster )
Evet kullanıcı sayısı epey fazla, bu durumda Application kapsamı yerine veritabanı kullanacağız. Ayrıca böylece çözümümüz ‘Cluster destekli’ olacak.
Veritabanında kullanıcıların kayıtlı olduğu bir KULLANICI tablosu olduğunu varsayıyorum. Bu tabloya NULLABLE bir LOGIN_ID alanı eklemeliyiz. Bu alandaki değer eğer NULL ise bu üyenin şu an oturum açmadığı anlamına gelir. Bu alanda oturum açan kullanıcı için bir UUID kaydedeceğiz.
Kullanıcı oturum açarken kullanıcı adı ve şifre kontrolü yapıp veritabanından kullanıcı bilgileri getirerek kullanıcının oturum açıp açamayacağına karar verdiğimiz yerde ilave olarak bu LOGIN_ID’yi de kontrol edeceğiz.
LOGIN_ID
boş/null ise kullanıcının oturum açmasına izin vereceğiz ve kullanıcının
CFID:CFTOKEN
bilgilerini bu LOGINID’ye kaydedeceğiz (update işlemi). (Eğer LOGINID için
createUUID()
ile başka bir UUID kullanırsanız Session kapsamına da bu değeri kaydedin, çünkü sonra her request için karşılaştırma yapacağız)
Eğer LOGIN_ID dolu ve kullanıcının şu an ki
CFID:CFTOKEN
bilgileri ile aynı ise kullanıcıya yine izin vereceğiz. (Eğer varsayılan 20 dakika kalıcı çerezli session ve cflogin framework’ünü bir arada kullanıyorsanız bu gerekli)
Fakat LOGIN_ID dolu ve içerdiği değer
CFID:CFTOKEN
‘dan farklıysa kullanıcıya bu kullanıcının zaten oturum açmış olduğunu mevcut oturumu kapatarak oturum açmak isteyip istemediğini soracağız. Kullanıcı evet derse LOGIN_ID’ye yeni CFID:CFTOKEN’ı kaydedeceğiz ve oturum açmasına izin vereceğiz.
Ayrıca her request için aktif oturumun geçerli olup olmadığını kontrol etmek durumundayız. Bu kontrolde LOGIN_ID ile CFID:CFTOKEN’ı karşılaştırırız. Eğer farklıysa bu kullanıcının oturumu artık geçersiz demektir.
Son olarak kullancı kendi isteğiyle oturumu kapattığında ve session timeout olduğunda (artı eğer cflogin framework’ünü kullanıyorsanız login timeout olduğunda, ki login, session’dan önce timeout olabilir) kullanıcının veritabanı kaydındaki
LOGIN_ID'yi NULL
yapın.
(Not: Application.cfc kullanırsanız onSessionEnd() metodu session timeout olduğunda otomatikman çalışıyor! Aksi taktirde session timeout’u Java’ya girerek anlamak zorundasınız veya her request için login geçerliliği kontrolü yapmak yerine mevcut açık oturumu başka bir oturumdayken kapatmak zorundasınız (ki bu bir hile ile yapılabilir, o yüzden önerilmez). Eğer session timeoutu algılatamıyorsanız, sorun değil, bu çözüm yine de çalışır)
Bu çözümü performans açısından irdeleyelim. Sistemi etkileyebilecek fazladan iki sorgu yapıyoruz: biri oturum açıldıktan sonra yapılan update işlemi, diğeri de her request için yaptığımız oturum geçerlilik kontrolü. Her iki işlemde
KULLANICI_ID
yani Primary Key alan kullanılarak yapılacağı için performansı çok az etkileyecektir. Ayrıca MySQL değilde daha gelişmiş SQLServer veya Oracle gibi veritabanları kullanıyorsak bu veritabanları update işleminde sadece ilgili satırı kilitlediğinden KULLANICI tablosu üzerindeki diğer işlemler normal şekilde çalışacaktır.
Evet bu yöntem her yönden gayet iyi (yine de ek öneriler ve düzeltmelere açığım elbette). iyi çalışmalar,
<cfif isDefined('FORM.sifre') and isDefined('FORM.kullanici')>
<cfif FORM.sifre neq '' and FORM.kullanici neq ''>
<cfquery datasource='#Request.DB#' name='Login'>
SELECT * FROM KULLANICI
WHERE kulaniciAdi = '#FORM.kullanici#' AND sifre = '#FORM.sifre#'
</cfquery>
<!--- kullanıcı adı ve şifresi doğru --->
<cfif Login.RecordCount eq 1>
<!--- kullanıcı daha önce oturum açmış mı? --->
<cfif Login.LOGIN_ID eq ''>
<!--- açmamış ise --->
<cfset Session.Oturum = StructNew() />
<cfset Session.Oturum.ID = Login.UserID />
<cfset Session.Oturum.Name = Login.kulaniciAdi />
<!--- şimdi kullanıcının oturum açtığını veritabanına kaydedelim --->
<cfquery datasource='#Request.DB#'>
UPDATE KULLANICI SET
LOGIN_ID = '#Session.URLToken#'
WHERE UserID = <cfqueryparam cfsqltype='cf_sql_integer' value='#Session.Oturum.ID#' />
</cfquery>
<!--- oturum açıldı, kullanıcıyı yönlendirelim --->
<cflocation url='GidilecekSayfa.cfm' addtoken='no' /><!--- token göndermeli miyiz ? --->
<!--- eğer kullanıcı oturum açmış ve bilgileri doğru ise --->
<cfelseif Login.LOGIN_ID eq Session.URLToken>
<!--- kullanıcı işlemini yapıyor devam ediyor --->
<cflocation url='GidilecekSayfa.cfm' addtoken='no' />
<!--- bilgiler uyuşmuyor ise --->
<cfelse>
<cflocation url='GirisUyarisi.cfm' addtoken='no' />
</cfif>
<!--- kullanıcı adı/şifresi yanlış --->
<cfelse>
<cflocation url='GirisUyarisi.cfm' addtoken='no' />
</cfif>
</cfif>
</cfif>
Teşekkürler aynen bu kodu kullandım ve çalıştı. Ancak oturum zaman aşımı sürelerini algılatamadım :). Application.cfc üzerinde onSessionStart() ve onSessionEnd() metodları arasında bu işlemleri gerçekleştirmeyi planladım. Ancak sanırım CF dökümantasyonunu iyi anlayamadım, sorunlar oluştu. onSessionStart() ile LOGIN_ID alanının değerini güncellemeyi, onSessionEnd() ile de burayı tekrar [i]NULL[/i] değerine döndürmeye çalıştım. Ama ne yazıkki sonuç alamadım. Yardımınız için çok teşekkür ederim.
Bir sorum daha olacak. Bu tarz bir oturum açma uygulamasında kilitleri nerelerde ve hangi biçimde kullanmak doğru olur. Yada gerçekten gerek var mıdır? Bir değer oluştururken özel diğer şekiller de salt okunur olarak kullanmamız yeterlimi. Kısaca kilitlenmeye dair bir yorum yapabilirseniz çok sevinirim. Yarıdımınız için çok çok teşekkürler.
Kodunuzda <cfqueryparam> kullanmalısınız. 30 bin oturumdan bahsediyoruz, <cfqueryparam> kullanmak sizin için yani geliştirim ekibiniz için kaçınılmaz bir kural olmalı.
Oturum zaman aşımı olduğunda,
Application.cfc'deki onSessionEnd()
çalışması ile ilgili şöyle bir bug var: Eğer Application.cfc’de sessionTimeout değerini belirtmezseniz
onSessionEnd()
çalışmıyor.
Bunu düzeltmek için Application ayarlarını yaparken session timeout’u belirtmeliyiz:
<cfcomponent>
<cfset this.name='uygulamaAdi' />
<cfset this.sessionManagement=true />
<cfset this.sessiontimeout=CreateTimeSpan(0,0, 20, 0)>
<cffunction name='onSessionEnd' access='public'>
...
</cffunction>
...
</cfcomponent>
Kilitlerden kastınız
<cflock>
etiketiyse bu çözümde
<cflock>
‘a gerek yok.
<cflock>
‘u birden fazla request tarafından paylaşılan örneğin application ve session kapsamları için kullanmalıyız.
Fakat gönderdiğiniz kodda
<cflogin>
framework’ünü kullanmak yerine session’a bazı değerler kaydediyorsunuz; eğer siteniz frameliyse veya kullanıcının birden fazla tarayıcıyla aynı oturumda çalışabilmesi durumu söz konusuysa session’daki değişkenleri değiştirirken (set ederken)
<cflock scope="session" type="exclusive" timeout="20">
kullanabilirsiniz. Session’daki değerleri okurken de
<cflock scope="session" type="readonly" timeout="20">
kullanabilirsiniz.
Benim tablodaki satır kilitleme ile ilgili bahsettiğim konu ise farklı bir şeydi. Veritabanı çalışmasıyla ilgili bir tefarruattı sadece.
iyi çalışmalar,
http://www.macromedia.com/go/9ce734f4
adresinde Application.cfc’nin kullanımları konusunda bilgi bulabilirsiniz.
MMIstanbul Adobe UG
ColdFusion, Flex, AIR, Flash, PDF, Dreamweaver, Fireworks, Photoshop, Illustrator, iNdesign, Premiere, Soundbooth, Lightroom, InCopy, JRun, LiveCycle, Acrobat, AfterEffects, Resmi Adobe Kullanıcı Grubu.
Etkinlikler
Fuar
CeBIT 2008 Bilişim Eurasia 7 - 12 Ekim 2008' de
CeBIT 2008 Bilişim Eurasia 7 - 12 Ekim 2008' de
CeBIT Bilişim Eurasia bu yıl 7 – 12 Ekim tarihlerinde düzenleniyor
Adını dünyanın en büyük on fuarı arasına yazdırarak, İstanbul’u Avrasy...
Kategori: Fuar
Kimler Burada? 
Son 1 dakika içinde MMIstanbul' da 254 (2 kayıtlı, 252 ziyaretçi) kullanıcı varmış. Login durumda olanlar aşağıda:
MMIstanbul Blog'undan
Neler Yapılabilir?
Yeni bir portal, 30 civarında online / offline etkinlik, seminer vb rağmen MMIstanbul sanıyoruz ki halen hakettiği ilgiyi göremedi. " ...
500 Hatası Hakkında!
Reklam, MMIstanbul ve Yeni Projeler (Durumumuz Bu Tarzında)
Ne Nedir Kampanyası Başlıyor!
Çok Merak Edenler için; MMIstanbul Geliştirme Ekibi ve Çalışma Ortamımız





CF olarak değil ancak bu soruya genel mantık ile cevap verebiliriz..
Öncelikle Her Login olan kişi session_id ve ip’si ile birlikte db veya session’a kaydedilir..
Daha sonra 2. kez aynı user bilgileri ile login olan kişinin ip ve session_id si ile 1. kişinin login bilgileri ile karşılaştırılır..
Böylece eğer bilgiler aynı değilse 1. kişi veya isteğe göre 2. kişi logout yapılabilir veya 2.kişinin login olması engellenebilir..
eğer aynı ağ içerisinde ise pcnin özel fiziksel bilgilerden birisi ile bu işlem gerçekleştirilebilir..