Does ASP.NET Identity 2 support anonymous users?

2019-02-06 23:39发布

问题:

I want to allow anonymous/not yet registered and registered users to post on my website.

Posts (table)
- Id (int)
- Subject (nvarchar)
- Body (nvarchar)
- UserId (uniqueidentifier)

The project uses the latest MS technologies (ASP.NET MVC 5+, C#...) How should I go about doing that?

Is ASP.NET Identity even the right solution?

What's the difference between these:

  • ASP.NET Identity
  • SimpleMembership
  • Membership Provider

Update I need to be able to differentiate not yet registered users and record their postings in the database.

Update 2 Then have the option to migrate to a registered account. Just like how stackoverflow used to allow anonymous users. Something like this but compatible with ASP.NET Identitfy http://msdn.microsoft.com/en-us/library/ewfkf772(v=vs.100).aspx

回答1:

ASP.NET Identity is the newest revision of authentication in ASP.NET. It's predecessor was SimpleMembership, which itself was an attempt to improve on the old ASP.NET Auth. Membership providers are not a separate kind of authentication system, but instead, a way to bootstrap ASP.NET Auth or SimpleMembership with additional functionality. If you had a particular login scenario not covered by the defaults, you could create a membership provider that would allow ASP.NET to interface with that system.

ASP.NET Identity supercedes everything else, and does not use membership providers. Instead, it's provides a very extensible foundation for authentication that through the use of standard APIs allows you to customize authentication in pretty much any way you like. It also has much more robust support for OAuth and external signin providers, and interfaces better with things like Active Directory, especially the Azure version in the cloud.

If you're starting on a new project go with Identity. Saying that it will remain for the forseeable future is a bit dangerous with Microsoft's seeming flavor-of-the-week approach to authentication in the past, but from my personal experience working with it, they seem to have finally gotten it right. I think you'll only see refinements and improvements going forward, rather than complete replacements.



回答2:

I want to answer one of the original questions: "I need to be able to differentiate not yet registered users and record their postings in the database.".

I have used Simple Membership before and I am using Asp.Net Identity Framework 2.2.1. In both cases I use anonymous identification to differentiate not yet registered users and authenticated users.

  1. Enable anonymous identification in your Web.config by adding <anonymousIdentification enabled="true" cookieName="YOUR_COOKIE_FOR_ANONYMOUS_IDENTIFICATION" />.
  2. You can get the anonymous id by Request.AnonymousID. That id is a GUID in string format.
  3. As other users mention, you can use whatever identity system you want, just remember to clear the anonymous id during the log out process. Typically after a user is successfully authenticated, you save either the username / userId with the anonymousId into persistence storage. By clearing the anonymousId when the user logs out, you can make sure the other authenticated users won't be able to associate with the same anonymousId.
  4. You can clear the anonymousId by AnonymousIdentificationModule.ClearAnonymousIdentifier(). Note: the AnonymousIdentificationModule is in System.Web.Security assembly. You can add a reference of System.Web or use CTRL + "." on the AnonymousIdentificationModule in your code to bring in System.Web.Security.


回答3:

ASP.NET Identity is a flexible framework for handling user authentication in your Web App. It's pretty awesome, and I would highly recommend you continue using it in your project.

Identity doesn't support anonymous users, per se...rather, it's a framework for letting you manage users that are authenticated. Identity will let you maintain local users, or if you want, users that authenticate with your web app via an external service (say, Facebook or Google).

It sounds like you want part of your web app to be accessible to users who are not authenticated. The way you'd achieve that is through attributes on your ASP.NET Controllers.

Adding the [Authorize] attribute to a Controller or Controller method will tell MVC to ensure the user is both authenticated and authorized. However, to allow anonymous users, simply put the [AllowAnonymous] attribute on the method you want to give public access to.

However, you'll still be able to tell if the user is authenticated or not. Consider this sample controller and method:

[Authorize]
public class PostController : Controller
{
    [AllowAnonymous]
    public ActionResult Index()
    {
        var isAuthenticated = User.Identity.IsAuthenticated;

        return View();
    }
}

That isAuthenticated will let you know if the current user is logged in or not, and if they are, you can get more information from the User.Identity object.


In regards to your general question about the differences between the membership frameworks, I'll defer to the official documentation which gives a great overview of the differences: http://www.asp.net/identity/overview/getting-started/introduction-to-aspnet-identity. You definitely want to use ASP.NET Identity in your web app.


Update Check out this sample code, which will help you differentiate between not yet registered users when recording posts to the database.

[Authorize]
public class PostController : Controller
{
    [AllowAnonymous]
    public HttpStatusCodeResult CreatePost(string postText)
    {
        // Use ASP.NET Identity to see if the user is logged in.  
        // If they are, we can get their User Id (blank otherwise)
        var isAuthenticated = User.Identity.IsAuthenticated;
        var userId = "";
        if (isAuthenticated)
            userId = User.Identity.GetUserId();

        // Create a new post object
        var post = new
        {
            PostText = postText,
            Anonymous = !isAuthenticated,
            UserId = userId
        };

        // Save the post to the database here

        return new HttpStatusCodeResult(HttpStatusCode.OK);
    }
}


回答4:

One way you could handle this is by using a cookie based authentication method. Browsers will send up any cookies associated with your domain with each web request, so they're an easy way to handle authentication. The idea here is that we'll have a cookie called ident that will store a user id we generate. I'm using Guids, but you could easily create an entry in your DB instead. When we get a web request, see if the cookie exists. If it does, we have their user id in the cookie. Otherwise, generate a new user id for them and set the cookie.

It's not perfect...if your user clears cookies you'll lose your ability to identity them, but it's probably the best you can do.

Here's some working code you can drop into your project and play with:

public class PostController : Controller
{
    [HttpGet]
    public ActionResult Index(string text)
    {
        if (string.IsNullOrWhiteSpace(text))
            return Content("Please specifiy a value for text.  i.e. /Post/Index?text=Message");

        var message = "";

        var isAuthenticated = Request.Cookies["ident"] != null;
        if (isAuthenticated)
        {
            var userId = Request.Cookies["ident"].Value;
            var post = new
            {
                Text = text,
                User = userId
            };
            // Save to database here
            message = "You are a previously recognized user, with UserId=" + userId;
        }
        else
        {
            var userId = Guid.NewGuid().ToString();
            var identCookie = new HttpCookie("ident", userId);
            Response.Cookies.Add(identCookie);

            var post = new
            {
                Text = text,
                User = userId
            };
            // Save to database
            message = "You are a new anonymous user. Your new UserId=" + userId;
        }

        return Content(message);
    }
}

If you do end up going this route and you want to reuse this logic among multiple requests, I'd highly recommend abstracting it out into a utility class or, better yet, override the IPrincipal User property in the controller. Take a look [here](ASP.NET MVC - Set custom IIdentity or IPrincipal for more information about setting a custom IPrincipal.



回答5:

The ASP.NET Identity system is designed to replace the previous ASP.NET Membership and Simple Membership systems. It includes profile support, OAuth integration, works with OWIN, and is included with the ASP.NET templates shipped with Visual Studio 2013

The ASP.NET user profile feature is designed to provide information that is unique to the current user. Profiles can work with either authenticated users or with anonymous (non-authenticated) users.

In some cases, your application might initially be maintaining personalization information for an anonymous user, but eventually the user logs in to your application. In that case, the user's identity changes from the assigned anonymous user identity to the identity provided by the authentication process.

When users log in (that is, when they stop being anonymous users), the MigrateAnonymous event is raised. You can handle this event to migrate information from the user's anonymous identity to the new authenticated identity, if necessary.

http://msdn.microsoft.com/en-us/library/vstudio/ewfkf772(v=vs.100).aspx

Best way to Migrate Anonymous Profile

http://odetocode.com/articles/440.aspx

public void Profile_OnMigrateAnonymous(object sender, ProfileMigrateEventArgs args)
{
  ProfileCommon anonymousProfile = Profile.GetProfile(args.AnonymousID);

  Profile.ZipCode = anonymousProfile.ZipCode;
  Profile.CityAndState = anonymousProfile.CityAndState;
  Profile.StockSymbols = anonymousProfile.StockSymbols;

  ////////
  // Delete the anonymous profile. If the anonymous ID is not 
  // needed in the rest of the site, remove the anonymous cookie.

  ProfileManager.DeleteProfile(args.AnonymousID);
  AnonymousIdentificationModule.ClearAnonymousIdentifier(); 

  // Delete the user row that was created for the anonymous user.
  Membership.DeleteUser(args.AnonymousID, true);

}