ASP.NET MVC 5在登入与权限控管中,微软似乎是推荐使用ASP.NET Identity,最简单的使用方式就是在新建专案时就将预设的无验证改成第二项的个别使用者帐户功能。
不过我在做小专案时,选的是无验证,想体验[AuthorizeAttribute]
的权限验证功能,似乎最简单的方式是使用.net早期的FormsAuthenticationu验证,看别人的文章也讲的很简单,複製三段code,登入登出的功能就完成了。
小弟不幸的一用之下,我的登入功能在登入成功后又重新导回登入画面,形成无穷迴圈卡了一个小时。
[HttpPost][AllowAnonymous][ValidateAntiForgeryToken]public ActionResult Login(LoginViewModel user){ if (ModelState.IsValid) { User u = _userService.Find(user.ID , user.Password); if(u != null) { FormsAuthenticationTicket ticket = new FormsAuthenticationTicket( 1, u.ID, DateTime.UtcNow, DateTime.UtcNow.AddMinutes(90), isPersistent: true, userData: u.Name,cookiePath: FormsAuthentication.FormsCookiePath ); string encTicket = FormsAuthentication.Encrypt(ticket); var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket) { Secure = true, HttpOnly = true }; Response.Cookies.Add(cookie); //return View(); return RedirectToAction("Index", "Lectures"); } } ModelState.AddModelError("", "无效的帐号或密码。"); return View(user);}
这个问题关键字很难下,一眼看过去会觉得大家的程式码差不多,但问题发生的原因是在于我的程式码比别人的Cookies有多了一个Secure = true
的设定,当下还真的觉得没什么,安全很重要,认为这是一个正常的设定,结果眉角在这里。
Secure = true
的意思是要求浏览器这一个Cookie仅能在HTTPS连线下才能传送给后端Server辨识身分,若无Https则不传送。
所以我在使用Vistual Studio开发时,我的IIS Express是在Http环境下,登入成功后我使用的是RedirectToAction,会传递302状态码给浏览器,要求浏览器连线至我的另外一个Controller的Index Action,此时因为Cookie设定Secure的关係,浏览器发现不是https连线,所以就没有把Cookie送到后端Server,后端没拿到Cookie便认为我是未登入的使用者,就重新导向至登入画面,呈现登入后一直卡在登入画面的结果。
这样的问题要解决就是强制网站使用Https来连线,在IIS与Azure App Service都有选项可以勾选来启用https伺服器,在测试环境中用VS2017内建的IIS Express的SSL开启方式请看我的另外一篇文章在Visual Studio 2017启用IIS Express的Https
剩下两段程式码
登出
public ActionResult Logout(){ FormsAuthentication.SignOut(); return RedirectToAction("Login");}
全站Web.config设定
在<system.web>
标籤中加入<authentication>
这一段标籤内容如下,其中loginUrl代表要导向的登入页网址
<configuration>... <system.web> ... <authentication mode="Forms"> <forms loginUrl="~/Users/Login" timeout="2880"></forms> </authentication> </system.web></configuration>
这是我的FB粉专,欢迎大家来按讚:FB:长庚的作业簿
还有我的部落格:Wordpress:长庚的作业簿