ASP.NET MVC Custom Form Authentication

1988 查看

身份认证是一个网站的基本功能。ASP.NET MVC给我们封装的接口也是越来越花哨,都看不懂了。我只是想自己从数据库里读取用户名和密码以及身份信息从而实现权限控制,就这么简单的事情。看来看去,还是FormAuthentication更简单粗暴。

下面就是如何定制FormAuthentication来实现权限控制。

首先创建一个ASP.NET MVC项目


1.png

你可以点开Change Authentication查看可选的Authentication方式。


2.png

然后项目就创建好了,ASP.NET MVC很贴心地给我们创建了一大堆认证的代码,可惜我并不想用。。。删删删!!!把Controllers和Views里面内容都删了吧。App_Start也该删的都删了。

接下来,找到web.config,找到<system.web>,里面默认的authentication mode是None。

  <system.web>
    <authentication mode="None" />
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
  </system.web>

把它改为下面的配置

<system.web>
    <authentication mode="Forms">
      <forms loginUrl="~/Account/Login" timeout="2880" />
    </authentication>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" />
  </system.web>

~/Account/Login是如果用户没有登录就方位了一个需要验证的页面时,自动跳转的地方。

web.config中还有一处代码,要把这段也删了。

<system.webServer>
    <modules>
      <remove name="FormsAuthentication" />
    </modules>
  </system.webServer>

然后就是我们自己的登录和注销逻辑了。新建一个Account的Controller,添加Login和Logout代码如下

public ActionResult Login()
{
    return View();
}

[HttpPost]
public ActionResult Login(string username, string password, , string returnUrl)
{
    // Lets first check if the Model is valid or not
    if (ModelState.IsValid)
    {
        using (userDbEntities entities = new userDbEntities())
        {
            // Now if our password was enctypted or hashed we would have done the
            // same operation on the user entered password here, But for now
            // since the password is in plain text lets just authenticate directly

            bool userValid = entities.Users.Any(user => user.username == username && user.password == password);

            // User found in the database
            if (userValid)
            {
                FormsAuthentication.SetAuthCookie(username, false);
                if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
                    && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
                {
                    return Redirect(returnUrl);
                }
                else
                {
                    return RedirectToAction("Index", "Home");
                }
            }
            else
            {
                ModelState.AddModelError("", "The user name or password provided is incorrect.");
            }
        }
    }

    // If we got this far, something failed, redisplay form
    return View(model);
}

public ActionResult LogOff()
{
    FormsAuthentication.SignOut();

    return RedirectToAction("Index", "Home");
}

数据库读取那里可以换成自己的逻辑就好了。

如果你想更近一步,比如说,区分普通用户和admin用户,那也是分分钟的事。
找到Global.asax, 在里面添加 Application_PostAuthenticateRequest 方法如下

protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
    if (FormsAuthentication.CookiesSupported == true)
    {
        if (Request.Cookies[FormsAuthentication.FormsCookieName] != null)
        {
            try
            {
                //let us take out the username now                
                string username = FormsAuthentication.Decrypt(Request.Cookies[FormsAuthentication.FormsCookieName].Value).Name;
                string roles = string.Empty;

                using (userDbEntities entities = new userDbEntities())
                {
                    User user = entities.Users.SingleOrDefault(u => u.username == username);
                    roles = user.Roles;
                }
                //let us extract the roles from our own custom cookie

                //Let us set the Pricipal with our user specific details
                HttpContext.Current.User  = new System.Security.Principal.GenericPrincipal(
                  new System.Security.Principal.GenericIdentity(username, "Forms"), roles.Split(';'));
            }
            catch (Exception)
            {
                //somehting went wrong
            }
        }
    }
}

然后,在需要验证身份的方法上,添加Roles标签就好了。

public class HomeController : Controller
{
    [Authorize]
    public ActionResult Index()
    {
        ViewBag.Message = "This can be viewed only by authenticated users only";
        return View();
    }

    [Authorize(Roles="admin")]
    public ActionResult AdminIndex()
    {
        ViewBag.Message = "This can be viewed only by users in Admin role only";
        return View();
    }
}

详情参考http://www.codeproject.com/Articles/578374/AplusBeginner-splusTutorialplusonplusCustomplusF