60

ASP.NET MVC 中用户授权/身份验证的最佳方法是什么?

我看到实际上有两种方法:

  • 使用内置的 ASP.NET 授权系统。
  • 使用带有我自己的用户、权限、用户组表等的自定义系统。

我更喜欢第二种选择,因为 User 是我的域模型的一部分(而且我对ASP.NET 的内置内容的经验为零),但我真的很想听听人们在这个领域所做的事情。

4

6 回答 6

32

实际上还有第三种方法。asp.net 成员资格功能基于提供者模型。您可以编写自定义提供程序,从而能够为数据的存储方式提供您自己的实现,同时保留 asp.net 成员资格的大部分好处。

关于该主题的一些文章:

http://msdn.microsoft.com/en-us/library/f1kyba5e.aspx

http://www.asp.net/learn/videos/video-189.aspx

http://www.15seconds.com/issue/050216.htm

http://davidhayden.com/blog/dave/archive/2007/10/11/CreateCustomMembershipProviderASPNETWebsiteSecurity.aspx

于 2009-02-07T16:42:36.387 回答
25

随风而去。MembershipProvider 对我的口味来说太重了。是的,可以以一种简化的方式实现它,但是你会闻到 NotSupportedException 或 NotImplementedException 的味道很糟糕。

通过完全自定义的实现,您仍然可以使用 IPrincipal、IIdentity 和 FormsAuth。你自己的登录页面到底有多难?

于 2009-02-07T23:13:46.470 回答
7

The easiest way is to use asp.net user names as role names. You can write your own authorizarion attribute to handle authorization:

public class CustomAuthorizationAttribute:AuthorizeAttribute
{
    public CustomAuthorizationAttribute():base()
    {
        Users = "registereduser";
    }
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        //You must check if the user has logged in and return true if he did that.
        return (bool)(httpContext.Session["started"]??false); 

    }
    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        filterContext.HttpContext.Response.Redirect("SessionManagement/Index/?returningURL=" + 
            filterContext.HttpContext.Server.UrlEncode(filterContext.HttpContext.Request.Url.ToString()));

    }

}

The code must handle the AuthorizeCore to return true if the user has started the session, and HandleUnauthorizedRequest to redirect the user to the login page (optionaly you can attach the returning url).

In then controller methods that need authorization, set the attribute over them:

public class SecretPageController {
    [CustomAuthorizationAttribute]
    ActionResult Index() {
        //Method that requires authorization
        return View();
    }

}

Also set the authorization method to "Forms" in the web config.

Web.config:

  <authentication>
      <forms timeout="120"></forms>
  </authentication>

Controller:

public SessionManagementController:Controller {
    public ActionResult Index(string returningURL)
    {
        return View("Index", new SessionModel() { ReturningURL = returningURL});
    }
    [HttpPost]        
    public ActionResult Index(SessionModel mod)
    {
        if (UserAuthenticated(mod.UserName, mod.Password))
        {
            FormsAuthentication.SetAuthCookie("registereduser", false);
            if (mod.UrlRetorno != null)
            {
                return Redirect(mod.ReturningURL);                    
            }
            return RedirectToAction("Index", "StartPage");
        }
        mod.Error = "Wrong User Name or Password";
        return View(mod);
    }
    bool UserAuthenticated(string userName, string password) {
       //Write here the authentication code (it can be from a database, predefined users,, etc)
        return true;
    }

    public ActionResult FinishSession()
    {
        HttpContext.Session.Clear();//Clear the session information
        FormsAuthentication.SignOut();
        return View(new NotificacionModel() { Message = "Session Finished", URL = Request.Url.ToString() });
    }

}

In the Controller, when the user enters its user name and password, set the forms authentication cookie to TRUE (FormsAuthentication.SetAuthCookie("registereduser",true)), signaling the user name (registereduser in the example) to be authenticathed. Then the user signs out, tell ASP.NET to do so calling FormsAuthentication.SignOut().

Model:

class SessionModel {
    public string UserName {get;set;}
    public string Password {get;set;}
    public string Error {get;set;}
}  

Use a model to store the user data.

View (that presents the SessionModel type):

        <div class="editor-label">
            <%: Html.LabelFor(model => model.UserName) %>
        </div>
        <div class="editor-field">
            <%: Html.TextBoxFor(model => model.UserName) %>
            <%: Html.ValidationMessageFor(model => model.UserName) %>
        </div>

        <div class="editor-label">
            <%: Html.LabelFor(model => model.Password) %>
        </div>
        <div class="editor-field">
            <%: Html.TextBoxFor(model => model.Password) %>
            <%: Html.ValidationMessageFor(model => model.Password) %>
        </div>
        <div class="field-validation-error"><%:Model==null?"":Model.Error??"" %></div>
        <%:Html.HiddenFor(model=>model.ReturningURL) %>
        <input type="submit" value="Log In" />

Use a view to get the data. In this example, there is a hidden field to store the returning URL

I hope this helps (I had to translate the code, so I'm not sure if it is 100% correct).

于 2011-04-14T13:21:30.103 回答
6

Yet another approach is to use ASP.NET membership for authentication, link your User class to ASP.NET members, and use your User class for more granular permissions. We do this, because it allows changing authentication providers very easily, while still retaining the ability to have a complex permission system.

In general, it's worth remembering that authentication/identity and storing permissions are not necessarily the same problem.

于 2009-02-09T15:20:38.583 回答
1

You may be interested in RPX for a free API to authenticate your users

http://blog.maartenballiauw.be/post/2009/07/27/Authenticating-users-with-RPXNow-(in-ASPNET-MVC).aspx

Try the ASP.Net MVC Membership Starter Kit for an administrative API

Screenshots

http://www.squaredroot.com/2009/08/07/mvcmembership-release-1-0/

Old locations changesets (historic)

http://mvcmembership.codeplex.com/SourceControl/list/changesets

New Location:

http://github.com/TroyGoode/MembershipStarterKit

于 2011-02-07T06:01:28.713 回答
0

This is a forth approach. Using the web matrix security classes you can use simple membership provider which can use EF so users and roles can be part of your domain model but also part of the IPrincipal and IIdentity MVC helpers.

I have created an example Github project to see how this can be used with automated self registration and email signup / password reset and the like.

于 2013-11-20T16:41:23.153 回答