简体   繁体   中英

Return a custom response body for 401 with Windows Authentication with MVC under IIS

I'm currently working on an MVC app which has a particular URL which must be protected by Windows (NTLM) authentication.

Currently I have set up that particular URL to use Windows Authentication under IIS. This works, but I get the default HTML response:

401 - Unauthorized

Cache-Control: private
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/7.5
WWW-Authenticate: Negotiate,NTLM
X-Powered-By: ASP.NET
Date: Fri, 06 Dec 2013 14:53:11 GMT
Content-Length: 6347

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
<title>IIS 7.5 Detailed Error - 401.2 - Unauthorized</title> 
<!-- bla bla bla -->
</html> 

I want this exact response - headers and whatnot as they are - but with a different body and content type, a bit like the following:

401 - Unauthorized

Cache-Control: private
Content-Type: application/json; charset=utf-8
Server: Microsoft-IIS/7.5
WWW-Authenticate: Negotiate,NTLM
X-Powered-By: ASP.NET
Date: Fri, 06 Dec 2013 14:53:11 GMT
Content-Length: <whatever>

{ "message": "Bummer, you're not authenticated" }

This seems almost impossible to achieve without screwing up all the headers (and probably causing the whole challenge/response to never even happen). This question seems to imply it just isn't doable at this level, which I find hard to believe but it is all happening a bit early so it makes sense.

My ideal solution would be to have the NTLM authentication logic to be handled inside my application instead of by IIS, but I know of no way to do this:

[WindowsAuthentication]  // this filter would be under my control or customisable
public ActionResult ExampleWindowsAuth() {
    // all my stuff
}

The problem here is that NTLM authentication is not the most straightforward, and re-inventing the whole thing seems a little daft.

Can someone point me in the direction of a solution?

I did something similar by implementing my own class inheriting from ActionFilterAttribute and perform validation in there (in this case, checking the current user was in an AD group). By overriding the OnActionExecuting method, you have access to the HttpActionContext and I think this happens early enough in the process for what you're trying to achieve. You can then throw an HttpResponseException and include a custom message like so:

             var msg = string.Format("User {0} attempted to use {1} but is not a member of the AD group.", id, actionContext.Request.Method);
            _logger.Info(msg);
            throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.Unauthorized)
            {
                Content = new StringContent(msg),
                ReasonPhrase = msg
            });

Hope this helps! There is a walkthrough on MSDN here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM