登入驗證可以用資料庫帳密、AD(網域驗證),當然也可以用微軟自家的Azure AD,但是一般開發大多以前兩者為多拉,本篇文章以AD驗證為示範。
Web Form的AD驗證比較簡單,只要修改Web.config,在<connectionStrings></connectionStrings>區間加入以下資料:
<add name="ADConnectionString" connectionString="LDAP://AD主機位置/DC=網域URL第一段,DC=網域URL第二段" />
然後在<system.web></system.web>加入以下:
<membership defaultProvider="AbcAD">
<providers>
<add name="AbcAD" type="System.Web.Security.ActiveDirectoryMembershipProvider" connectionStringName="ADConnectionString" attributeMapUsername="sAMAccountName" />
</providers>
</membership>
<authentication mode="Forms">
<forms loginUrl="~/Login" defaultUrl="~/Default" />
</authentication>
<authorization>
<deny users="?" />
<allow users="*" />
</authorization>
在</system.web>後加入以下:
<!-- 開始-允許匿名存取的資料夾 -->
<location path="bundles">
<system.web>
<authorization>
<allow users="?" />
</authorization>
</system.web>
</location>
<location path="favicon.ico">
<system.web>
<authorization>
<allow users="?" />
</authorization>
</system.web>
</location>
<location path="Scripts">
<system.web>
<authorization>
<allow users="?" />
</authorization>
</system.web>
</location>
<location path="fonts">
<system.web>
<authorization>
<allow users="?" />
</authorization>
</system.web>
</location>
<location path="Content">
<system.web>
<authorization>
<allow users="?" />
</authorization>
</system.web>
</location>
<location path="api">
<system.web>
<authorization>
<allow users="?" />
</authorization>
</system.web>
</location>
<!-- 結束-允許匿名存取的資料夾 -->
然後去Login.aspx拉一個登入元件,這樣就大功告成了。
以MVC為主的登入驗證呢?那就更更更簡單,但是前提是用範本來做,才會簡單勒,請參考以下畫面:
以上建好後,是用Local DB的方式建立帳號與登入,當然把Local DB的 connectionStrings 改掉就可連接資料庫了,但問題是我們要的是AD登入喔,所以要小修改一下。
首先,一樣在 <connectionStrings></connectionStrings>區間 加入網域主機的位置。
然後在 <system.web></system.web> 區間加入以下:
<membership defaultProvider="AbcAD">
<providers>
<add name="AbcAD" type="System.Web.Security.ActiveDirectoryMembershipProvider" connectionStringName="ADConnectionString" attributeMapUsername="sAMAccountName" />
</providers>
</membership>
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" defaultUrl="~/" />
</authentication>
<authorization>
<deny users="?" />
<allow users="*" />
</authorization>
然後把以下註解掉:
<!-- <authentication mode="None"/> -->
<!-- <remove name="FormsAuthentication"/> -->
接著要再 </system.web> 後加入應該要允許匿名存取的資料夾,例如以下:
<!-- 開始-允許匿名存取的資料夾 -->
...略...
<location path="api">
<system.web>
<authorization>
<allow users="?" />
</authorization>
</system.web>
</location>
<!-- 結束-允許匿名存取的資料夾 -->
接著修改AccountController.cs ,以下有兩個TODO記得要補起來,才有防止駭客的能力。
public ActionResult Login(LoginViewModel model, string returnUrl)
{
// 檢查模型資料是否有綁好Required,如果沒有就掰掰。
if (!ModelState.IsValid)
{
return View(model);
}
// 改成用AD驗證
if (Membership.ValidateUser(model.UserName, model.Password))
{
// TODO: 登入成功要紀錄 "AccountController.Login() User.Identity.Name=" + User.Identity.Name);
FormsAuthentication.RedirectFromLoginPage(model.UserName, false);
}
else
{
// TODO: 失敗次數超過可以鎖定帳號或導向不能登入
ModelState.AddModelError("", "登入失敗。");
}
return View(model);
}
然後修改AccountViewModels.cs,只留下以下Class即可。
public class LoginViewModel
{
[Required]
[Display(Name = "帳號")]
public string UserName { get; set; }
[Required]
[DataType(DataType.Password)]
[Display(Name = "密碼")]
public string Password { get; set; }
}
最後修改Login.cshtml,把Email為帳號的部分改成UserName,如下:
@Html.ValidationSummary(true, "", new { @class = "text-danger" })
<div class="form-group">
@Html.LabelFor(m => m.UserName, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.TextBoxFor(m => m.UserName, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.UserName, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" })
<div class="col-md-10">
@Html.PasswordFor(m => m.Password, new { @class = "form-control" })
@Html.ValidationMessageFor(m => m.Password, "", new { @class = "text-danger" })
</div>
</div>
以上是Razor語法寫的,要花一點時間習慣。總之AD登入就大功告成了,但是登出是不能用的,要改成以下:
public ActionResult LogOff()
{
HttpContext.GetOwinContext().Authentication.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
FormsAuthentication.SignOut();
Session.Abandon();
// TODO: 登入成功回寫資料庫
return RedirectToAction("Account", "Login");
}
可以把一些用不到的砍一砍,真的搞定了。