Mvc ile MsSQL kullanarak rol tabanlı yetkilendirme

Projemizde kullanıcı oluşturma , kullanıcı girişi ve rol tabanlı yetkilendirme olayları Mssql veritabanıyla çalışacak şekilde kullanılacaktır. Yeni bir mvc projesi  oluşturuyoruz. Projemizin kullanıcı girişi olmayacak şekilde girişi oluşturuyoruz. Daha sonra referanslar kısmından Add Reference diyoruz.

Assemblies -> Extensions yolunu izleyerek webmatrix i aratıyoruz.

Webmatrix ve webmatrix.data seçeneklerinin ikisinide yüklüyoruz.

Referanslar kısmında bu yüklediğimiz nesnelerin ayarlarına geliyoruz ve ikisi içinde copy local seçeneklerini true yapıyoruz.

Şimdi projemize başlayalım. AccountController oluşturuyoruz. aşağıdaki gibi olmasını sağlıyoruz.

public class AccountController : Controller
{
public ActionResult Login()
{
return View();
}
public ActionResult Register()
{
return View();
}
}

Daha sonra Web.config dosyasına geliyoruz. </system.web></system.web> etiketleri içinde en alta aşağıdaki kısımlar ekliyoruz.

<membership defaultProvider=”SimpleMembershipProvider”>
<providers>
<clear />
<add name=”SimpleMembershipProvider” type=”WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData”/>
</providers>
</membership>
<roleManager enabled=”true” />
</system.web>

Şimdi Mssql içinde SimpleMemberShip adıyla bir veritabanı oluşturuyoruz . Server explorerda bu veritabanına bağlantı yapıyoruz. Eklenen databasein ayarlarına geliyoruz ve connectionstring değerini kopyalıyoruz.

web.config dosyasında <configuration></configuration> içinde en alta aşağıdaki satırlar eklenir.

<connectionStrings>
<add name=”VarsayilanBaglanti” connectionString=”Data Source=ERENALI\MSSQL;Initial Catalog=SimpleMemberShip;Integrated Security=True” providerName=”System.Data.SqlClient”  />
</connectionStrings>

Şimdi Global.asax dosyasına gidiyoruz. Application_start classı içine ağaıdaki kısmı ekliyoruz.

WebSecurity.InitializeDatabaseConnection(“VarsayilanBaglanti”,”UserProfile”,”UserId”,”Username”,true);

Sayfamızı çalıştırdığımızda Güvenlik saydamlığıyla ilgili Hata ile karşılaşıyoruz. Hatayı gidermek için Package Manager Console a girilerek aşağıdaki yüklemeler sağlanır. Bu yükleme işlemi sorunu giderecektir.

Install-Package Microsoft.AspNet.WebHelpers

Install-Package Microsoft.AspNet.WebPages.Data

 

Veritabanına bakıldığında yetkilendirme ve girişlerde kullanacağımız yeni tabloların oluştuğu görülür.

Models klasöründe add-> class diyerek Login ve Register modellerini oluşturuyoruz.

public class Login
{
public string Username { get; set; }
public string Password { get; set; }
}
public class Register
{
public string Username { get; set; }
public string Password { get; set; }
}

Contollerdaki Login actionnınin viewini oluşturuyoruz.

Login.cshtml

@using SimpleMemberShip.Models
@model Login
@{  ViewBag.Title = “Login”;  }
<h2>Kullanıcı Adınız :</h2>
<div>
@using(@Html.BeginForm())
{
@Html.AntiForgeryToken()
<label>Kullanıcı Adınız:</label>
@Html.TextBoxFor(m => m.Username,new{@class=”form-control”}) //form-control güzel bir fomr olarak görünmesini sağlıyor.
<label>Parolanız:</label>
@Html.TextBoxFor(m => m.Password, new{@class = “form-control” })
<br />
<button class=”btn btn-primary”>Giriş Yap</button>
}
</div>

Register viewi oluşturuldu. Register.cshtml

@using SimpleMemberShip.Models
@model Register
@{
ViewBag.Title = “Register”;
}
<h2>Yeni Üye Oluştur</h2>
<div>
@using (@Html.BeginForm())
{
@Html.AntiForgeryToken()
<label>Kullanıcı Adınız:</label>
@Html.TextBoxFor(m => m.Username, new { @class = “form-control” }) //form-control güzel bir fomr olarak görünmesini sağlıyor.
<label>Parolanız:</label>
@Html.TextBoxFor(m => m.Password, new { @class = “form-control” })
<br />
<button class=”btn btn-primary”>Üye Ol</button>
}
</div>

 

