Merhaba arkadaşlar. Oturum yönetimi konusuna daha önce Apacahe Shiro yazıları ile değinmiştik. Buradan ve buradan o yazılara ulaşabilirsiniz. Bu yazıda ise Servlet taraflı bir iş yapacağız ve Filtre (Filter) vasıtası ile oturum yönetimine değineceğiz.
Bu yazıyı yazmak için yararlandığım kaynağa buradan erişebilirsiniz. Şimdi uygulamayı inceleyelim. İlk olarak xhtml sayfalarına değinelim.
Uygulama 3 xhtml sayfası var. Birisi herkesin ulaşabildiği info sayfası. Bir diğeri login sayfası. Sonuncu sayfa ise secure dizini altında yer alan ve yetkili kişilerin erişebildiği welcome sayfası. Bu 3 sayfada kodlama olarak anlatılacak bir yer yok arkadaşlar. Hepsi daha önce yazdığım şeyler. Şimdi Java sınıflarımıza bakalım.
LoginBean.java
import java.io.Serializable; import javax.faces.application.FacesMessage; import javax.faces.bean.ManagedBean; import javax.faces.bean.ManagedProperty; import javax.faces.bean.SessionScoped; import javax.faces.context.FacesContext; @ManagedBean @SessionScoped public class LoginBean implements Serializable { private static final long serialVersionUID = 7765876811740798583L; // Bu listeyi bir veri tabanı gibi düşünelim. private static final String[] users = {"anna:qazwsx","kate:123456"}; private String username; private String password; private boolean loggedIn; @ManagedProperty(value="#{navigationBean}") private NavigationBean navigationBean; public String doLogin() { // Veri tabanından veri çekme işlemi olarak düşünelim for (String user: users) { String dbUsername = user.split(":")[0]; System.out.println(dbUsername); String dbPassword = user.split(":")[1]; // Girilen kullanıcı adı şifre veri tabanında var mı bakıyoruz. if (dbUsername.equals(username) && dbPassword.equals(password)) { loggedIn = true; return navigationBean.redirectToWelcome(); } } // Hata mesajı döndürüyoruz. FacesMessage msg = new FacesMessage("Login error!", "ERROR MSG"); msg.setSeverity(FacesMessage.SEVERITY_ERROR); FacesContext.getCurrentInstance().addMessage(null, msg); // Giriş sayfasına yönlendiriyoruz. return navigationBean.toLogin(); } public String doLogout() { //Oturum kapandığını bildiriyoruz. loggedIn = false; // Çıkış mesajı veriyoruz. FacesMessage msg = new FacesMessage("Logout success!", "INFO MSG"); msg.setSeverity(FacesMessage.SEVERITY_INFO); FacesContext.getCurrentInstance().addMessage(null, msg); return navigationBean.toLogin(); } // ------------------------------ // Getters & Setters public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public boolean isLoggedIn() { return loggedIn; } public void setLoggedIn(boolean loggedIn) { this.loggedIn = loggedIn; } public void setNavigationBean(NavigationBean navigationBean) { this.navigationBean = navigationBean; } }
LoginBean sınıfımız içinde oturum açılıp açılmadığını tutan bir boolean değişken ve kullanıcı adını,şifreyi tutan değişkenler yer alıyor. Kod içerisinde göreceğiniz üzere @ManagedProperty notasyonu mevcut. Bu notasyondan biraz bahsetmek istiyorum arkadaşlar.
Bu notasyon managed bean’ler arası bağımlılık enjektesi için kullanılan bir notasyondur. Normal zamanda bir sınıf içinde başka bir sınıfın değişkenlerini ve mtotlarını kullanmak istediğimizde kullanmak istediğimiz sınıfa ait nesne oluşturmak zorundayız. Hatta bu durum aynı sınıfta main metot içinden başka bir metot ya da değişken çağırdığımızda da geçerlidir. @ManagedProperty notasyonu ile bu nesne oluşturma işlemine gerek kalmaz ve biz managed bean içinde başka bir managed bean’in özelliklerini kullanabiliriz.
doLogin metodu içinde xhtml sayfasından gelen isim ve parolanın bizde olup olmadığı kontrol ediliyor ve varsa welcome sayfasına yönlendiriliyoruz. Yoksa bir hata mesajı verdiriyoruz.
doLogout metodunda da loggedIn değişkenine false değer atayıp login sayfasına yönlendiriyoruz.
LoginFilter.java
import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Filter checks if LoginBean has loginIn property set to true. * If it is not set then request is being redirected to the login.xhml page. * * @author itcuties * */ public class LoginFilter implements Filter { /** * Checks if user is logged in. If not it redirects to the login.xhtml page. */ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // Get the loginBean from session attribute LoginBean loginBean = (LoginBean)((HttpServletRequest)request).getSession().getAttribute("loginBean"); // For the first application request there is no loginBean in the session so user needs to log in // For other requests loginBean is present but we need to check if user has logged in successfully if (loginBean == null || !loginBean.isLoggedIn()) { String contextPath = ((HttpServletRequest)request).getContextPath(); System.out.println(contextPath); ((HttpServletResponse)response).sendRedirect(contextPath + "/login.xhtml"); } chain.doFilter(request, response); } public void init(FilterConfig config) throws ServletException { // Nothing to do here! } public void destroy() { // Nothing to do here! } }
Yazının başında dediğim gibi Servlet taraflı bir iş yapıyoruz ve bu uygulamada bu işi LoginFilter sınıfı yapıyor. Buradaki doFilter metodu bir LoginBean nesnesini session özelliğinden cast işlemi ile alıyor. Eğer birisi daha önce girmişse o kişi için bir loginBean hazır tutlur fakat oturumu kapalı olduğu zamanlarda loggedIn değeri false yapılır, girdiği zaman dilimi içinde true yapılır. Girmemiş ise zaten loginBean null olacağı için oturum açılmaz. Eğer şartlar tamam olursa chain.doFilter() metodu ile gelen istek işlenir ve işlem tamamlanır. Diğer 2 metot bu uygulama için bir önem arzetmiyor.
NavigationBean sınıfı içinde sadece yönlendirme metotları olduğu için değinmemiz gereken bir nokta yok arkadaşlar.
Son olarak web.xml‘e değinmemiz gerekiyor.
Web.Xml
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> <display-name>JSFFilterOturumYonetimi</display-name> <welcome-file-list> <welcome-file>secured/welcome.xhtml</welcome-file> </welcome-file-list> <filter> <filter-name>LoginFilter</filter-name> <filter-class>LoginFilter</filter-class> </filter> <!-- Set the login filter to secure all the pages in the /secured/* path of the application --> <filter-mapping> <filter-name>LoginFilter</filter-name> <url-pattern>/secured/*</url-pattern> </filter-mapping> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.xhtml</url-pattern> </servlet-mapping> <context-param> <description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>client</param-value> </context-param> <context-param> <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name> <param-value>resources.application</param-value> </context-param> <listener> <listener-class>com.sun.faces.config.ConfigureListener</listener-class> </listener> <session-config> <session-timeout> 1 </session-timeout> </session-config> </web-app>
LoginFilter sınıfımızın uygulama ile birlikte çalışması ve Servlet taraflı bir iş yapması sebebi ile onu web.xml’e tanıtmamız gerekiyor. Bu tanıtma işlemlerini <filter></filter> ve <filter-mapping></filter-mapping> ile yapıyoruz. Dikkat etmemiz gereken nokta <filter-name></filter-name> etiketleri arasındaki kısmın hem filter hem de filter-mapping için aynı olması zorunluluğudur. <filter-class></filter-class> etiketi Filtre sınıfının adını (varsa paket yolu ile birlikte) veriyoruz. <url-pattern></url-pattern> ile de hangi url üstünde çalışacağını bildiriyoruz.
Yaznının başlarında verdiğim kaynakta olmayıp bu kodda olan bir kısım mevcut o da session-config bölümü. Bu bölüm ile oturumun süresini 1 dakika olarak belirledik. 1 dakika sonra sayfayı yenilediğinizde tekrar sizden kullanıcı adı şifre isteyecektir.
Ekran Çıktıları
Saat 14:24’de sayfaya giriş yaptım.
Saat 14:26’da sayfayı yenilediğimde oturumun sonlanmış olduğunu görüyor ve login sayfasına yönlendiriliyorum.
Bu yazıda da bu kadar arkadaşlar. Filter ile oturum yönetimini bu şekilde yapıyoruz. Başka bir yazıda görüşmek üzere esen kalın.
ne gerek var 500 satır kod yazmaya, java biliyorum diye her işe java’ı sokmak saçmalıktan başka bir şey değil, aynı şey php de 10 satır, kolay gelsin.
Merhaba;
PHP’de 10 satır olabilir ama PHP ve Java amaçları ve yaptıkları işler ile bambaşka 2 dünya. Karşılaştırmanız doğru olmamış.
Kolay gelsin.
Merhaba
LoginBean loginBean = (LoginBean)((HttpServletRequest)request).getSession().getAttribute(“loginBean”);
Bu satırda sakınca yaşıyorum. Açıkçası tam olarak idrak edemedim bu kodun getAttribute olarak neyi aldığına.
getAttribute(“loginBean”); bu kısımdaki “loginBean” ifadesi bizim managedBean classımızın adı mı ?
Benim managedBean in mbLogin adı altında ve şöyle kullanmaya çalıştığım zaman;
mbLogin login = (mbLogin) ((HttpServletRequest) request).getSession().getAttribute(“mbLogin”);
login ifadem debug ile baktığımda null geliyo ve doğal olarak Login.xhtml e yönlendiriyor. Neyi yanlış yapmış olabilirim bir fikriniz var mı ?
Merhabalar.
Managen Bean sınıfımızın adı “LoginBean”. “loginBean” ise managed bean sınıfının tanımlayıcısı. Managed Bean tanımlamalarında @ManagedBean ile işaretlediğiniz sınıflarda sınıf adı büyük harfle başlarken (L) managed bean tanımlayıcıları küçük harfle (l) başlar.
Sizin mbLogin ifadeniz eğer sınıf adı ise öncelikle sınıf isimlendirmesini kurala aykırı yapıp küçük harfle başlatmışsınız ama çalışmaması için bir sorun da yok gibi. Eğer mbLogin managed bean’in tanımlayıcısı ise onun yerine sınıfın adını kullanmanız gerekiyor.
GetAttribute metoduna verdiğimiz şey ise managed bean’in tanımlayıcısı.
Anlatamadığım bir yer var ise tekrar sorunuz lütfen.
Kolay Gelsin
Dediğinizi anladım ancak kod çalışmıyor. Ben aracı olarak bir NavigationBean kullanmadım işlemleri direk return login.xhtml şeklinde kullandım belki ondan çalışmıyodur diye düşündüm ancak şöyle bir sıkıntı var. Ben Maven projei açmadım(ki maven nedir onuda pek bilmiyorum) JSF projesi üzerinde bu kodlar bende çalışmadı ve sanırım çalışmama sebebi login() içerisinde biz bir session kaydı yapmıyoruz ve kaydetmediğimiz session ı getSession().getAttribute ile çağırmaya çalışıyoruz. Tabi kaydetmediğimiz için null döndürüyo. Ben sıkıntımı şöyle çözdüm aynı sıkıntıyı yaşayan arkadaşlar olursa bunu deniyebilirler;
Login metodumuzun içine ;
FacesContext context = FacesContext.getCurrentInstance();
HttpSession session = (HttpSession) context.getExternalContext().getSession(false);
session = (HttpSession) context.getExternalContext().getSession(true);
session.setAttribute(“login”, this);
ve logout un içine ;
FacesContext context = FacesContext.getCurrentInstance();
HttpSession session = (HttpSession) context.getExternalContext().getSession(false);
session = (HttpSession) context.getExternalContext().getSession(true);
session.setAttribute(“login”, null);
Şeklinde yaparsak bir sıkıntı olmadan kullanabildim. Bilginize sunarım ve ilginiz için teşekkürler, iyi çalışmalar