'Login as another user' MVC 4 Windows Auth

2019-01-17 08:33发布

问题:

I have an intranet project written in MVC 4 which uses Windows Authentication to authorise and authenticate users.

I need to add a 'Login as another user' functionality.

After some searching I found this solution which suggests returning a 401, and created the following Action (which is called using a form):

    // 
    // POST: /Home/LogOut

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult LogOut()
    {
        return new HttpUnauthorizedResult();
    }

The Action gets called, and the browser pops up a username and password window, however as the result redirects back to the Action, a 401 is always returned.

How do I redirect the user back to the previous action, once they have logged in with the new credentials?

Is there a way to invalidate the credentials on the server side instead of just returning a 401?

回答1:

People reverse engineered\decompiled some code from Sharepoint that happens to have this feature.

I tested it in an ASP.NET MVC 5 app and it's working as expected.

The code is based on decompiling the Microsoft.TeamFoundation.WebAccess which has the "Sign in as a different User" function.

public ActionResult LogOut()
{
    HttpCookie cookie = Request.Cookies["TSWA-Last-User"];

    if(User.Identity.IsAuthenticated == false || cookie == null || StringComparer.OrdinalIgnoreCase.Equals(User.Identity.Name, cookie.Value))
    {
        string name = string.Empty;

        if(Request.IsAuthenticated)
        {
            name = User.Identity.Name;
        }

        cookie = new HttpCookie("TSWA-Last-User", name);
        Response.Cookies.Set(cookie);

        Response.AppendHeader("Connection", "close");
        Response.StatusCode = 401; // Unauthorized;
        Response.Clear();
        //should probably do a redirect here to the unauthorized/failed login page
        //if you know how to do this, please tap it on the comments below
        Response.Write("Unauthorized. Reload the page to try again...");
        Response.End();

        return RedirectToAction("Index");
    }

    cookie = new HttpCookie("TSWA-Last-User", string.Empty)
    {
        Expires = DateTime.Now.AddYears(-5)
    };

    Response.Cookies.Set(cookie);

    return RedirectToAction("Index");

}

Source:

Force Sign in as a different user while using Windows Authentication in asp.net



回答2:

This method will always log the user out and redirect to the home page. I also added [AllowAnonymous] to make sure everybody can access this method.

    [AllowAnonymous]
    public ActionResult LogOut()
    {
        HttpCookie cookie = Request.Cookies["TSWA-Last-User"];

        cookie = new HttpCookie("TSWA-Last-User", string.Empty)
        {
            Expires = DateTime.Now.AddYears(-5)
        };
        Response.Cookies.Set(cookie);

        Response.AppendHeader("Connection", "close");
        Response.StatusCode = 401; // Unauthorized;
        Response.Clear();

        // redirect to home
        Response.Write("<script type='text/javascript'>");
        Response.Write("var getUrl = window.location; var baseUrl = getUrl.protocol + " + 
           "'//' + getUrl.host + '/' + getUrl.pathname.split('/')[1]; window.location.href = baseUrl; ");
        Response.Write("</script>");
        Response.End();           

        return RedirectToAction("Index");

    }


回答3:

For me, working this:

 public ActionResult LogOut()
{
    HttpCookie cookie = Request.Cookies["TSWA-Last-User"];

if(User.Identity.IsAuthenticated == false || cookie == null
{
    string name = string.Empty;

    if(Request.IsAuthenticated)
    {
        name = User.Identity.Name;
    }

    cookie = new HttpCookie("TSWA-Last-User", name);
    Response.Cookies.Set(cookie);

    Response.AppendHeader("Connection", "close");
    Response.StatusCode = 401; // Unauthorized;
    Response.Clear();
    //should probably do a redirect here to the unauthorized/failed login page
    //if you know how to do this, please tap it on the comments below
    Response.Write("Unauthorized. Reload the page to try again...");
    Response.End();

    return RedirectToAction("Index");
}

cookie = new HttpCookie("TSWA-Last-User", string.Empty)
{
    Expires = DateTime.Now.AddYears(-5)
};

Response.Cookies.Set(cookie);

return RedirectToAction("Index");

}

And in html

   <a href="@Url.Action("LogOut", "Home")" class="logout"><i class="fa fa-fw fa-power-off"></i> Salir</a>

   $(".logout").click(function () {
            logOut();
        });


    function logOut() {
        try {
            document.execCommand("ClearAuthenticationCache");
        } catch (e) { }
    }