Controller tarafı da aşağıdaki gibi düzenlendi.

using SimpleMemberShip.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace SimpleMemberShip.Controllers
{
public class AccountController : Controller
{
[HttpGet]
public ActionResult Login()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Login(Login logindata)
{
if (ModelState.IsValid)
{
WebSecurity.Login(logindata.Username, logindata.Password);
return RedirectToAction(“Index”, “Home”);
}
ModelState.AddModelError(“”, “Şifre yada kullanıcı adı geçersiz.”);
return View(logindata);
}
}
}
[HttpGet]
public ActionResult Register()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Register(Login registerdata)
{
if (ModelState.IsValid)
{
WebSecurity.CreateUserAndAccount(registerdata.Username, registerdata.Password);
return RedirectToAction(“Index”, “Home”);
}
ModelState.AddModelError(“”, “Bu kullanıcı adı kullanılıyor.”);
return View(registerdata);
}

Daha sonra logout actionını controllerda oluşturuyoruz.

public ActionResult Logout()
{   WebSecurity.Logout();
return RedirectToAction(“Index”, “Home”);
}

Menülerde giriş yaptıysa çıkış menüsünü yoksa kaydol ve giriş yap seçeneğini göstermek için _Layout.cshtml dosyasında aşağıdaki düzenlemeyi yapıyoruz.

<li>@Html.ActionLink(“Home”, “Index”, “Home”)</li>
<li>@Html.ActionLink(“About”, “About”, “Home”)</li>
<li>@Html.ActionLink(“Contact”, “Contact”, “Home”)</li>
@{
if (User.Identity.IsAuthenticated)
{
<li>@Html.ActionLink(“Çıkış Yap”, “Logout”, “Account”)</li>
<li><strong style=”color:white”>@User.Identity.Name</strong></li>
}
else
{
<li>@Html.ActionLink(“Giriş Yap”, “Login”, “Account”)</li>
<li>@Html.ActionLink(“Kayıt Ol”,”Register”,”Account”)</li>
}
}

Bu şekilde giriş yapınca kullanıcı adını gösterip  çıkış yap seçeneğini gösterebiliyoruz.

Giriş de hata olsa da olmasa da ana sayfaya yönlendiriyor bu hatayı gidermek için

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Login(Login logindata)
{
if (ModelState.IsValid)
{
if (WebSecurity.Login(logindata.Username, logindata.Password))
{
return RedirectToAction(“Index”, “Home”);
}
else
{
ModelState.AddModelError(“”, “Şifre yada kullanıcı adı geçersiz.”);
return View(logindata);
}
}
ModelState.AddModelError(“”, “Şifre yada kullanıcı adı geçersiz.”);
return View(logindata);
}

Controllerı bu şekilde düzeltiyoruz. Login viewi ne de @Html.ValidationSummary() Kontrolunu ekliyoruz. ki oluşan hatayı gösterebilelim.

@using SimpleMemberShip.Models
@model Login
@{
ViewBag.Title = “Login”;
}
<h2>Kullanıcı Adınız</h2>
<div>
@using(@Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.ValidationSummary()
<label>Kullanıcı Adınız:</label>
@Html.TextBoxFor(m => m.Username,new{@class=”form-control”}) //form-control güzel bir fomr olarak görünmesini sağlıyor.
<label>Parolanız:</label>
@Html.TextBoxFor(m => m.Password, new{@class = “form-control” })
<br />
<button class=”btn btn-primary”>Giriş Yap</button>
}
</div>

Aynı şekilde register sırasında oluşan bir hata için de düzenleme yaparsak controller aşağıdaki şekilde olur.

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Register(Register registerdata)
{
if (ModelState.IsValid)
{
try
{
WebSecurity.CreateUserAndAccount(registerdata.Username, registerdata.Password);
return RedirectToAction(“Index”, “Home”);
}
catch (MembershipCreateUserException exception)
{
ModelState.AddModelError(“”, “Bu kullanıcı adı için geç kaldınız.”);
return View(registerdata);
}
}
ModelState.AddModelError(“”, “Bu kullanıcı adı için geç kaldınız.”);
return View(registerdata);
}

