12. MVC [personne] web uygulaması – sürüm 7
12.1. Introduction
Bu sürümde, bazı istemci tarayıcılarının aşağıdakileri engellemiş olabileceğini varsayıyoruz:
- sunucunun gönderdiği çerezlerin geri gönderilmesini
- Görüntülenen HTML sayfalarında gömülü olan JavaScript kodunun çalıştırılmasını
Yine de bu tür tarayıcıların uygulamamızı kullanabilmesini istiyoruz. 2. madde bizi uygulamamızın 2. sürümüne geri götürüyor; zira JavaScript, 3. sürümden itibaren kullanılmaya başlanmıştı. 2. sürüm, uygulamayı JavaScript olmadan çalıştırıyordu; dolayısıyla 2. madde çözülmüş oluyor.
- madde, yönetilmesi zor ya da kolay olabilir. Uygulamamızın 6. sürümü çerezler olmadan çalışıyordu. 2. ve 6. sürümleri birleştirerek istenen sonucu elde ediyoruz. Ek bir kısıtlama daha ekleyeceğiz: uygulama bir oturumu yönetmelidir. Bu, anlamsız bir kısıtlama değildir. Kullanıcıların kimlik doğrulaması yapması gereken bir uygulamada, sunucu, kullanıcının her sayfa talebinde yeniden kimlik doğrulaması yapmasını önlemek için kullanıcının kullanıcı adı/şifre çiftini hatırlamalıdır.
Şimdiye kadar, istemci-sunucu iletişimi sırasında bilgileri saklamak için üç çözüm kullandık:
- oturum
- çerezler
- gizli alanlar.
İkinci çözüm, istemci tarayıcısının çerez kullanımını engellemiş olabileceği için elenebilir.
- çözüm, daha önce incelediğimiz sürüm 6'daki çözümdür. Güvenlik nedenleriyle bu çözüm kullanılamaz. Eğer (kullanıcı adı / şifre) çifti tarayıcıya gönderilen her sayfada kapsüllenmişse, bu, her istemci-sunucu iletişimi sırasında ağ üzerinden aktarıldığı anlamına gelir. Bu, uygulamanın güvenliği açısından iyi değildir. Bu durumda, istemci-sunucu iletişimini şifreleyen HTTPS protokolünü kullanmayı düşünebiliriz. Ancak bunu uygulamanın her sayfası için kullanmak sunucu yükünü artıracaktır.
Çözüm 1'i, yine çerezlere dayalı olduğu için elemek isteyebiliriz. İlk istemci-sunucu iletişimi sırasında sunucu, istemciye bir oturum jetonu gönderir ve istemci her yeni istekte bu jetonu sunucuya geri gönderir. Bu jeton sayesinde sunucu, istemcisini tanıyabilir ve önceki bir iletişim sırasında kaydettiği bilgileri ona atayabilir. Oturum jetonu, sunucu tarafından bir çerez içinde gönderilir. Çerezleri engellememiş olan tarayıcı, sonraki isteklerinde bu çerezi sunucuya geri gönderebilir. Çerezleri engellemişse, başka bir çözümü vardır: istediği URL’ye oturum jetonunu ekleyebilir. Şimdi, sürüm 4’teki [index.jsp] dosyasını incelemeye devam ederek bunu göreceğiz:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>
<c:redirect url="/main"/>
Yukarıdaki 5. satırın, istemciyi [/personne4/main?jsessionid=XX] URL’sine yönlendirdiğini hatırlatırız; burada XX, [http://localhost:8080/personne4] URL’sini talep ettikten sonra elde edilen aşağıdaki ekran görüntüsünde de görüldüğü gibi oturum jetonudur:

Oturum jetonu açısından <c:redirect> etiketinin işleyişini daha yakından inceleyelim. Çerezlerin kabul edildiği bir tarayıcı ele alalım. Aşağıda, Firefox tarayıcısını yapılandırıyoruz:

[1]'te çerezlere izin veriyoruz ve [2]'te bilinen bir durumdan yola çıkmak için mevcut çerezleri siliyoruz. Ardından [http://localhost:8080/personne4] URL'sini istiyoruz. Aşağıdaki yanıtı alıyoruz:

Müşterinin ilk HTTP isteği şöyleydi:
Müşterinin oturum çerezi göndermediğini belirtelim. Sunucu tarafından gönderilen HTTP yanıtı şöyledir:
- 1. satır: Sunucu, istemciden yeniden yönlendirilmesini ister
- 3. satır: Sunucu, [JSESSIONID] özniteliğiyle ilişkili bir oturum jetonu gönderir
- 4. satır: Yönlendirme URL'si oturum çerezini içerir. İstemci oturum çerezi göndermediği için <c:redirect> etiketi bunu URL'ye eklemiştir.
Yönlendirilmesi istenen tarayıcı, ardından şu isteği gönderdi:
- 1. satır: Yönlendirme URL’sini, oturum jetonu dahil olmak üzere ister. Bu nedenle ekran görüntüsünde tarayıcı bu URL’yi göstermektedir.
- 10. satır: Tarayıcı, önceki iletişimde sunucu tarafından kendisine gönderilen oturum jetonunu geri gönderir. Bu, istemci tarayıcısında çerezlere izin verildiğinde çerezlerin normal işleyişidir. Aksi takdirde, alınan çerezler geri gönderilmez.
Sunucu, bu ikinci isteğe şu yanıtı verdi:
İstenen sayfayı buldu ve gönderiyor. Artık oturum jetonunu göndermediğine dikkat edelim. Bu, oturum jetonunun normal işleyişidir: sunucu tarafından bir çerez şeklinde tarayıcıya tek seferlik olarak gönderilir ve tarayıcı, tanınmak için her istekte bunu geri gönderir.
Şimdi, aynı tarayıcıyla [http://localhost:8080/personne4] URL’sini elle yazarak tekrar isteyelim. Bunun üzerine şu sayfa karşımıza çıkar:

Tarayıcıda görüntülenen URL’nin artık oturum jetonunu içermediğini görüyoruz. İlk istemci-sunucu iletişimine bakalım:
Tarayıcı şu isteği gönderdi:
Bu, bir önceki seferkiyle tamamen aynı istektir, ancak bir fark vardır: 10. satırda, tarayıcı ilk iletişim sırasında aldığı oturum jetonunu geri gönderir. Yine, tarayıcının çerezleri etkinse bu normal bir durumdur.
Sunucu şu yanıtı gönderdi:
Sunucu, istemciden yeniden yönlendirilmesini ister. İstemciden bir oturum jetonu aldığı için oturumu devam ettirir ve yeni bir oturum jetonu göndermez. Aynı nedenden ötürü, <c:redirect> etiketi bu oturum jetonunu yönlendirme URL'sine dahil etmez. Bu nedenle, yukarıdaki ekran görüntüsünde gösterilen URL'de oturum jetonu bulunmamaktadır.
Tüm bunlardan çıkarılacak kural şudur: <c:redirect> etiketi, yalnızca istemci HTTP başlığını göndermediyse oturum jetonunu yönlendirme URL’sine dahil eder:
Bu kural, ileride ele alacağımız <c:url> etiketi için de geçerlidir.
Çerezlerin engellendiği bir tarayıcıda ne olur? Hadi deneyelim. Öncelikle tarayıcıyı sıfırlayalım:

[1] komutunda çerezleri devre dışı bırakıyoruz ve [2] komutunda, bilinen bir durumdan yola çıkmak için mevcut çerezleri siliyoruz. Ardından [http://localhost:8080/personne4] URL'sini çağırıyoruz. Şu yanıtı alıyoruz:

Daha önce elde ettiğimiz sonuçla aynı sonucu alıyoruz. Ancak HTTP adresindeki işlemler tam olarak aynı değil:
- 1-9. satırlar: Tarayıcının 1 numaralı isteği. Oturum çerezi göndermiyor.
- 11-17. satırlar: Sunucunun, tarayıcıyı başka bir URL'ye yönlendirmesini isteyen yanıtı. Bir oturum çerezi gönderir. 13. satır: <c:redirect> etiketi, 14. satırdaki yönlendirme URL'sine jetonu eklemiştir.
- satır 19-27: Tarayıcının 2 numaralı isteği. Çerezleri devre dışı olduğu için sunucunun az önce gönderdiği oturum çerezini geri göndermiyor.
- 29-33. satırlar: Sunucunun yanıtı. Tarayıcının oturum çerezi göndermemiş olmasına rağmen, beklendiği gibi yeni bir oturum başlatmadığı görülebilir. Bunu, 13. satırda yaptığı gibi HTTP [Set-Cookie] başlığını göndermemesinden anlayabiliriz. Bu, önceki oturumu sürdürdüğü anlamına gelir. Tarayıcının 19. satırda talep ettiği URL’de bulunan oturum jetonu sayesinde bu oturumu bulabilmiştir.
Sunucunun, istemci tarafından gönderilen oturum jetonunu iki farklı yolla alarak oturumu takip ettiğini unutmayalım:
- istemci tarafından gönderilen HTTP [Set-Cookie] başlığında
- istemci tarafından istenen URL'de
Şimdi, aynı tarayıcıyla, çerezlere izin verildiğinde yapıldığı gibi, [http://localhost:8080/personne4] URL'sini elle yazarak yeniden isteyelim. Bunun üzerine şu sayfa karşımıza çıkar:

Çerezlere izin verildiğinde elde edilen sonuçtan farklı bir sonuçla karşılaşıyoruz: oturum jetonu, tarayıcı tarafından görüntülenen URL’de yer alıyor. Gerçekleşen HTTP iletişimlerini incelemeden bu sonucu açıklayalım:
[cookies autorisés]
- [http://localhost:8080/personne4] URL'sine yapılan ikinci istek sırasında, istemci tarayıcısı aynı URL'ye yapılan ilk istek sırasında sunucudan aldığı oturum çerezini geri göndermişti. Dolayısıyla <c:redirect> etiketi, yönlendirme adresine oturum çerezini dahil etmemişti.
[cookies inhibés]
- [http://localhost:8080/personne4] URL'sine yapılan ikinci istek sırasında, istemci tarayıcısı çerezleri devre dışı olduğu için aynı URL'ye yapılan ilk istek sırasında sunucudan aldığı oturum çerezini göndermemiştir. Bu nedenle <c:redirect> etiketi, yönlendirme adresine oturum jetonunu ekler. İşte bu yüzden yukarıdaki ekran görüntüsünde bu jeton görülmektedir.
<c:redirect> ve <c:url> etiketleri, oturum jetonunun URL'lere eklenmesini sağlar. Burada önerilen çözüm budur.
12.2. Eclipse Projesi
[/personne7] web uygulamasının Eclipse projesi [mvc-personne-07]'i oluşturmak için, 6.2. paragrafında açıklanan prosedürü izleyerek [mvc-personne-06] projesini kopyalayacağız.
![]() | ![]() |
12.3. [personne7] web uygulamasının yapılandırılması
/personne7 uygulamasının web.xml dosyası şu şekildedir:
<?xml version="1.0" encoding="UTF-8"?>
...
<display-name>mvc-personne-07</display-name>
...
Bu dosya, web uygulamasının görüntüleme adının [mvc-personne-07] olarak değiştiği 3. satır dışında önceki sürümdekiyle aynıdır. [index.jsp] ana sayfası değişmez.
...
<c:redirect url="/do/formulaire"/>
12.4. Görünüm kodları
[formulaire, réponse, erreurs] görünümleri, JavaScript içermeyen sürüm 2'deki hallerine, yani c.a.d'e geri dönüyor. Ancak son sürümlerdeki JSTL etiketlerini koruyorlar.
12.4.1. [formulaire] görünümü

Javascript koduyla ilişkili düğmeler kaldırılmıştır.
[formulaire.jsp]:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>
<html>
<head>
<title>Personne - formulaire</title>
</head>
<body>
<center>
<h2>Personne - formulaire</h2>
<hr>
<form name="frmPersonne" action="<c:url value="validationFormulaire"/>" method="post">
<table>
<tr>
<td>Nom</td>
<td><input name="txtNom" value="${nom}" type="text" size="20"></td>
</tr>
<tr>
<td>Age</td>
<td><input name="txtAge" value="${age}" type="text" size="3"></td>
</tr>
<tr>
</table>
<table>
<tr>
<td><input type="submit" name="bouton" value="Envoyer"></td>
<td><input type="reset" value="Rétablir"></td>
<td><input type="submit" name="bouton" value="Effacer"></td>
</tr>
</table>
</form>
</center>
</body>
</html>
- 14. satır: POST'in hedef URL'si, istemcinin HTTP [Cookie] başlığını göndermeyen bir tarayıcı olması durumunda oturum jetonunun buraya eklenmesi için <c:url> etiketiyle yazılmıştır.
- Formda [submit] türünde iki düğme bulunmaktadır: [Envoyer] (28. satır) ve [Effacer] (30. satır). Her iki düğme de aynı adı taşımaktadır: bouton. POST düğmesine basıldığında, tarayıcı şu parametreyi gönderecektir:
- düğme=Gönder, eğer POST işlemi [Gönder] düğmesi tarafından tetiklenmişse
- POST işlemi [Sil] düğmesi tarafından tetiklenmişse: button=Sil
Bu parametre, yapılması gereken tam eylemi belirlememize yardımcı olacaktır; çünkü [/do/validationFormulaire] URL'si artık iki farklı eyleme karşılık gelmektedir.
12.4.2. [réponse] görünümü

[réponse.jsp]:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>
<html>
<head>
<title>Personne</title>
</head>
<body>
<h2>Personne - réponse</h2>
<hr>
<table>
<tr>
<td>Nom</td>
<td>${nom}</td>
</tr>
<tr>
<td>Age</td>
<td>${age}</td>
</tr>
</table>
<br>
<a href="<c:url value="retourFormulaire"/>">${lienRetourFormulaire}</a>
</body>
</html>
- 24. satır: HREF'in hedef URL'si, istemcinin HTTP [Cookie] başlığını göndermeyen bir tarayıcı olması durumunda oturum jetonunun buraya eklenmesi için <c:url> etiketiyle yazılmıştır.
12.4.3. [erreurs] görünümü

[erreurs.jsp]:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@ taglib uri="/WEB-INF/c.tld" prefix="c" %>
<html>
<head>
<title>Personne</title>
</head>
<body>
<h2>Les erreurs suivantes se sont produites</h2>
<ul>
<c:forEach var="erreur" items="${erreurs}">
<li>${erreur}</li>
</c:forEach>
</ul>
<br>
<a href="<c:url value="retourFormulaire"/>">${lienRetourFormulaire}</a>
</body>
</html>
- 18. satır: HREF'in hedef URL'si, istemcinin HTTP [Cookie] başlığını göndermeyen bir tarayıcı olması durumunda oturum jetonunun bu URL'de bulunması için <c:url> etiketiyle yazılmıştır.
Okuyucunun, önceki sürümlerde görülen ilkeye göre bu yeni görünümleri test etmesi önerilir.
12.5. [ServletPersonne] denetleyicisi
[/personne7] web uygulamasının [ServletPersonne] denetleyicisi şu şekildedir:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | |
- 35. satır: [/retourFormulaire] eylemi, önceki sürümde olduğu gibi bir POST tarafından değil, bir GET tarafından gerçekleştirilir.
- 70-87. satırlar: [/validationFormulaire] eylemi,[formulaire] görünümündeki [Envoyer] veya [Effacer] düğmelerinden birine tıklanmasıyla tetiklenir. [doValidationFormulaire] yöntemi, bu iki durumu iki farklı yöntemle işler.
- 90-103. satırlar: [doEnvoyer] yöntemi, önceki sürümdeki [doValidationFormulaire] yöntemine karşılık gelir. Girilen veriler oturuma kaydedilir (96-98. satırlar); oysa önceki sürümde bu veriler sorguya ekleniyordu.
- 58-67. satırlar: Yeni [doEffacer] yöntemi boş bir form görüntülemelidir. Bu işi zaten yapan [doInit] yönteminden yararlanılabilir. Burada, oturumun formun en son durumunu yansıtmaya devam etmesi için [nom, age] öğelerini de silme fırsatını değerlendiriyoruz.
- 50-55. satırlar: Bu görünümün şablonunu görünürde başlatmadan [formulaire] görünümünün görüntülenmesini ister. Bu şablon aslında oturumda zaten bulunan [nom, age] öğelerinden oluşur. Başka bir işlem yapmaya gerek yoktur.
12.6. Tests
Eclipse projesini [personne-mvc-07] entegre ettikten sonra Tomcat'i başlatın veya yeniden başlatın, ardından çerezleri devre dışı bırakılmış ve mevcut çerezler silinmiş bir tarayıcıyla [http://localhost:8080/personne7] URL'sini çağırın. Aşağıdaki yanıt alınır:

Tarayıcı tarafından alınan kaynak kodu şöyledir:
- satırda, oturum jetonu POST hedef URL'sinde yer almaktadır.
Formu dolduralım ve gönderelim:

Tarayıcı tarafından alınan kaynak kodu şöyledir:
- satırda, oturum jetonu bağlantının hedef URL'sinde yer almaktadır.

