How to setup a custom authentication on asp.net mvc identity?

你说的曾经没有我的故事 提交于 2019-12-05 06:00:19

It seems like a custom authorization attribute would work. Here's an example implementation:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
public class RequiresSerialValidationAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        bool hasValidSerial = false;
        if (filterContext.HttpContext.Request.IsAuthenticated)
        {
            string userName = filterContext.HttpContext.User.Identity.Name;

            if (!string.IsNullOrWhiteSpace(userName))
            {       
                string serial = string.Empty;// TODO: Retrieve user's previously authenticated serial, perhaps from Session or a cookie?

                if(!string.IsNullOrWhiteSpace(serial))
                {
                    var service = DependencyResolver.Current.GetService<IYourAuthService>();
                    hasValidSerial = service.IsSerialValidForUser(userName, serial);
                }
            }
        }

        if (!hasValidSerial)
        {
            filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "yourserialauthcontroller", action = "yourauthaction", area = string.Empty }));
        }
        else
        {
            base.OnAuthorization(filterContext);
        }
    }
}

You would decorate the action methods with this attribute:

[RequireSerialValidation]
public ActionResult SomeAction()
{
}

The attribute would trigger a redirect to your challenge action, where you prompt your user for their serial. Assuming all goes well, you store their serial somewhere (Session could work here, or create an encrypted cookie), and then redirect back to the original action. On this second attempt, you've already verified that the action is allowed, so no redirect occurs.

Your authentication service can be whatever you want it to be. In this example, I assume you're using dependency injection and that you've configured the global dependency resolver. Given that, your IYourAuthService could look like this (omitting other methods):

public IYourAuthService
{
    bool IsSerialValidForUser(string userName, string serial);
}

with an implementation like so:

public YourAuthService : IYourAuthService
{
    public bool IsSerialValidForUser(string userName, string serial)
    {
        using(var context = new YourEntityFrameworkDbContext())
        {
            return context.Users.Any(u => u.UserName.Equals(userName, StringComparison.OrdinalIgnoreCase) && u.Serial.Equals(serial, StringComparison.OrdinalIgnoreCase));
        }
    }
}

This assumes you have a table called User (or Users) in your database, and that UserName and Serial are fields on that table. StringComparison.OrdinalIgnoreCase lets you do a case-insensitive, culture-insensitive match on the strings you're attempting to compare.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!