各位先進好,上來請教一下ASP.NET MVC [Authorize]問題
最新剛接觸ASP.NET MVC先實作登入相關功能,但[Authorize]功能無法實現,卡關,想上來請教一下各位先進是否能幫忙看看,以下為程式碼實作相關資訊:
登入的Controller
#region 登入
[AllowAnonymous]
public ActionResult Login()
{
if (User.Identity.IsAuthenticated)
{
return RedirectToAction("Index", "Guestbook");
}
return View();
}
//傳入登入資料的Action
[HttpPost]//設定此Action只接受頁面POST資料傳入
[AllowAnonymous]
public ActionResult Login(MemberLoginView LoginMember)
{
string ValidateStr = memberService.CheckUserData(LoginMember.Account, LoginMember.Password);
if (String.IsNullOrEmpty(ValidateStr))
{
HttpContext.Session.Clear();
//角色先寫死
string RoleData = "User,Admin";
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
version: 1
, name: LoginMember.Account //你想要存放在User.Identy.Name的值,通常是使用者帳號
, issueDate: DateTime.Now
, expiration: DateTime.Now.AddMinutes(30)
, isPersistent: false //記住我 true or false//將管理者登入的Cookie設定成Session Cookie
, userData: RoleData //user data 看你想存放什麼//這邊可以放使用者名稱,而範例這邊是放使用者的群組代號
, cookiePath: FormsAuthentication.FormsCookiePath);
string encryptedTicket = FormsAuthentication.Encrypt(ticket);
HttpCookie httpCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
httpCookie.HttpOnly = true;
Response.Cookies.Add(httpCookie);
Session["auth"] = true;
return RedirectToAction("Index", "Guestbook");
}
else
{
ModelState.AddModelError("", ValidateStr);
return View(LoginMember);
}
}
#endregion
Global.asax
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
if (Request.IsAuthenticated)
{
FormsIdentity id = (FormsIdentity)User.Identity;
FormsAuthenticationTicket ticket = id.Ticket;
string[] roles = ticket.UserData.Split(new char[] { ',' });
Context.User = new GenericPrincipal(Context.User.Identity, roles);
}
}
Web.config
<authentication mode="Forms">
<forms loginUrl="~/Member/Login" timeout="2880"></forms>
</authentication>
驗證的Controller
//新增商品傳入資料時的Action
[Authorize]
public ActionResult Create()
{
return View();
}
以上是相關登入及[Authorize]相關程式碼,己測試登入功能驗證正常運作,Session["auth"] = true;也有正常寫入確定有登入,但套用[Authorize]關鍵字,就會被重新導向到的登入頁面。
登入後所寫入的Cookies是否有什麼方法可以查詢驗證相關資訊的呢?
實在不太清楚問題出在那裡,再請各位先進指教了,先感謝了~
we.config 有加這一段嗎?
<membership>
<providers>
<clear />
<add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="LineDB" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="3" minRequiredPasswordLength="4" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" />
</providers>
</membership>
<profile>
<providers>
<clear />
<add name="AspNetSqlProfileProvider" type="System.Web.Profile.SqlProfileProvider" connectionStringName="LineDB" applicationName="/" />
</providers>
</profile>
<roleManager enabled="false">
<providers>
<clear />
<add name="AspNetSqlRoleProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="LineDB" applicationName="/" />
<add name="AspNetWindowsTokenRoleProvider" type="System.Web.Security.WindowsTokenRoleProvider" applicationName="/" />
</providers>
</roleManager>
您好,這個沒有加也,請問這部份程式碼是要加在web.config裡的那一個tag裡面呢?
看了許多登入相關教學文件都沒有提過要加這些內容至web.config,再請先進指教了,謝謝~
就加在這一段下面:
<authentication mode="Forms">
<forms loginUrl="~/Member/Login" timeout="2880"></forms>
</authentication>
己加入以上先進提供的程式碼測試登入驗證功能,結果也是一樣無法以[Authorize]驗證成功!
補充說明:
1.若註解掉[Authorize]關鍵字,則可以順利進入該功能的View
2.若加入[Authorize]關鍵字,驗證不成功,則重新導向的頁面並非我所指定的
<forms loginUrl="~/Member/Login" timeout="2880"></forms>
這個頁面,而是重新導向至微軟建立專案時預設幫我們建好的登入頁面,http://localhost:4875/Account/Login?ReturnUrl=%2FHome%2FCreate
不知道是不是微軟有幫我們建立登入功能,造成我們自訂的功能無法正常運作的問題,又或者要如何把微軟幫我們建立的登入功能Disable掉?
在Startup.Auth.cs找到/Account/Login,不知道是不是微軟預設的這段驗證相關的程式碼有影響,但不知道該如何調整!
// 如需設定驗證的詳細資訊,請瀏覽 http://go.microsoft.com/fwlink/?LinkId=301864
public void ConfigureAuth(IAppBuilder app)
{
// 設定資料庫內容、使用者管理員和登入管理員,以針對每個要求使用單一執行個體
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
// 讓應用程式使用 Cookie 儲存已登入使用者的資訊
// 並使用 Cookie 暫時儲存使用者利用協力廠商登入提供者登入的相關資訊;
// 在 Cookie 中設定簽章
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/Account/Login"),
Provider = new CookieAuthenticationProvider
{
// 讓應用程式在使用者登入時驗證安全性戳記。
// 這是您變更密碼或將外部登入新增至帳戶時所使用的安全性功能。
OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
validateInterval: TimeSpan.FromMinutes(30),
regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}
});
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// 讓應用程式在雙因素驗證程序中驗證第二個因素時暫時儲存使用者資訊。
app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));
// 讓應用程式記住第二個登入驗證因素 (例如電話或電子郵件)。
// 核取此選項之後,將會在用來登入的裝置上記住登入程序期間的第二個驗證步驟。
// 這類似於登入時的 RememberMe 選項。
app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);
// 註銷下列各行以啟用利用協力廠商登入提供者登入
//app.UseMicrosoftAccountAuthentication(
// clientId: "",
// clientSecret: "");
//app.UseTwitterAuthentication(
// consumerKey: "",
// consumerSecret: "");
//app.UseFacebookAuthentication(
// appId: "",
// appSecret: "");
//app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
//{
// ClientId = "",
// ClientSecret = ""
//});
}
我猜你的MemberController有加 [Authorize],才會再導向 http://localhost:4875/Account/Login?ReturnUrl=%2FHome%2FCreate
我的Login method是寫在我建的MemberController.cs
Login相關method沒加入[Authorize],如原文Controller的程式碼。
webconfig有加入以下程式碼:
<authentication mode="Forms">
<forms loginUrl="~/Member/Login" timeout="2880"></forms>
</authentication>
這段程式碼我的理解應該是=>若有[Authorize]關鍵字的method驗證失敗,則會重新導向至loginUrl="~/Member/Login",但我目前專案的結果卻是重新導向/Account/Login,所以我才在尋找到底是那一段程式碼會把驗證失敗後的頁面重新導向/Account/Login。
所以目前整個流程條列式整理如下:
1.進入自訂的MemberController登入頁面,如原文程式碼 (成功)
2.輸入帳號密碼驗證並寫入Session,如原文程式碼 (成功)
3.帳號密碼驗證成功後重新導向至首頁 (成功)
4.測試進入有加[Authorize]關鍵字的method頁面,會被重新導向至/Account/Login,,並非重新導向至loginUrl="~/Member/Login" (失敗)
5.測試同步聚4,若把[Authorize]關鍵字拿掉,則可正常進入該頁面,並執行相關動作
經以上測試驗證流程,確認是因為[Authorize]關鍵字無法正常驗證導致頁面重新導向至/Account/Login,但/Account/Login此頁面為微軟專案預設建立的,此新專案也無任何自訂的程式碼有將頁面重新導向至/Account/Login,所以目前個人最大的瓶頸就是:
1.Controller裡的[Authorize]無法正常驗證
2.webconfig裡的loginUrl="~/Member/Login"無法正常導向
然後前輩指點的MemberController我己確認過,並沒有加入[Authorize]關鍵字。
想要確認幾點問題:
1.關於登入驗證的功能若沒有使用專案預設的DB,而使用自己安裝的MSSQL應該可以吧?
2.在建立專案時的變更驗證選項,是否應該要選擇"無驗證"呢?上面出問題的專案是選擇"個別使用者帳戶"下所建立的專案,所以專案預設會產生一套驗證機制,以及AccountController相關程式碼
web.config 有加這個嗎?
<authorization>
<deny users="?" />
</authorization>