﻿
{"id":11955,"date":"2019-08-30T22:00:50","date_gmt":"2019-08-30T22:00:50","guid":{"rendered":"https:\/\/www.gencayyildiz.com\/blog\/?p=11955"},"modified":"2019-08-30T22:00:50","modified_gmt":"2019-08-30T22:00:50","slug":"asp-net-core-identity-sifremi-unuttum-xi","status":"publish","type":"post","link":"https:\/\/www.gencayyildiz.com\/blog\/asp-net-core-identity-sifremi-unuttum-xi\/","title":{"rendered":"Asp.NET Core Identity &#8211; \u015eifremi Unuttum &#8211; XI"},"content":{"rendered":"<div id=\"fb-root\"><\/div>\n<p>Merhaba,<\/p>\n<p><a href=\"https:\/\/www.gencayyildiz.com\/blog\/asp-net-core-identity-yazi-dizisi\/\" target=\"_blank\" rel=\"noopener noreferrer\">Asp.NET Core Identity yaz\u0131 dizimizin<\/a> 11. makalesinde web sitemize \u00fcye olan kullan\u0131c\u0131lar taraf\u0131ndan belirtilen \u015fifrelerin <em>-insanl\u0131k hali-<\/em> unutulmas\u0131 durumunda kullan\u0131c\u0131n\u0131n nas\u0131l yeni \u015fifre talep edece\u011fini Identity mekanizmas\u0131 \u00fczerinden inceleyece\u011fiz.<\/p>\n<p>S\u00fcre\u00e7te b\u00fct\u00fcnl\u00fc\u011f\u00fc sa\u011flayabilmek ad\u0131na yaz\u0131 dizimizde kulland\u0131\u011f\u0131m\u0131z projemiz \u00fczerinde geli\u015ftirme yapaca\u011f\u0131z.<\/p>\n<p>Her\u015feyden \u00f6nce uygulamada \u015fifremi unuttum mekanizmas\u0131n\u0131 in\u015fa edebilmek i\u00e7in token provider yap\u0131lanmas\u0131n\u0131 servis olarak dahil etmemiz gerekmektedir. Bunun i\u00e7in &#8220;Startup.cs&#8221; dosyas\u0131na giderek 21. sat\u0131rda oldu\u011fu gibi &#8220;AddDefaultTokenProviders&#8221; metodunu eklememiz yeterlidir.<\/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                _.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 temel konfig\u00fcrasyondan sonra kullan\u0131c\u0131n\u0131n ihtiyaca binaen yeniden \u015fifre talep edebilmesi i\u00e7in &#8220;\u015eifremi Unuttum&#8221; sayfas\u0131n\u0131 tasarlayal\u0131m.<\/p>\n<h3>\u015eifremi Unuttum Sayfas\u0131n\u0131n Tasarlanmas\u0131<\/h3>\n<p>\u0130lk olarak uygulamam\u0131z\u0131n &#8220;Models&#8221; -> &#8220;ViewModels&#8221; klas\u00f6r\u00fc alt\u0131nda yeni \u015fifre talebi esnas\u0131nda veriyi kar\u015f\u0131layabilmek i\u00e7in &#8220;ResetPasswordViewModel&#8221; isminde bir viewmodel tasarl\u0131yoruz.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class ResetPasswordViewModel\r\n    {\r\n        &#x5B;Display(Name = &quot;E-Posta Adresiniz&quot;)]\r\n        &#x5B;Required(ErrorMessage = &quot;L\u00fctfen e-posta adresinizi bo\u015f ge\u00e7meyiniz.&quot;)]\r\n        &#x5B;EmailAddress(ErrorMessage = &quot;L\u00fctfen uygun formatta e-posta giriniz.&quot;)]\r\n        public string Email { get; set; }\r\n    }\r\n<\/pre>\n<p>Ard\u0131ndan &#8220;User(Controller).cs&#8221; controller s\u0131n\u0131f\u0131 i\u00e7erisinde ilgili talebi y\u00f6netece\u011fimiz &#8220;PasswordReset&#8221; isimli bir action olu\u015fturuyoruz ve a\u015fa\u011f\u0131daki gibi geli\u015ftiriyoruz.<\/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 IActionResult PasswordReset()\r\n        {\r\n            return View();\r\n        }\r\n        &#x5B;HttpPost]\r\n        public async Task&lt;IActionResult&gt; PasswordReset(ResetPasswordViewModel model)\r\n        {\r\n            AppUser user = await _userManager.FindByEmailAsync(model.Email);\r\n            if (user != null)\r\n            {\r\n                string resetToken = await _userManager.GeneratePasswordResetTokenAsync(user);\r\n\r\n                MailMessage mail = new MailMessage();\r\n                mail.IsBodyHtml = true;\r\n                mail.To.Add(user.Email);\r\n                mail.From = new MailAddress(&quot;******@gmail.com&quot;, &quot;\u015eifre G\u00fcncelleme&quot;, System.Text.Encoding.UTF8);\r\n                mail.Subject = &quot;\u015eifre G\u00fcncelleme Talebi&quot;;\r\n                mail.Body = $&quot;&lt;a target=\\&quot;_blank\\&quot; href=\\&quot;https:\/\/localhost:5001{Url.Action(&quot;UpdatePassword&quot;, &quot;User&quot;, new { userId = user.Id, token = HttpUtility.UrlEncode(resetToken) })}\\&quot;&gt;Yeni \u015fifre talebi i\u00e7in t\u0131klay\u0131n\u0131z&lt;\/a&gt;&quot;;\r\n                mail.IsBodyHtml = true;\r\n                SmtpClient smp = new SmtpClient();\r\n                smp.Credentials = new NetworkCredential(&quot;*****@gmail.com&quot;, &quot;******&quot;);\r\n                smp.Port = 587;\r\n                smp.Host = &quot;smtp.gmail.com&quot;;\r\n                smp.EnableSsl = true;\r\n                smp.Send(mail);\r\n\r\n                ViewBag.State = true;\r\n            }\r\n            else\r\n                ViewBag.State = false;\r\n\r\n            return View();\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\u011funda, birazdan view i\u00e7eri\u011finide g\u00f6rece\u011fimiz &#8220;PasswordReset&#8221; action\u0131 geli\u015ftirilmi\u015ftir. Yap\u0131lan post neticesinde kullan\u0131c\u0131 taraf\u0131ndan do\u011fru email adresi girilmi\u015fse e\u011fer 20. sat\u0131rda &#8220;GeneratePasswordResetTokenAsync&#8221; metodu ile kullan\u0131c\u0131ya \u00f6zel token de\u011feri \u00fcretilmektedir. Hemen ard\u0131ndan \u00fcretilen bu de\u011fer user id de\u011feri ile birlikte olu\u015fturulan bir update linkine query string olarak eklenmekte ve ilgili url yeni \u015fifre talep eden kullan\u0131c\u0131n\u0131n email adresine g\u00f6nderilmektedir. Dolay\u0131s\u0131yla kullan\u0131c\u0131 url \u00fczerinden g\u00f6nderilen token de\u011ferinin g\u00fcvencesiyle kendisine ait hesaba dair \u015fifreyi g\u00fcncelleyebilecektir.<\/p>\n<p>Evet&#8230; Burada email yap\u0131lanmas\u0131n\u0131 farkl\u0131 bir katmanda tasarlamak daha do\u011fru olabilir. Lakin \u00f6rneklendirmeyi fazla par\u00e7alamamak ad\u0131na olmas\u0131 gereken bu durumu sizlere b\u0131rak\u0131yorum&#8230;<\/p>\n<p>\u015eimdide &#8220;PasswordReset&#8221; action\u0131n\u0131n view&#8217;ini g\u00f6relim.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n@model AspNetCoreIdentityExample.Models.ViewModels.ResetPasswordViewModel\r\n@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers\r\n\r\n&lt;h3&gt;\u015eifremi Unuttum&lt;\/h3&gt;\r\n\r\n&lt;hr \/&gt;\r\n@if (ViewBag.State == null)\r\n{\r\n    &lt;form asp-action=&quot;PasswordReset&quot;&gt;\r\n        &lt;table&gt;\r\n            &lt;tr&gt;\r\n                &lt;td colspan=&quot;3&quot;&gt;&lt;div asp-validation-summary=&quot;All&quot;&gt;&lt;\/div&gt;&lt;\/td&gt;\r\n            &lt;\/tr&gt;\r\n            &lt;tr&gt;\r\n                &lt;td&gt;&lt;label asp-for=&quot;Email&quot;&gt;&lt;\/label&gt;&lt;\/td&gt;\r\n                &lt;td&gt;&lt;input asp-for=&quot;Email&quot; \/&gt;&lt;\/td&gt;\r\n                &lt;td&gt;&lt;span asp-validation-for=&quot;Email&quot;&gt;&lt;\/span&gt;&lt;\/td&gt;\r\n            &lt;\/tr&gt;\r\n            &lt;tr&gt;\r\n                &lt;td colspan=&quot;3&quot;&gt;&lt;input type=&quot;submit&quot; value=&quot;Yeni \u015eifre Talebi G\u00f6nder&quot; \/&gt;&lt;\/td&gt;\r\n            &lt;\/tr&gt;\r\n        &lt;\/table&gt;\r\n    &lt;\/form&gt;\r\n}\r\nelse\r\n{\r\n    if (ViewBag.State)\r\n    {\r\n        @:&lt;div class=&quot;alert-success&quot;&gt;\u015eifre talebi i\u00e7in e-posta adresinize bilgilerindirici mail g\u00f6nderilmi\u015ftir.&lt;\/div&gt;\r\n    }\r\n    else\r\n    {\r\n        @:&lt;div class=&quot;alert-success&quot;&gt;B\u00f6yle bir e-posta bulunmamaktad\u0131r.&lt;\/div&gt;\r\n    }\r\n}\r\n<\/pre>\n<p>Evet, art\u0131k \u015fifreyi g\u00fcncelleme i\u015flemini operasyonel olarak ger\u00e7ekle\u015ftirecek &#8220;UpdatePassword&#8221; action metodunu tasarlayabiliriz.<\/p>\n<h3>\u015eifreyi G\u00fcncelleme Sayfas\u0131n\u0131n Tasarlanmas\u0131<\/h3>\n<p>Kullan\u0131c\u0131 taraf\u0131m\u0131zca mail \u00fczerinden g\u00f6nderilen url&#8217;e t\u0131klad\u0131\u011f\u0131 vakit yeni \u015fifresini belirleyebilmek i\u00e7in &#8220;UpdatePassword&#8221; action metodu taraf\u0131ndan kar\u015f\u0131lanacakt\u0131r. Dolay\u0131s\u0131yla ilk olarak kullan\u0131c\u0131n\u0131n girdi\u011fi \u015fifreyi ta\u015f\u0131mas\u0131 i\u00e7in &#8220;UpdatePasswordViewModel&#8221; isminde bir viewmodel tasarlayal\u0131m.<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n    public class UpdatePasswordViewModel\r\n    {\r\n        &#x5B;Display(Name = &quot;Yeni \u015eifre&quot;)]\r\n        &#x5B;Required(ErrorMessage = &quot;L\u00fctfen \u015fifreyi bo\u015f ge\u00e7meyiniz.&quot;)]\r\n        &#x5B;DataType(DataType.Password)]\r\n        public string Password { get; set; }\r\n    }\r\n<\/pre>\n<p>Ard\u0131ndan &#8220;UpdatePassword&#8221; action metodunu in\u015fa edelim.<\/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        &#x5B;HttpGet(&quot;&#x5B;action]\/{userId}\/{token}&quot;)]\r\n        public IActionResult UpdatePassword(string userId, string token)\r\n        {\r\n            return View();\r\n        }\r\n        &#x5B;HttpPost(&quot;&#x5B;action]\/{userId}\/{token}&quot;)]\r\n        public async Task&lt;IActionResult&gt; UpdatePassword(UpdatePasswordViewModel model, string userId, string token)\r\n        {\r\n            AppUser user = await _userManager.FindByIdAsync(userId);\r\n            IdentityResult result = await _userManager.ResetPasswordAsync(user, HttpUtility.UrlDecode(token), model.Password);\r\n            if (result.Succeeded)\r\n            {\r\n                ViewBag.State = true;\r\n                await _userManager.UpdateSecurityStampAsync(user);\r\n            }\r\n            else\r\n                ViewBag.State = false;\r\n            return View();\r\n        }\r\n    }\r\n    .\r\n    .\r\n    .\r\n    \/\/di\u011fer actionlar\r\n    .\r\n    .\r\n    .\r\n<\/pre>\n<p>G\u00f6r\u00fcld\u00fc\u011f\u00fc \u00fczere kullan\u0131c\u0131ya g\u00f6nderilen e-postadaki urle t\u0131kland\u0131\u011f\u0131 vakit query string olarak belirtilen userId ve token de\u011ferleri &#8220;UpdatePassword&#8221; action metodu taraf\u0131ndan yakalanmakta ve  <a href=\"https:\/\/www.gencayyildiz.com\/blog\/asp-net-mvcde-tempdata-ile-veri-tasima-ve-actionlar-arasinda-veri-transferi\/\" rel=\"noopener noreferrer\" target=\"_blank\">TempData<\/a>&#8216;ya at\u0131lmaktad\u0131r. Post neticesinde &#8220;UpdatePasswordViewModel&#8221; parametresi kullan\u0131c\u0131 taraf\u0131ndan girilen yeni \u015fifreyi ta\u015f\u0131maktad\u0131r ve <strong>19.<\/strong> sat\u0131rda oldu\u011fu gibi &#8220;ResetPasswordAsync&#8221; metodu ile token de\u011feri kontrol\u00fcnde \u015fifre g\u00fcncellemesi ger\u00e7ekle\u015ftirilmektedir. <strong>23.<\/strong> sat\u0131rda ise ana de\u011ferlerden biri olan \u015fifrenin de\u011fi\u015fmesinden dolay\u0131 &#8220;UpdateSecurityStampAsync&#8221; metodu arac\u0131l\u0131\u011f\u0131yla ilgili kullan\u0131c\u0131n\u0131n SecurityStamp kolonu yeni bir de\u011ferle g\u00fcncellenmi\u015ftir. B\u00f6ylece \u00f6nceki \u00fcretilen cookie de\u011ferleri \u00e7\u00fcr\u00fct\u00fclm\u00fc\u015ft\u00fcr.<\/p>\n<p>&#8220;UpdatePassword&#8221; action\u0131n\u0131n view dosyas\u0131n\u0131da incelersek e\u011fer;<\/p>\n<pre class=\"brush: jscript; title: ; notranslate\" title=\"\">\r\n@model AspNetCoreIdentityExample.Models.ViewModels.UpdatePasswordViewModel\r\n@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers\r\n\r\n&lt;h3&gt;\u015eifremi Unuttum&lt;\/h3&gt;\r\n\r\n&lt;hr \/&gt;\r\n@if (ViewBag.State == null)\r\n{\r\n    &lt;form asp-action=&quot;UpdatePassword&quot;&gt;\r\n        &lt;table&gt;\r\n            &lt;tr&gt;\r\n                &lt;td colspan=&quot;3&quot;&gt;&lt;div asp-validation-summary=&quot;All&quot;&gt;&lt;\/div&gt;&lt;\/td&gt;\r\n            &lt;\/tr&gt;\r\n            &lt;tr&gt;\r\n                &lt;td&gt;&lt;label asp-for=&quot;Password&quot;&gt;&lt;\/label&gt;&lt;\/td&gt;\r\n                &lt;td&gt;&lt;input asp-for=&quot;Password&quot; \/&gt;&lt;\/td&gt;\r\n                &lt;td&gt;&lt;span asp-validation-for=&quot;Password&quot;&gt;&lt;\/span&gt;&lt;\/td&gt;\r\n            &lt;\/tr&gt;\r\n            &lt;tr&gt;\r\n                &lt;td colspan=&quot;3&quot;&gt;&lt;input type=&quot;submit&quot; value=&quot;\u015eifreyi G\u00fcncelle&quot; \/&gt;&lt;\/td&gt;\r\n            &lt;\/tr&gt;\r\n        &lt;\/table&gt;\r\n    &lt;\/form&gt;\r\n}\r\nelse\r\n{\r\n    if (ViewBag.State)\r\n    {\r\n        @:&lt;div class=&quot;alert-success&quot;&gt;\u015eifre ba\u015far\u0131yla g\u00fcncellenmi\u015ftir.&lt;\/div&gt;\r\n    }\r\n    else\r\n    {\r\n        @:&lt;div class=&quot;alert-success&quot;&gt;\u015eifreyi g\u00fcncellerken beklenmeyen hatayla kar\u015f\u0131la\u015f\u0131ld\u0131.&lt;\/div&gt;\r\n    }\r\n}\r\n<\/pre>\n<p>\u015feklinde olacakt\u0131r.<\/p>\n<p>Art\u0131k uygulaman\u0131n bu son halini kaydedip, derledi\u011finiz vakit a\u015fa\u011f\u0131daki gibi \u015fifremi unuttum mekanizmas\u0131n\u0131n \u00e7al\u0131\u015ft\u0131\u011f\u0131n\u0131 g\u00f6zlemleyebilirsiniz.<br \/>\n<a href=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2019\/08\/Asp.NET-Core-Identity-\u015eifremi-Unuttum-XI.gif\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.gencayyildiz.com\/blog\/wp-content\/uploads\/2019\/08\/Asp.NET-Core-Identity-\u015eifremi-Unuttum-XI.gif\" alt=\"Asp.NET Core Identity - \u015eifremi Unuttum - XI\" width=\"800\" height=\"540\" class=\"aligncenter size-full wp-image-11982\" \/><\/a><\/p>\n<p>\u0130lgilenenlerin faydalanmas\u0131 dile\u011fiyle.<br \/>\nSonraki yaz\u0131lar\u0131mda g\u00f6r\u00fc\u015fmek \u00fczere.<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\/08\/AspNetCoreIdentityExample-8.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 dizimizin 11. makalesinde web sitemize \u00fcye olan kullan\u0131c\u0131lar taraf\u0131ndan belirtilen \u015fifrelerin -insanl\u0131k hali- unutulmas\u0131 durumunda kullan\u0131c\u0131n\u0131n nas\u0131l yeni \u015fifre talep edece\u011fini Identity mekanizmas\u0131 \u00fczerinden inceleyece\u011fiz. S\u00fcre\u00e7te b\u00fct\u00fcnl\u00fc\u011f\u00fc sa\u011flayabilmek ad\u0131na&#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":[2952,3002,3001],"class_list":["post-11955","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-net-core-identity","tag-identity-sifremi-unuttum","tag-sifremi-unuttum"],"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/11955","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=11955"}],"version-history":[{"count":27,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/11955\/revisions"}],"predecessor-version":[{"id":11985,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/posts\/11955\/revisions\/11985"}],"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=11955"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/categories?post=11955"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gencayyildiz.com\/blog\/wp-json\/wp\/v2\/tags?post=11955"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}