﻿
{"id":12027,"date":"2019-09-09T22:37:15","date_gmt":"2019-09-09T22:37:15","guid":{"rendered":"https:\/\/www.gencayyildiz.com\/blog\/?p=12027"},"modified":"2019-09-09T22:37:15","modified_gmt":"2019-09-09T22:37:15","slug":"asp-net-core-identity-oturum-kapatma-xiii","status":"publish","type":"post","link":"https:\/\/www.gencayyildiz.com\/blog\/asp-net-core-identity-oturum-kapatma-xiii\/","title":{"rendered":"Asp.NET Core Identity &#8211; Oturum Kapatma &#8211; XIII"},"content":{"rendered":"<div id=\"fb-root\"><\/div>\n<p>Merhaba,<\/p>\n<p>Asp.NET Core Identity yaz\u0131 dizisinde s\u0131ra oturum kapatma i\u015flemini ele almaya geldi. Uygulamada oturum a\u00e7m\u0131\u015f olan kullan\u0131c\u0131lar\u0131n oturumlar\u0131ndan \u00e7\u0131k\u0131\u015f yapabilmesi i\u00e7in nas\u0131l bir i\u015flem ger\u00e7ekle\u015ftirece\u011fimizi inceleyece\u011fiz. <\/p>\n<p>Kullan\u0131c\u0131n\u0131n, nas\u0131l ki giri\u015f yapt\u0131\u011f\u0131nda s\u00fcreci SignInManager nesnesiyle kontrol ediyorsak benzer mant\u0131kla \u00e7\u0131k\u0131\u015f yapabilmesi i\u00e7inde yine ayn\u0131 nesneyi kullanaca\u011f\u0131z.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class UserController : Controller\r\n    {\r\n        readonly UserManager&lt;AppUser&gt; _userManager;\r\n        readonly SignInManager&lt;AppUser&gt; _signInManager;\r\n        public UserController(UserManager&lt;AppUser&gt; userManager, SignInManager&lt;AppUser&gt; signInManager)\r\n        {\r\n            _userManager = userManager;\r\n            _signInManager = signInManager;\r\n        }\r\n        public async Task&lt;IActionResult&gt; Logout()\r\n        {\r\n            await _signInManager.SignOutAsync();\r\n            return RedirectToAction(&quot;Index&quot;);\r\n        }\r\n    .\r\n    .\r\n    .\r\n    \/\/di\u011fer actionlar\r\n    .\r\n    .\r\n    .\r\n    }\r\n<\/pre>\n<p>Yukar\u0131daki kod blo\u011funu incelerseniz e\u011fer &#8220;Logout&#8221; action metodu i\u00e7erisinde 12. sat\u0131rda &#8220;SignOutAsync&#8221; metodu ile kullan\u0131c\u0131n\u0131n oturumu d\u00fc\u015f\u00fcr\u00fclmektedir ve ard\u0131ndan &#8220;Index&#8221; action\u0131na y\u00f6nlendirme ger\u00e7ekle\u015ftirilmektedir. Bu y\u00f6ntem iki oturum d\u00fc\u015f\u00fcrme senaryolar\u0131ndan birisidir. Di\u011feri ise Asp.NET Core MVC mimarisindeki Tag Helper yap\u0131lanmas\u0131n\u0131n bizlere getirmi\u015f oldu\u011fu bir ba\u015fka nimettir.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class UserController : Controller\r\n    {\r\n        readonly UserManager&lt;AppUser&gt; _userManager;\r\n        readonly SignInManager&lt;AppUser&gt; _signInManager;\r\n        public UserController(UserManager&lt;AppUser&gt; userManager, SignInManager&lt;AppUser&gt; signInManager)\r\n        {\r\n            _userManager = userManager;\r\n            _signInManager = signInManager;\r\n        }\r\n        public async Task Logout()\r\n        {\r\n            await _signInManager.SignOutAsync();\r\n        }\r\n    .\r\n    .\r\n    .\r\n    \/\/di\u011fer actionlar\r\n    .\r\n    .\r\n    .\r\n    }\r\n<\/pre>\n<p>Yukar\u0131daki kod blo\u011funu incelerseniz e\u011fer &#8220;Logout&#8221; action\u0131 geriye de\u011fer d\u00f6nd\u00fcrmeyen metot haline getirilerek, &#8220;SignOutAsync&#8221; metodu neticesinde herhangi bir sayfaya yap\u0131lan y\u00f6nlendirme kald\u0131r\u0131lm\u0131\u015ft\u0131r.<br \/>\n<strong>Peki \u00e7\u0131k\u0131\u015f yap\u0131ld\u0131ktan sonra nas\u0131l y\u00f6nlendirme yapaca\u011f\u0131z?<\/strong> sorusuna kar\u015f\u0131l\u0131k ise bir paragraf \u00f6nce bahsetti\u011fim tag helper yap\u0131lanmas\u0131n\u0131 cevap olarak sunaca\u011f\u0131m.<\/p>\n<p>&#8220;Logout&#8221; action\u0131na link verdi\u011fimiz sayfada &#8220;<em>asp-route-returnUrl<\/em>&#8221; tag helper\u0131n\u0131 a\u015fa\u011f\u0131daki gibi kullanarak, bu link \u00fczerinden istek yap\u0131ld\u0131\u011f\u0131 taktirde neticede hangi adrese y\u00f6nlendirilece\u011fini belirlemi\u015f bulunmaktay\u0131z.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n&lt;a asp-action=&quot;Logout&quot; asp-controller=&quot;User&quot; asp-route-returnUrl=&quot;\/User\/Signin&quot;&gt;Logout&lt;\/a&gt;\r\n<\/pre>\n<p>Lakin ilgili tag helper\u0131n kullan\u0131labilmesi i\u00e7in &#8220;Startup.cs&#8221; dosyas\u0131nda uygulamaya dair cookie konfig\u00fcrasyonunu sa\u011flad\u0131\u011f\u0131m\u0131z &#8220;ConfigureApplicationCookie&#8221; metodunda a\u015fa\u011f\u0131daki kod blo\u011funda 26. sat\u0131rda oldu\u011fu gibi &#8220;LogoutPath&#8221; \u00f6zelli\u011fine hangi action tetiklendi\u011finde \u00e7al\u0131\u015faca\u011f\u0131n\u0131 belirlememiz gerekmektedir.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class Startup\r\n    {\r\n        public IConfiguration Configuration { get; set; }\r\n        public Startup(IConfiguration configuration) =&gt; Configuration = configuration;\r\n        public void ConfigureServices(IServiceCollection services)\r\n        {\r\n            services.AddDbContext&lt;AppDbContext&gt;(_ =&gt; _.UseSqlServer(Configuration&#x5B;&quot;ConnectionStrings:SqlServerConnectionString&quot;]));\r\n            services.AddIdentity&lt;AppUser, AppRole&gt;(_ =&gt;\r\n            {\r\n                _.Password.RequiredLength = 5; \/\/En az ka\u00e7 karakterli olmas\u0131 gerekti\u011fini belirtiyoruz.\r\n                _.Password.RequireNonAlphanumeric = false; \/\/Alfanumerik zorunlulu\u011funu kald\u0131r\u0131yoruz.\r\n                _.Password.RequireLowercase = false; \/\/K\u00fc\u00e7\u00fck harf zorunlulu\u011funu kald\u0131r\u0131yoruz.\r\n                _.Password.RequireUppercase = false; \/\/B\u00fcy\u00fck harf zorunlulu\u011funu kald\u0131r\u0131yoruz.\r\n                _.Password.RequireDigit = false; \/\/0-9 aras\u0131 say\u0131sal karakter zorunlulu\u011funu kald\u0131r\u0131yoruz.\r\n\r\n                _.User.RequireUniqueEmail = true; \/\/Email adreslerini tekille\u015ftiriyoruz.\r\n                _.User.AllowedUserNameCharacters = &quot;abc\u00e7defghi\u0131jklmno\u00f6pqrs\u015ftu\u00fcvwxyzABC\u00c7DEFGHI\u0130JKLMNO\u00d6PQRS\u015eTU\u00dcVWXYZ0123456789-._@+&quot;; \/\/Kullan\u0131c\u0131 ad\u0131nda ge\u00e7erli olan karakterleri belirtiyoruz.\r\n            }).AddPasswordValidator&lt;CustomPasswordValidation&gt;()\r\n              .AddUserValidator&lt;CustomUserValidation&gt;()\r\n              .AddErrorDescriber&lt;CustomIdentityErrorDescriber&gt;().AddEntityFrameworkStores&lt;AppDbContext&gt;()\r\n              .AddDefaultTokenProviders(); ;\r\n\r\n            services.ConfigureApplicationCookie(_ =&gt;\r\n            {\r\n                _.LoginPath = new PathString(&quot;\/User\/Login&quot;);\r\n                _.LogoutPath = new PathString(&quot;\/User\/Logout&quot;);\r\n                _.Cookie = new CookieBuilder\r\n                {\r\n                    Name = &quot;AspNetCoreIdentityExampleCookie&quot;, \/\/Olu\u015fturulacak Cookie'yi isimlendiriyoruz.\r\n                    HttpOnly = false, \/\/K\u00f6t\u00fc niyetli insanlar\u0131n client-side taraf\u0131ndan Cookie'ye eri\u015fmesini engelliyoruz.\r\n                    Expiration = TimeSpan.FromMinutes(2), \/\/Olu\u015fturulacak Cookie'nin vadesini belirliyoruz.\r\n                    SameSite = SameSiteMode.Lax, \/\/Top level navigasyonlara sebep olmayan requestlere Cookie'nin g\u00f6nderilmemesini belirtiyoruz.\r\n                    SecurePolicy = CookieSecurePolicy.Always \/\/HTTPS \u00fczerinden eri\u015filebilir yap\u0131yoruz.\r\n                };\r\n                _.SlidingExpiration = true; \/\/Expiration s\u00fcresinin yar\u0131s\u0131 kadar s\u00fcre zarf\u0131nda istekte bulunulursa e\u011fer geri kalan yar\u0131s\u0131n\u0131 tekrar s\u0131f\u0131rlayarak ilk ayarlanan s\u00fcreyi tazeleyecektir.\r\n                _.ExpireTimeSpan = TimeSpan.FromMinutes(2); \/\/CookieBuilder nesnesinde tan\u0131mlanan Expiration de\u011ferinin varsay\u0131lan de\u011ferlerle ezilme ihtimaline kar\u015f\u0131n tekrardan Cookie vadesi burada da belirtiliyor.\r\n            });\r\n\r\n            services.AddMvc();\r\n        }\r\n\r\n        public void Configure(IApplicationBuilder app, IHostingEnvironment env)\r\n        {\r\n            if (env.IsDevelopment())\r\n                app.UseDeveloperExceptionPage();\r\n\r\n            app.UseStatusCodePages();\r\n            app.UseStaticFiles();\r\n            app.UseAuthentication();\r\n            app.UseMvc(_ =&gt; _.MapRoute(&quot;Default&quot;, &quot;{controller=Home}\/{action=Index}\/{id?}&quot;));\r\n        }\r\n    }\r\n<\/pre>\n<p>Bu i\u015flem neticesinde uygulamada oturum a\u00e7an kullan\u0131c\u0131 oturumunu kapatt\u0131\u011f\u0131 taktirde &#8220;User\/Signin&#8221; route&#8217;una y\u00f6nlendirilecektir. <\/p>\n<p>Evet&#8230; Bir i\u00e7eri\u011fimizin daha sonuna geldik.<br \/>\n\u0130lgilenenlerin faydalanmas\u0131 dile\u011fiyle&#8230;<br \/>\nSonraki yaz\u0131lar\u0131mda g\u00f6r\u00fc\u015fmek \u00fczere&#8230;<br \/>\n\u0130yi \u00e7al\u0131\u015fmalar&#8230;<\/p>\n<p>Not : \u00d6rnek projeyi indirmek i\u00e7in <a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2019\/09\/AspNetCoreIdentityExample.zip\">buraya t\u0131klay\u0131n\u0131z.<\/a><\/p>\n<!-- AddThis Advanced Settings generic via filter on the_content --><!-- AddThis Share Buttons generic via filter on the_content -->","protected":false},"excerpt":{"rendered":"<p>Merhaba, Asp.NET Core Identity yaz\u0131 dizisinde s\u0131ra oturum kapatma i\u015flemini ele almaya geldi. Uygulamada oturum a\u00e7m\u0131\u015f olan kullan\u0131c\u0131lar\u0131n oturumlar\u0131ndan \u00e7\u0131k\u0131\u015f yapabilmesi i\u00e7in nas\u0131l bir i\u015flem ger\u00e7ekle\u015ftirece\u011fimizi inceleyece\u011fiz. Kullan\u0131c\u0131n\u0131n, nas\u0131l ki giri\u015f yapt\u0131\u011f\u0131nda s\u00fcreci SignInManager&#46;&#46;&#46;<!-- AddThis Advanced Settings generic via filter on get_the_excerpt --><!-- AddThis Share Buttons generic via filter on get_the_excerpt --><\/p>\n","protected":false},"author":1,"featured_media":11583,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2668,2656,2811,2832,2898],"tags":[3011,3010,3009],"class_list":["post-12027","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-asp-net-core-2","category-asp-net-core-2-mvc","category-asp-net-core-2-1","category-asp-net-core-2-2","category-asp-net-core-3-0","tag-asp-route-returnurl","tag-asp-net-core-identity-logout","tag-asp-net-core-identity-oturum-kapatma"],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/12027","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/comments?post=12027"}],"version-history":[{"count":18,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/12027\/revisions"}],"predecessor-version":[{"id":12046,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/12027\/revisions\/12046"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media\/11583"}],"wp:attachment":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/media?parent=12027"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/categories?post=12027"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/tags?post=12027"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}