在ASP.NETMVC5中,可以通过自定义身份验证来替代默认的ASP.NET Identity机制。以下是创建自定义身份验证并将其映射到默认过滤器的步骤。
1. 打开Visual Studio,创建一个新的项目。
2. 选择ASP.NET应用程序,并为项目命名。
3. 选择MVC模板。
4. 项目加载后,创建一个新的文件夹DAL(在这里可以调用自定义的用户身份验证实现方法)。
5. 现在项目结构应该如下所示:
6. 在DAL层添加两个类:User.cs和Repository.cs。
7. 在User.cs文件中粘贴以下代码:
public class User
{
public string Email { get; set; }
public string Roles { get; set; }
public string Password { get; set; }
}
8. 在Repository.cs文件中粘贴以下代码:
public static class Repository
{
static List<User> users = new List<User>() {
new User() { Email = "abc@gmail.com", Roles = "Admin,Editor", Password = "abcadmin" },
new User() { Email = "xyz@gmail.com", Roles = "Editor", Password = "xyzeditor" }
};
public static User GetUserDetails(User user)
{
return users.Where(u => u.Email.ToLower() == user.Email.ToLower() && u.Password == user.Password).FirstOrDefault();
}
}
9. 打开控制器文件夹中的“AccountController”。
10. 转到名为Login的方法(LoginViewModel model, string returnUrl)。
11. 删除Login方法中的以下代码:
12. 在Login方法中粘贴以下代码:
if (!ModelState.IsValid)
{
return View(model);
}
User user = new User() { Email = model.Email, Password = model.Password };
user = Repository.GetUserDetails(user);
if (user != null)
{
FormsAuthentication.SetAuthCookie(model.Email, false);
var authTicket = new FormsAuthenticationTicket(1, user.Email, DateTime.Now, DateTime.Now.AddMinutes(20), false, user.Roles);
string encryptedTicket = FormsAuthentication.Encrypt(authTicket);
var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
HttpContext.Response.Cookies.Add(authCookie);
return RedirectToAction("Index", "Home");
}
else
{
ModelState.AddModelError("", "Invalid login attempt.");
return View(model);
}
13. 转到AccountController中的public ActionResult LogOff()方法。
14. 用以下代码替换现有代码:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LogOff()
{
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
FormsAuthentication.SignOut();
return RedirectToAction("Index", "Home");
}
15. 打开Global.asax.cs文件。
16. 粘贴以下方法:
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
var authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
if (authTicket != null && !authTicket.Expired)
{
var roles = authTicket.UserData.Split(',');
HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(new FormsIdentity(authTicket), roles);
}
}
}
现在,身份验证和角色设置已完成。
1. 在Repository.cs类中创建了两个用户:Admin和Editor。
2. 现在在HomeController的“Index”方法中,只允许“Admin”访问,对于“About”方法,将允许“Admin”和“Editor”访问。首先用[Authorize]属性装饰HomeController以限制未经授权的访问,然后用上述讨论的角色分别装饰剩余的两个方法。
以下是参考代码片段:
[Authorize]
public class HomeController : Controller
{
[Authorize(Roles = "Admin")]
public ActionResult Index()
{
return View();
}
[Authorize(Roles = "Admin,Editor")]
public ActionResult About()
{
ViewBag.Message = "Your application description page.";
return View();
}
}
现在让运行应用程序,由于已经用[Authorize]属性装饰了HomeController,所以首先会看到登录页面,而不是默认的HomeController Index方法。
如果查看URL,它并没有直接调用Account/Login方法,而是有一个额外的ReturnUrl:
http://localhost:51581/Account/Login?ReturnUrl=%2F
以下是默认路由配置:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
所以当它直接转到HomeController时,它没有得到认证,所以它重定向到AccountController中的登录页面。现在输入创建的凭据。
现在当点击登录按钮时,它将重定向到HomeController中的Index方法。
当看到右上角时,它会从上下文中读取用户详细信息并显示Hello abc@gmail.com!
现在注销并输入编辑器凭据。
当点击登录页面时,将看到相同的屏幕,但右侧可以看到用户已经认证(Hello xyz@gmail.com!),因为他没有权限调用Index方法,所以它将显示相同的页面。