viewi de ise aşağıdaki şekilde kodlamalıyız.

<div>
@using (@Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.ValidationSummary()
<label>Kullanıcı Adınız:</label>
@Html.TextBoxFor(m => m.Username, new { @class = “form-control” }) //form-control güzel bir fomr olarak görünmesini sağlıyor.
<label>Parolanız:</label>
@Html.TextBoxFor(m => m.Password, new { @class = “form-control” })
<br />
<button class=”btn btn-primary”>Üye Ol</button>
}
</div>

 

Menülerden hangilerinin kullanıcı girişinden sonra açılmasını istiyorsak.

Controllardaki actionının hemen üstüne [Authorize]  Satırını eklemeliyiz.

[Authorize]
public ActionResult About()
{

Daha sonra yönlendirme yapabilmesi için yani hakkında menüsüne tıkladığımızda karşımıza kullanıcı girişi geldi fakat giriş yaptıktan sonra hakkında menüsü yerine anasayfaya yönlendiriliyoruz . Bunu engellemek için Login actionını aşağıdaki gibi değiştimemiz gerekmektedir.

public ActionResult Login(Login logindata,string ReturnUrl)
{
if (ModelState.IsValid)
{
if (WebSecurity.Login(logindata.Username, logindata.Password))
{
if (ReturnUrl != null)
{
return Redirect(ReturnUrl);
}
return RedirectToAction(“Index”, “Home”);
}
else
{
ModelState.AddModelError(“”, “Şifre yada kullanıcı adı geçersiz.”);
return View(logindata);
}
}
ModelState.AddModelError(“”, “Şifre yada kullanıcı adı geçersiz.”);
return View(logindata);
}

Bundan sonra kayıt olurken role tanımlanması istenirse. Veritabanındaki roles tablosuna tanımlamalar yapıldıktan sonra View de aşağıdaki gibi bir dropdownlist ve bir list objesi oluşturmamız gerekir. List içersinde tanımlama yapılırken görüntülenmesi istenen roleler yazılır.

@using SimpleMemberShip.Models
@model Register
@{
ViewBag.Title = “Register”;
List<SelectListItem> roles = new List<SelectListItem>()
{
new SelectListItem()
{
Text=”yönetici”,
Value=”yonetici”
},new SelectListItem()
{
Text=”kullanıcı”,
Value=”kullanici”
},new SelectListItem()
{
Text=”deneme”,
Value=”deneme”
}
};
}
<h2>Yeni Üye Oluştur</h2>
<div>
@using (@Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.ValidationSummary()
<label>Kullanıcı Adınız:</label>
@Html.TextBoxFor(m => m.Username, new { @class = “form-control” }) //form-control güzel bir fomr olarak görünmesini sağlıyor.
<label>Parolanız:</label>
@Html.TextBoxFor(m => m.Password, new { @class = “form-control” })
<br />
@Html.DropDownList(“role”, roles,”Rolünüzü Seçiniz”);
<br /><br />
<button class=”btn btn-primary”>Üye Ol</button>
}
</div>

Daha sonra kontroller tarafında Roles.AddUserToRole(registerdata.Username, role);  komutu ile rolün veritabanına kaydı sağlanır.

public ActionResult Register(Register registerdata,string role)
{
if (ModelState.IsValid)
{
try
{
WebSecurity.CreateUserAndAccount(registerdata.Username, registerdata.Password);
Roles.AddUserToRole(registerdata.Username, role);
return RedirectToAction(“Index”, “Home”);
}
catch (MembershipCreateUserException exception)
{
ModelState.AddModelError(“”, “Bu kullanıcı adı için geç kaldınız.”);
return View(registerdata);
}
}
ModelState.AddModelError(“”, “Bu kullanıcı adı için geç kaldınız.”);
return View(registerdata);
}

Eğer role göre giriş yetkisi vermek istersek kontoller kısmında istediğimi actionın hemen üstüne [Authorize(Roles=”yonetici”)]  şeklinde bir kural yerleştirebiliriz. Sadece yonetici olan kullanıcılar giriş yapabilirler.

 

Bu şekilde basit anlamda role tabanlı bir yetkilendirme süzeni kurmuş olduk.