Öncelikle kullanıcı kayıt ve giriş işlemlerinde kullanacağımız ViewModellerimizi tanımlayalım.
RegisterModel.cs
using System.ComponentModel.DataAnnotations; namespace MvcProject.Website.Models.AccountModels { public class RegisterModel { [StringLength(150, ErrorMessage = "{0} alanı en fazla {1}, en az {2} karakter uzunluğunda olmalıdır!", MinimumLength = 3)] [Required(ErrorMessage = "{0} alanı gereklidir!")] [Display(Name = "Kullanıcı Adı")] [System.Web.Mvc.Remote("ValidateUserName", "Account")] public string UserName { get; set; } [StringLength(50, ErrorMessage = "{0} alanı en fazla {1}, en az {2} karakter uzunluğunda olmalıdır!", MinimumLength = 3)] [Required(ErrorMessage = "{0} alanı gereklidir!")] [DataType(DataType.Password)] [Display(Name = "Şifre")] public string Password { get; set; } [System.Web.Mvc.Compare("Password", ErrorMessage = "İki şifre eşleşmiyor!")] [Display(Name = "Şifre Tekrar")] [DataType(DataType.Password)] public string ConfirmPassword { get; set; } [StringLength(150, ErrorMessage = "{0} alanı en fazla {1} karakter uzunluğunda olmalıdır!")] [Required(ErrorMessage = "{0} alanı gereklidir!")] [EmailAddress(ErrorMessage = "{0} geçersiz!")] [Display(Name = "E-Posta")] [System.Web.Mvc.Remote("ValidateEmail", "Account")] public string Email { get; set; } } }
LoginModel.cs
using System.ComponentModel.DataAnnotations; namespace MvcProject.Website.Models.AccountModels { public class LoginModel { [StringLength(150, ErrorMessage = "{0} alanı en fazla {1} karakter uzunluğunda olmalıdır!")] [Required(ErrorMessage = "{0} alanı gereklidir!")] [Display(Name = "Kullanıcı Adı")] public string UserName { get; set; } [StringLength(50, ErrorMessage = "{0} alanı en fazla {1}, en az {2} karakter uzunluğunda olmalıdır!", MinimumLength = 3)] [Required(ErrorMessage = "{0} alanı gereklidir!")] [DataType(DataType.Password)] [Display(Name = "Şifre")] public string Password { get; set; } [Display(Name = "Beni Hatırla?")] public bool RememberMe { get; set; } } }
Yine BaseController sınıfından kalıtım alan bir AccountController sınıfı ekliyoruz. AccountController sınıfımızın içeriği aşağıdaki gibidir. Şimdilik kodların hepsini yazıyorum, tek tek açıklamasını yazacağım. Ayrıca User sınıfına bazı özelliklerde ekledim (LastLoginDate, LastIp, ...). Bunlar çok önemli değil, projemizi etkileyecek değişikliler değil.
using System; using System.Text.RegularExpressions; using System.Web.Mvc; using System.Web.Security; using MvcProject.Core.Domain.Entity; using MvcProject.Data.UnitOfWork; using MvcProject.Service.Users; using MvcProject.Web.Models.AccountModel; namespace MvcProject.Web.Controllers { public class AccountController : BaseController { private readonly IUserService _userService; public AccountController(IUserService userService, IUnitOfWork uow) : base(uow) { _userService = userService; } public ActionResult Register() { return View(); } [HttpPost] public ActionResult Register(RegisterModel model) { if (ModelState.IsValid) { try { User user = new User { ConfirmationId = Guid.NewGuid(), DisplayName = model.UserName, IsConfirmed = false, LastLoginDate = DateTime.Now, LastLoginIp = Request.UserHostAddress, Password = model.Password, ProfileImageUrl = "Content/Images/no_profile_image.png", Email = model.Email, UserName = model.UserName, IsActive = false, IsEditable = true, IsDeletable = true }; _userService.Insert(user); _uow.SaveChanges(); _userService.SendConfirmationMail(user.Id, user.Email, Request.Url.GetLeftPart(UriPartial.Authority)); return RedirectToAction("Index", "Home"); } catch (Exception ex) { ModelState.AddModelError("", "Kullanıcı oluşturma başarısız!"); } } return View(model); } public ActionResult Login(string ReturnUrl) { ViewBag.ReturnUrl = ReturnUrl; return View(); } [HttpPost] public ActionResult Login(LoginModel model, string ReturnUrl) { var user = _userService.ValidateUser(model.UserName, model.Password); if (ModelState.IsValid && user != null) { if (!user.IsConfirmed) { TempData["EpostaOnayMesaj"] = "E-posta adresiniz onaylı değildir. Lütfen e-posta adresinizdeki linki kullanarak e-posta adresinizi onaylayınız."; return View(); } FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe); return RedirectToLocal(ReturnUrl); } else { ModelState.AddModelError("", "Kullanıcı adı ve ya şifre geçersiz!"); } return View(model); } // RegisterModel içerisindeki Email alanını // RemoteAttribute ile kontrol eder public JsonResult ValidateEmail(string Email) { var result = _userService.ValidateEmail(Email); if (result) { return Json("Girdiğiniz e-posta adresi sistemde zaten mevcut!", JsonRequestBehavior.AllowGet); } return Json(!result, JsonRequestBehavior.AllowGet); } // RegisterModel içerisindeki UserName alanını // RemoteAttribute ile kontrol eder public JsonResult ValidateUserName(string UserName) { var result = _userService.ValidateUserName(UserName); if (result) { return Json("Girdiğiniz kullanıcı adı sistemde zaten mevcut!", JsonRequestBehavior.AllowGet); } return Json(!result, JsonRequestBehavior.AllowGet); } public ActionResult LogOff() { FormsAuthentication.SignOut(); return RedirectToAction("Index", "Home"); } public ActionResult ConfirmUser(Guid confirmationId) { if (string.IsNullOrEmpty(confirmationId.ToString()) || (!Regex.IsMatch(confirmationId.ToString(), @"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}"))) { TempData["EpostaOnayMesaj"] = "Hesap geçerli değil. Lütfen e-posta adresinizdeki linke tekrar tıklayınız."; return View(); } else { var user = _userService.Find(confirmationId); if (!user.IsConfirmed) { user.IsConfirmed = true; _userService.Update(user); _uow.SaveChanges(); FormsAuthentication.SetAuthCookie(user.UserName, true); TempData["EpostaOnayMesaj"] = "E-posta adresinizi onayladığınız için teşekkürler. Artık sitemize üyesiniz."; return RedirectToAction("Wellcome"); } else { TempData["EpostaOnayMesaj"] = "E-posta adresiniz zaten onaylı. Giriş yapabilirsiniz."; return RedirectToAction("Login"); } } } public ActionResult Wellcome() { return View(); } #region private methods private ActionResult RedirectToLocal(string returnUrl) { if (Url.IsLocalUrl(returnUrl)) { return Redirect(returnUrl); } else { return RedirectToAction("Index", "Home"); } } #endregion protected override void Dispose(bool disposing) { _uow.Dispose(); base.Dispose(disposing); } } }
AccountController içerisindeki bazı metodlar, önceki yazılarda paylaştığım userService içerisinde yok. Örneğin, _userService.ValidateUserName, userService.ValidateEmail gibi. Gerekli metodları kendiniz ekleyebilirsiniz. Ben sadece e-posta gönderen metodu yazayım;
/// <summary> /// Yeni üye olan kullanıcıya onay mesajı gönder. /// </summary> /// <param name="p1"></param> /// <param name="p2"></param> public void SendConfirmationMail(int userId, string email, string ConfirmationUrl) { var user = Find(userId); string confirmationId = user.ConfirmationId.ToString(); ConfirmationUrl += "/Account/ConfirmUser?confirmationId=" + confirmationId; var message = new MailMessage("info@belleksizintisi.com", email) { Subject = "Lütfen e-posta adresinizi onaylayınız.", Body = ConfirmationUrl }; var client = new SmtpClient(); client.Send(message); }
Gerekli web.config ayarı:
<configuration><system.net><mailSettings><smtp deliveryMethod="Network"><network host="smtp.gmail.com"port="587"userName="xxx@gmail.com"password="sifre"enableSsl="false"/></smtp></mailSettings></system.net>...</configuration>
Login.cshtml
@model MvcProject.Website.Models.AccountModels.LoginModel @{ ViewBag.Title = "Kullanıcı Girişi"; } @section Scripts { @Scripts.Render("~/bundles/jqueryval") } <div class="row"> <div class="col-md-12"> @using (Html.BeginForm()) { @Html.AntiForgeryToken() <div class="form-horizontal"> <h4>Kullanıcı Girişi</h4> <hr /> @Html.ValidationSummary(true) @TempData["EpostaOnayMesaj"] <div class="form-group"> @Html.LabelFor(model => model.UserName, new { @class = "col-md-2" }) <div class="col-md-10"> @Html.TextBoxFor(model => model.UserName, new { @class = "form-control" }) @Html.ValidationMessageFor(model => model.UserName) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Password, new { @class = "col-md-2" }) <div class="col-md-10"> @Html.PasswordFor(model => model.Password, new { @class = "form-control" }) @Html.ValidationMessageFor(model => model.Password) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.RememberMe, new { @class = "col-md-2" }) <div class="col-md-10"> @Html.EditorFor(model => model.RememberMe) @Html.ValidationMessageFor(model => model.RememberMe) </div> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="Giriş Yap" class="btn btn-default" /> </div> </div> </div> } <div> Hesabınız yoksa lütfen @Html.ActionLink("Kayıt Olunuz", "Register") </div> </div> </div>
Register.cshtml
@model MvcProject.Website.Models.AccountModels.RegisterModel @{ ViewBag.Title = "Kullanıcı Kaydı"; } @section Scripts { @Scripts.Render("~/bundles/jqueryval") } @using (Html.BeginForm()) { @Html.AntiForgeryToken() <div class="form-horizontal"> <h4>Kullanıcı Kaydı</h4> <hr /> @Html.ValidationSummary(true) <div class="form-group"> @Html.LabelFor(model => model.UserName, new { @class = "col-md-2" }) <div class="col-md-10"> @Html.TextBoxFor(model => model.UserName, new { @class = "form-control" }) @Html.ValidationMessageFor(model => model.UserName) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Password, new { @class = "col-md-2" }) <div class="col-md-10"> @Html.PasswordFor(model => model.Password, new { @class = "form-control" }) @Html.ValidationMessageFor(model => model.Password) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.ConfirmPassword, new { @class = "col-md-2" }) <div class="col-md-10"> @Html.PasswordFor(model => model.ConfirmPassword, new { @class = "form-control" }) @Html.ValidationMessageFor(model => model.ConfirmPassword) </div> </div> <div class="form-group"> @Html.LabelFor(model => model.Email, new { @class = "col-md-2" }) <div class="col-md-10"> @Html.TextBoxFor(model => model.Email, new { @class = "form-control" }) @Html.ValidationMessageFor(model => model.Email) </div> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="Kayıt Ol" class="btn btn-default" /> </div> </div> </div> } <div> Hesabınız varsa lütfen @Html.ActionLink("Giriş Yapınız", "Login") </div>
Wellcome.cshtml
@{ ViewBag.Title = "Hoş Geldiniz"; } <h2>Hoşgeldiniz</h2> <hr /> <div> @TempData["EpostaOnayMesaj"] </div>
Üyelik için gerekli olan controllerlar ve view sayfalarımız hazır. Bu hali ile kullanıcı kaydı yapılır, kullanıcıya onay mesajı gönderilir. Kullanıcı onay mesajına tıklayınca üyeliği aktif olur. Buraya kadar herşey tamam gibi görünüyor.
Peki, kullanıcını için AuthorizeAttribute nesnesini nasıl kontrol edeceğiz. Bu hali ile giriş yapan kullanıcının yetkili oldugu controller metodları belirlenebilir. Ama kullanıcının rollerini, o rolde olup olmadıgını nasıl kullanacagız. Makalelerin başında da söylemiştim, kendi üyelik ve rol sistemimizi kullanacagız.
Bunun için MembershipProvider ve RoleProvider sınıflarından kalıtım alarak üyelik sistemimizi yazacağız. Ben projenin kök dizini içerisinde Application/Membership diye bir klasör, açtım ve sınıfları buraya yazacağım.
CustomMembershipProvider.cs
public class CustomMembershipProvider : MembershipProvider { public static IUserService _userService { get { return DependencyResolver.Current.GetService<UserService>(); } } public override bool ValidateUser(string userName, string password) { return _userService.FindByUserNameAndPassword(userName, password) == null ? false : true; } #region not imlemented public override string ApplicationName { get { throw new System.NotImplementedException(); } set { throw new System.NotImplementedException(); } } public override bool ChangePassword(string username, string oldPassword, string newPassword) { throw new System.NotImplementedException(); } public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer) { throw new System.NotImplementedException(); } public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status) { throw new System.NotImplementedException(); } public override bool DeleteUser(string username, bool deleteAllRelatedData) { throw new System.NotImplementedException(); } public override bool EnablePasswordReset { get { throw new System.NotImplementedException(); } } public override bool EnablePasswordRetrieval { get { throw new System.NotImplementedException(); } } public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords) { throw new System.NotImplementedException(); } public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords) { throw new System.NotImplementedException(); } public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords) { throw new System.NotImplementedException(); } public override int GetNumberOfUsersOnline() { throw new System.NotImplementedException(); } public override string GetPassword(string username, string answer) { throw new System.NotImplementedException(); } public override MembershipUser GetUser(string username, bool userIsOnline) { throw new System.NotImplementedException(); } public override MembershipUser GetUser(object providerUserKey, bool userIsOnline) { throw new System.NotImplementedException(); } public override string GetUserNameByEmail(string email) { throw new System.NotImplementedException(); } public override int MaxInvalidPasswordAttempts { get { throw new System.NotImplementedException(); } } public override int MinRequiredNonAlphanumericCharacters { get { throw new System.NotImplementedException(); } } public override int MinRequiredPasswordLength { get { throw new System.NotImplementedException(); } } public override int PasswordAttemptWindow { get { throw new System.NotImplementedException(); } } public override MembershipPasswordFormat PasswordFormat { get { throw new System.NotImplementedException(); } } public override string PasswordStrengthRegularExpression { get { throw new System.NotImplementedException(); } } public override bool RequiresQuestionAndAnswer { get { throw new System.NotImplementedException(); } } public override bool RequiresUniqueEmail { get { throw new System.NotImplementedException(); } } public override string ResetPassword(string username, string answer) { throw new System.NotImplementedException(); } public override bool UnlockUser(string userName) { throw new System.NotImplementedException(); } public override void UpdateUser(MembershipUser user) { throw new System.NotImplementedException(); } #endregion }
CustomRoleProvider.cs
public class CustomRoleProvider : RoleProvider { public static IRoleService _roleService { get { return DependencyResolver.Current.GetService<RoleService>(); } } public override bool IsUserInRole(string userName, string roleName) { return _roleService.IsUserInRole(userName, roleName); } public override string[] GetRolesForUser(string username) { return _roleService.GetRolesByUserName(username).Select(x => x.RoleName).ToArray<string>(); } #region not implemented public override void AddUsersToRoles(string[] usernames, string[] roleNames) { throw new System.NotImplementedException(); } public override string ApplicationName { get { throw new System.NotImplementedException(); } set { throw new System.NotImplementedException(); } } public override void CreateRole(string roleName) { throw new System.NotImplementedException(); } public override bool DeleteRole(string roleName, bool throwOnPopulatedRole) { throw new System.NotImplementedException(); } public override string[] FindUsersInRole(string roleName, string usernameToMatch) { throw new System.NotImplementedException(); } public override string[] GetAllRoles() { throw new System.NotImplementedException(); } public override string[] GetUsersInRole(string roleName) { throw new System.NotImplementedException(); } public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames) { throw new System.NotImplementedException(); } public override bool RoleExists(string roleName) { throw new System.NotImplementedException(); } #endregion }
Sadece AuthorizeAttributte nesnesinin kullandıgı metodların içerisini doldurdum. Şimdi bu iki sınıfı üyelik sistemi olarak kullanabilmek için web.config ayarlarını yapalım.
<configuration> <appSettings> <add key="webpages:Version" value="3.0.0.0" /> <add key="webpages:Enabled" value="false" /> <add key="ClientValidationEnabled" value="true" /> <add key="UnobtrusiveJavaScriptEnabled" value="true" /> </appSettings> <system.web> <compilation debug="true" targetFramework="4.5" /> <httpRuntime targetFramework="4.5" /> <authentication mode="Forms"> <forms loginUrl="~/Account/Login" timeout="2880" /> </authentication> <profile defaultProvider="DefaultProfileProvider"> <providers> <add name="DefaultProfileProvider" type="System.Web.Providers.DefaultProfileProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="DefaultConnection" applicationName="/" /> </providers> </profile> <membership defaultProvider="CustomMembershipProvider"> <providers> <add name="CustomMembershipProvider" type="MvcProject.Website.Application.Membership.CustomMembershipProvider" connectionStringName="DefaultConnection" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" /> </providers> </membership> <roleManager defaultProvider="CustomRoleProvider" enabled="true"> <providers> <add name="CustomRoleProvider" type="MvcProject.Website.Application.Membership.CustomRoleProvider" connectionStringName="DefaultConnection" applicationName="/" /> </providers> </roleManager>
....
Uygulamanın üyelik sistemide artık bitmiştir. Kodları elimden geldiği kadar anlaşılır yazmaya çalıştım. Umarım eksik bir yer kalmamıştır. Eksik ve fazlaları geri dönüşlere göre değiştirmeye çalışıyorum. Bende çoğu şeyi yazarken öğreniyorum. Yakalayamadığım yerler olabiliyor. Bunlarıda beraber çözmeye çalışıyoruz.
Bu arada, proje başladığı gibi gitmiyor, bazen değiştiriyorum. Gereksiz bir şeyler varsa çıkarıyorum, eklemem gereken bir şeyler ve ya yenilikler olursa ekliyorum. Kritik değişimler değil bunlar. Projeye devam ederken kendinizin yakalayacağı ve değişikliği kendinizin yapacağı değişiklikler. Çok yapısal bir değişiklik olursa onu da belirtirim.
Sonraki makalelerde, kullanıcının profilini düzenleme, fileupload gibi konuları anlatmaya çalışacağım. Makale uzamazsa, aynı makalede area kavramına ve admin area kısmına girişte yapabiliriz.
Makalelerin geç kalmasından dolayı kusura bakmayın.
İyi çalışmalar...
çalışmalarınızı çok başarılı buluyorum.. çalışmalarınız sayesinde mvc'nin inceliklerini kavramaya çalıyorum...
YanıtlaSilMembershipProvider tasarımında Web.Config yapılandırmasını bir türlü yapamadım.. siszin haber portal örneğiniz ve bu makalenizden takip ederek yaptım fakat çalıştıramıyorum... öncelikli yüklenmesi gereken eklentiler var diyor. stackoverflow dan da baktığımda type namespace hatası olabileceğini anladım fakat bir türlü çalıştıramadım... sizin bir öneriniz varmıdır. şimdiden teşlekür ederim...
Nasıl bir hata alıyorsunuz? Hata mesajları var mı? Varsa nedir? Hatanızla alakalı stacoverflow da buldugunuz sorunların linkini yazar mısınız...
SilÖncelikle ilginize teşekür ederim.. sizin kullandığınız yapıda aşağıdaki gibi bir tanımlama vardı. bende kullanmak istedim. xxxxx ile ifade edilen yer üyelik sağlayıcımızı iifade ediyor. fakat bir türlü çalışmadı .
YanıtlaSilStackoverflow ve benzeri siitelerde araştırmamda aşağıdaki gibi bir tanımlama yapmam gerektiğini söylüyorlardı. ayrıca üyelik sağlayıcıyı namespace tanımlaması yapmadan kullandım. UyelikSaglayici sınıfını kök dizine koydum ayrıca type kısmında sınıf, proje ismi şeklinde yapınca çalıştı. proje ismi Guvenlik. aşağıdaki yapı ile çalıştı. İlginize tekrar teşekür ederim.. Çalışmalarınızın devamını dilerim..
Yazılar cıkmamıs ama, sorunun cözülmüş olması iyi. Teşekkürler...
SilGerçekten başarılı validationlar için FluentValidation kullanılabilir ben çok beğeniyorum. Projede dil yapısıda olacak mı ? Diğer makale için sabırsızlanıyorum.
YanıtlaSilMulti Language bir proje olacak
SilHocam Baştan sona Kadar Video olarak da çekme ve yayınlama sansımız var mı ?
SilElinize saglik hocam cok iyi gidiyorsunuz benim konu disi bir sorum olucak kullanici yetkilendirme ile ilgili, membership yapisini kullanmiyorum kendi kullancilari bir tabloda tutup session kontrolu ile yetkilendirme yapiyorum merak ettigim yanlis mi yapiyorum sadece session kontrolu yapmak guvenlimi membership kontrolleri nasil calisiyor session dan extra guvenlik kontrolu varmi bu konu hakkinda goruslerinizi alabilirsem cok sevinicem.
YanıtlaSilSession da bir yöntem, kullanılabilir. Fakat yönetimi nasıl olur onu bilmiyorum. Yani her yerde ayrı ayrı Session kontrolü yapmak, projenin modülerliği açısından sanki yönetimi zorlaştırıyor gibi. Mvc de session kullanan hiç örnek (açık kaynak proje) görmedim. FormAuthentication kullanıldıgında ve benim anlattığım örnekteki, membership metodlarını override edince, uygulama boyunca, hazır yetkilendirme metodlarından (Authorize gibi) tam olarak faydalanabilirsiniz.
SilAslinda cok kolay hocam Authorize attribute'u yazinca. Membership daha guvenliymis sanirim biraz arastirdim simdi kafami kurcalayan bisey var. Admin login sayfasini nasil normal login sayfasindan farkli olarak redirect ederim, yani admin area var admin login sayfasi farkli olmasini istiyorum. web.config yada attribute'mu nasil olur daha once karsilastinizmi bu durumla tesekkur ederim.
SilAyrı yapmak istiyorum derken ne demek istediginizi anlamadım. Kullanıcı giriş yapınca, eğer admin ise ana sayfada bir admin linki cıkarıp, admin sayfasına yonlendirebilirsiniz.
SilKullanici login sayfasi farkli admin login sayfasi farkli sekilde yapmak. Areas ekliyorum admin islemlerini admin area sindan yapiyorum. SimpleMembership kullandigimda Authroize Admin diyecem ama bu sefer gidicek Account/Login 'e iste oraya gitmesinde Admin/Acciunt/Login e gitsin admin ordan giris yapsin mumkunmu boyle birsey.
Silgiriş yapmayan bir kullanıcının hangi rolde oldugunu nasıl anlayacaksınız?
Silonu anlayamayiz da role'e gore login page olayi olmali bunu gelistirmeliler bence eksik bi ozellik
SilHocam role göre login page diye birşey olmaz. Kullanıcının rolünü nasıl almayı düşünüyorsunuz kullanıcı giriş yapmadan? Rol almak için kullanıcıyı tanımanız lazım. Kullanıcıyı tanımak için kullanıcı girş yapmış olmalı. Sizin admin oldugunuzu nasıl anlayıp sizi admin login e yönlendirecek?
SilBu yorum yazar tarafından silindi.
Silweb.config e eklenebilir nasil account/login varsa, Authroize("Roles=Admin") yaptiginda authorize olan role un login sayfasina yonelndirecek bunuda ayarlamak icin web.config e eklenbilir role login gibi alan acilabilir
Siladmin login sayfasi ile normal kullanici login sayfasi arasinda nasil bir fark olacak?
SilBurada kullanıcının admin olup olmadığını kontrol ederek istediğin gibi bir alan gösterimi, buton.. gibi istediğin herşeyi gösterebilirsin sadece Admin'e özel
Sil@if (Request.IsAuthenticated && User.IsInRole("Admin"))
{
istediğin buton ya da html kodları
}
Tasarim farkli olucak tabiki.
SilBerdan o lazim degil.
Merhaba Hocam,
YanıtlaSilBenim sorum biraz daha genel olucak. Mvc 4 örnek bir uygulama açtığımızda hali hazırda gelen bir Authentication sistemi var. Şu iki duruma göre kendi Authentication classımımızı mı yazmak mantıklı yoksa halihazırda var olanı mı kullanmak?
- Kişisel blog yazarken sadece tek kullanıcı giriş yapacağı zaman,
- Birden çok kullanıcının bu bloga girip veri girişi yapacağı zaman.
Teşekkürler
Makalelerde hazır kullanmamamın sebebi, her zaman kendim yazmaktan yana olmamdır. Kendiniz yazarsanız, veri tabanı tabloları ve uyelik sınıfları üzerinde tam hakim olursunuz. Ben her zaman kendim yazmak taraftarıyım. Kendi oluşturacağınız diğer sınıflarında bu üyelik sınıfları ile olan illişkilerini daha iyi yönetirsiniz.
SilAnladım hocam, peki güvenlik açısından ele aldığımızda hangisi daha güvenli olur?(Temel kullanıcı seviyesini düşünerek yani sizin yazdığınız gibi bir authentication yazabiliyorum.) Kendi Sessionlarımın kontrolü için bir SesionFilter oluşturdum ve bütün Controllerlarımın başına [SessionFilter] yazarak kullanıcıya ait olan Session'ı benim oluşturduğum olup olmadığını kontrol ediyorum. Elimden gelen güvenlik kontrolü bu kadar.
SilBunları ele alarak hazır olan authentication'ının ek olarak sağladığı güvenlik falan var mı?
Bunların güvenlik acısından karşılaştıracak kadar bilgim yok. Sanırım biraz araştırmak lazım.Eğer siz bu konuda araştırma yaparda burada paylaşırsanız güzel olur.
SilAyrım olarak birşey bulamadım daha doğrusu söylenen eğer biliyorsan kendi kodlarını yazmak daha mantıklı tarzında yorumlar var ama bilmekten kasıt nedir bunu anlamak biraz zor. Çünkü güvenlik konusuna girdiğimde Authentication dan çok ilk önce Xsrf/Csrf saldırılarının üzerinde durmuşlar. Bunlardan sonra okuduğum yerlerde Authentication için filter ile ilgili yazılardı. Yani sayfalar arasında gezerken sessionı kontrol etmek ya da Login yaptığın Controller senin AuthenticationController'ından mı olmuş tarzı filtreleme seçenekleri getiriyorlardı.
SilDilim döndüğünce anlatmaya çalıştım umarım yardımcı olur başkalarına.
Merhaba,
YanıtlaSilsürekli takip ediyorum kardeşim herşey için sağol ama bir eleştirim olacak. Ya bazan haftalar aylar bekletiyon. Her gün açıyom yok yok. Tamam yoğunsun bizede zaman ayırıyon teşekkür ederiz. Ama biraz daha ilgi bekliyoruz :)
Hocam sağol ama gerçekten zaman olmuyor. Forum sitelerini bile takip edemiyorum. Makale yazmak birazda zor iş. Paylaşacak çok sey var ama işte... Kusura bakmayın, elimden geldigi kadar hızlı olmaya çalışırım :)
SilMakale için teşekkürler. Daha önceden yazmıştım ama hata oldu heralde çıkmadı forumda. Benim iki sorum olacak birincisi notimplemented methodlar için bir örnek verebilirmisiniz mesela changepassword için. 2. soruda normal mvc internet varsaılan bir proje oluşturduğumuzda ordaki membership şifreleri kaydederken SHA ve password salt ile kriptolayıp saklıyor buların örneklerine baktım md5 ile yapabildim SHA ve password salt ile nasıl yapılabilir çözemedim? teşekkürler.
YanıtlaSil.net MD5 kullanıyor diye biliyorum. Ben daha önce hiç kullanmadım. Sizin bildiklerinizle aynı şeyi biliyorum bu konuda. NotImplemented metodları doldurmak için ekstra birşey bilmenize gerek yok. Kendi yazdığınız metodları bu metodların içerisinde çağırın sadece. implement edilen metodlar gibi
SilHocam şuan kadar olan Projeyi paylaşa bilir misiniz?
YanıtlaSilProje ile alakalı tüm kodları makalelerde yazdım. Birkaç proje üzerinde çalışarak, kodları o projelerden alarak tek projeymiş gibi, yazıyorum, bundan dolayıda şu an bir proje paylaşımı zor görünüyor.
SilMerhaba Ali Rıza bey, Elinize sağlık çok yararlı bir siteniz var.
YanıtlaSilBir sorum olacaktı; MVC 4.0 kullanarak oluşturduğum projemde her isteği HomeController daki index ActionResultuna yönlendirip gelen url den tıklanan sayfanın url alıyorum ve ilgili View yönlendiriyorum bu işlemleri projeyi Empty olarak açarsam yapıyorum fakat proje Basic açarsam controllerda olmayan bir action olduğu için hata veriyor "Server Error in '/' Application." sizce nerde hata yapıyorum.
Sorunuzu pek anlamadım. Bir kaç satır kod görmek lazım. Routing ayarlarından olabilir.
SilMerhaba,
YanıtlaSiliki projedede aşağıdaki veriler aynı, Basic oluşturduğum projede her isteğin home controller + Index ActionREsult metoduna yönlendirmek istiyorum.
RouteCongig.cs sınıfındaki url şablonum
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Şöyle bir contoller var ve içinde bir ActionResult var
public class HomeController : Controller
{
public ActionResult Index()
{
return View(ilgili_View_adı);
}
}
Problem yok gibi görünüyor. routeconfig sınıfının tam görüntüsü aşağıdaki gibi bu arada değil mi: (ve global.asax ta tanımlı)
Silpublic static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "hom", action = "Index", id = UrlParameter.Optional }
);
}
Kodlarınızın sorunsuz çalışması lazım.
Merhaba,
YanıtlaSilEvet routeConfig.cs görüntüsü aynı... ve global asax aşağıdaki gibi tanımlı
RouteConfig.RegisterRoutes(RouteTable.Routes);
url adresim "/home/index/ " veya "/" olunca çalışıyor fakat "/home/list/" olunca sayfa bulunamadı hatası veriyor list View mevcut sadece home controller içerisinde methodu yok.
MVC mimarisinin yapısı view sayfalarını metodlar ile döndürmektir. Metodu olmayan bi sayfa zaten, tanımlı değildir. O view sayfasını döndürecek bir metod yoktur.
SilBence öncelikle MVC mimarisi nedir? nasıl çalışır model, view, controller nedir? gibi soruların cevaplarını tam olarak anlamak için araştırma yapsanız yararlı olur.
Merhaba,
YanıtlaSilAslında MVC'deki eksiklerimi gidermek için sürekli çalışıyorum ve denemeler yapıyorum tavsiyeniz için Gerçekten Teşekkürler. sadece anlamadığım bir view 'in metodunun var olup olmadığı nerede kontrol edilir ve müdahale edemezmiyiz.
Hocam Bur da Kullanıcıları Ldap(Zimbra) doğrulama yapsak nasıl bir yol izleriz? Örnek olarak yapabilir miyiz?
YanıtlaSilOlabilir.
SilHocam Örnek kod varsa Ldap(Zimbra) için paylaşa bilir misiniz?
SilŞu an yok.
SilKeşke yüz milyon satır makale yazacağınıza dersleri video olarak kayıt etseydiniz. Takibi daha kolay olur ve gözlerimiz bozulmazdı. :)
YanıtlaSilninject Ioc kullanıyorum, savechanges yöntemi için nasıl bir strateji izlemem gerek
YanıtlaSilunitofwork gereklimi, başka şekilde save changes yapılabilirmi, unit of work desinin bu ninjectli projeye uygulayabilimiyim. sadece generic repository kullanmıyorum, özel olanlarda da var.
Erkan yürek
- unitofowrk gerekli mi?
Sil- Hayır
- başka savechanges yapılabilir mi?
- Evet
-unit of work desinin bu ninjectli projeye uygulayabilimiyim?
- Evet
Unit of work yazmazsanız her repository içerisinde savechanges yazmanız gerekecektir. ilişkili nesneleri eklerken her nesne eklendikten sonra savechanges calısır.
Hocam merhabalar
YanıtlaSilpublic ActionResult ConfirmUser(Guid confirmationId)
fonksiyonunda
_userService.Find(confirmationId);
hata alıyorum ondan dolayıda fonksiyon çalışmıyor
Error 1 The best overloaded method match for 'MvcProject.Services.Users.IUserService.Find(int)' has some invalid arguments MvcProject.WebSite
ve
Error 2 Argument 1: cannot convert from 'System.Guid' to 'int'
Hatalarını alıyorum çözüm bulan var mı ?
Hocam bazı metodlar service te yok. Bu eksik metdoları eklemeniz gerektigini soylemiştim yukarıda. ConfirmationId ile kullanıcı bulan metod da bunlardan biri...
Silpublic ActionResult Login(LoginModel model, string ReturnUrl)
YanıtlaSil{
var userr = _userService.Find(model.UserId);
var user = _userService.ValidateUser(model.UserName, model.Password);
if (ModelState.IsValid && user != null)
{
if (!user.IsConfirmed) bu kısımda da hata almaktayım nasıl bir yol izleyelim fikri olan var mı
hocam yeni makale ne zaman gelir? :)
YanıtlaSilDevami ne zaman serinin?
YanıtlaSilMakalenin devamını bekliyoruz?
YanıtlaSilBu gidişle pek devamı gelmeyecek gibi:)
YanıtlaSilMakalelerin devamı inş. gelecek. Bu aralar işler yoğun, ayrıca proje de değişiklikler yapıyorum (yapısal olarak değişiklik yaptığım için biraz zaman alacak). Ayrıca projeyi baştan sona kadar video olarak cekme gibi bir fikrim var. Zamanım olursa öyle yapacağım ve projeyi de github dan paylaşacağım. Kusura bakmayın. Bu konudaki isteğiniz ve sabrınız için de ayrıca sağolun.
SilSevgili Yazarımız yaşıyormuş :) Teşekkürler bu açıklama için..
SilAli Rıza bey merhaba,
SilMakalenizdeki aşağıdaki IsConfirmed özelliğinde hata alıyorum. Projede belirttiğiniz eksik metodları falan halledebildim. Ancak bu kısımda user nesnesinin LoginModel sınıfından örneklenen model ın böyle bir özelliği yok. bu özelliği siz haber sitesinde farklı bir şekilde uygulamışsınız. Bu makaledeki yapıya göre bunu nasıl uygulayabiliriz? yani sorunu nasıl çözebiliriz?
<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
public ActionResult Login(LoginModel model, string ReturnUrl)
{
var user = _userService.ValidateUser(model.UserName, model.Password);
if (ModelState.IsValid && user != null)
{
if (!user.IsConfirmed)
{
TempData["EpostaOnayMesaj"] = "E-posta adresiniz onaylı değildir. Lütfen e-posta adresinizdeki linki kullanarak e-posta adresinizi onaylayınız.";
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>><
Cevabınız için şimdiden teşekkürler.
Kolay gelsin.
"IsConfirmed özelliğinde hata alıyorum" ne demek? nasıl bir hata? hata mesajı falan? pek anlayamadım sorunuzu.
SilSorunu şu şekilde çözdüm.
Sil<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>
public ActionResult Login(LoginModel model, string ReturnUrl)
{
if(ModelState.IsValid && _userService.ValidateUser(model.UserName, model.Password) )
{
var user = _userService.Find(model.UserName);
if(!user.IsConfirmed)
{
.........................
burdan sonrası sizin kodlarınızla aynı.
<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>
IsConfirmed özelliğini kabul etmiyordu ve ilk if ile başlayan parantez içindeki sizin yazmış olduğunuz kod kısmında da hata veriyordu aynı şekilde. ben çözümü bu şekilde buldum.
Kolay gelsin.
ali rıza kardeşim bir sonraki yazıyı bekleye bekleye saçlarım ağardı. :)
YanıtlaSilwalla bekliyoruz..
ali rıza kardeşim bir sonraki yazıyı bekleye bekleye saçlarım ağardı. :)
YanıtlaSilwalla bekliyoruz..
Ali Rıza Bey,
YanıtlaSilprojenizdeki "FindByUserNameAndPassword(userName, password)" bu methodun kodlarını paylaşabilir misiniz?
Teşekkürler
Bu metodu yazabiliyor olmanız gerekiyor.
Silİyi çalışmalar.. Konuyla alakalı değil fakat bir sorum olacaktı size...
YanıtlaSilruntime sırasında mvc4 ile partial bir sayfa eklemesi yapabilirmiyiz.. aspnet ile textbox nesnesini add.control gibi kodla ekleyebiliyorduk.. aslında yapmak istediğim farklı amaçlar için hazırlanmış partial dosyalarım var bunları veritabanı ile sayfaya ekleme çıkarma yapmak istiyorum. kusura bakmayın saçma bir soru da olabilir ..
vereceğiniz cevap için şimdiden teşekkür ederim..
Gercek senaryoyu yazarsanız daha net cevap verebilirim. Dinamik partial view yuklemek mumkun (ajax ile). Sayfanıza dinamik kontroller akleyebilir siniz
Silmerhaba hocam Kulanıcı Şifre Hatırlatma ile ilgili bi kaynağınız varmı
YanıtlaSilsu an kod blogu yok elimde, ama kendiniz cok rahat yazabilirsiniz. Eğer şifreleri kriptolama kullanmıyorsanız, kullanıcıdan aldıgınız mail adresine şifreyi yollarsınız. Şifreler kriptolu ise, kullanıcının şifresini sıfırlarsınız direk.
SilMvc'de yeni view oluşturdugumda bu hatayı alıyorum(hatanın resmi linkte) bunun sebebi hakkında bir bilginiz varmı?
YanıtlaSilhttp://3.bp.blogspot.com/-DzEh2swwvZ0/UOAI7v0ewiI/AAAAAAAAAbw/l4NJM7h0SgA/s1600/ke.PNG
Bu hatayı vermemesi lazım. asp.net temprory files dosyasını bulup silin. Cache de tuttugu bilgilerden kaynaklanıyor. visual studio ile alaklı yani
Sil"ASP.NET MVC - KOMPLE BİR PROJE YAPISI OLUŞTURMAK - 5" isimli makaleyi yayımlayacak mısınız ?
YanıtlaSilMerhaba hocam, ben mvc 4'de blog sitesi oluşturmaya çalışıyorum aklıma bi soru takıldı, şimdi sizin üyelik sisteminizi mi kullansam yoksa mvc 4 ile beraber gelen membership mi ? hangisi daha güvenli kafam burda biraz karıştı çünkü mesela membershipte üye olan kişiye email gönderme gelmiyor ama sizin yapınızda var sanki sizin yapınız membership'e göre daha detaylı ?
YanıtlaSilHocam, ilk sayfadan itibaren harfiyen projenizi takip ettim öğrenmek için ama bazı yerlerde küçük küçük hatalar var :s
YanıtlaSilneyse acaba mvc 4'da blog sitesi nasıl yapılır bunun hakkında makale yazmayı düşünüyormusunuz ?
Yazılara devam edin nooolur :)
YanıtlaSilAli Rıza Selam,
YanıtlaSilAnlatımın için teşekkürler,faydalı bir yazı olmuş.Devamını bekliyoruz.Eklemek istediğim bir kaç nokta var;
_userService.ValidateUserName, userService.ValidateEmail gibi metodları kullanmak için bunları Generic Repository'nin içine yazmamız gerekiyor.O zaman da bunun generic olmasının anlamı kalmıyor.Dolayısıyla direk generic repository'leri kullanmak yerine onları inherit eden concrete repository'ler yazılması gerekiyor. Aşağıdaki gibi :
http://www.tugberkugurlu.com/archive/generic-repository-pattern-entity-framework-asp-net-mvc-and-unit-testing-triangle
Ali Rıza bey tebrikler güzel bir yazı dizisi başlatmış ve yıllar sonra bile size dönüş yapan takipçiler edinmişsiniz.
YanıtlaSilBence de "Yine Yeniden Yeni Yapısıyla ASP.NET MVC - KOMPLE BİR PROJE YAPISI OLUŞTURMAK" diye bir yazı dizisi bekliyoruz sizden..
Başarılar..
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
YanıtlaSilpublic class CustomAuthorizeAttribute : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (filterContext.HttpContext.User.Identity.IsAuthenticated)
{
base.HandleUnauthorizedRequest(filterContext);
}
else
{
var areaName = filterContext.RouteData.DataTokens["area"];
if (areaName.Equals("Admin"))
{
filterContext.Result = new RedirectToRouteResult(new
RouteValueDictionary(new { controller = "Admin", action = "AdminLogin", area = "Admin" }));
}
else if (areaName.Equals("Public"))
{
filterContext.Result = new RedirectToRouteResult(new
RouteValueDictionary(new { controller = "Account", action = "Login" }));
}
// other conditions...
}
}
Merhaba,
YanıtlaSilMakaledeki repository deseni kullandım, ModelState.AddModelError işlemi ile silmede hata alırsam (örneğin Foreign Key hatası) her yerde aynı hata mesajını alıyorum.
örneğin, rol tablosunda silme hatası alırsam, kullanıcı eklerken veya başka bir tabloya ekleme yaparken de Rol tablosunda silme yapıyormuş gibi aynı hatayı alıyorum.
[HttpPost]
public ActionResult AddRole(RoleModel model)
{
if (ModelState.IsValid)
{
try
{
Role role = new Role
{
//Id = Guid.NewGuid(),
Name = model.Name,
Description = model.Description
};
roleService.Insert(role);
unitOfWork.SaveChanges();
return RedirectToAction("ListRole", "Role");
}
catch (Exception ei)
{
ModelState.AddModelError(String.Empty, "Insert: " + (ei.InnerException != null ? ei.InnerException.InnerException.Message : ""));
}
}
else
{
ModelState.AddModelError("", "Rol bilgileri eksik veya hatalı!");
}
return View(model);
}
Arkadaşlar Unit Of Work kullanmanızdaki amacı yazabilirmisiniz.
YanıtlaSilYani List li olarak birden fazla işlem ile uğraşıyorsak delete, update yada insert yaptığımda da işlemi tek seferde yapmış olacağım örnek method vereyim :
Kodların tamamını koymadım fakat anlayacağınızı düşünüyorum anlatmak istediğimi.
UniOFWork zaman kaybı oluyor gibi.
İnterface :
void InsertManufacturer(IEnumerable entities);
Methods :
if (entities == null)
throw new ArgumentNullException("entities");
_manufacturerRepository.Insert(entities);
Controller:
List Manufacturer= new List();
_manufacturerRepository.InsertPremiumModelValue(Manufacturer);