ASP.NET Web API Authentication

I am looking to authenticate a user from a client application while using the ASP.NET Web API. I have watched all the videos on the site and also read this forum post.

Putting the [Authorize] attribute correctly returns a 401 Unauthorized status. However, I need to know how to allow a user to log in to the API.

I want to provide user credentials from an Android application to the API, get the user logged in, and then have all subsequent API calls pre-authenticated.


allow a user to log in to the API

You need to send a valid Forms Authentication cookie along with the request. This cookie is usually sent by the server when authenticating ( LogOn action) by calling the [FormsAuthentication.SetAuthCookie method (see MSDN).

So the client needs to perform 2 steps:

  • Send an HTTP request to a LogOn action by sending the username and password. In turns this action will call the FormsAuthentication.SetAuthCookie method (in case the credentials are valid) which in turn will set the forms authentication cookie in the response.
  • Send an HTTP request to an [Authorize] protected action by sending along the forms authentication cookie it retrieved in the first request.
  • Let's take an example. Suppose that you have 2 API controllers defined in your web application:

    The first one responsible for handling authentication:

    public class AccountController : ApiController
    {
        public bool Post(LogOnModel model)
        {
            if (model.Username == "john" && model.Password == "secret")
            {
                FormsAuthentication.SetAuthCookie(model.Username, false);
                return true;
            }
    
            return false;
        }
    }
    

    and the second one containing protected actions that only authorized users can see:

    [Authorize]
    public class UsersController : ApiController
    {
        public string Get()
        {
            return "This is a top secret material that only authorized users can see";
        }
    }
    

    Now we could write a client application consuming this API. Here's a trivial console application example (make sure you have installed the Microsoft.AspNet.WebApi.Client and Microsoft.Net.Http NuGet packages):

    using System;
    using System.Net.Http;
    using System.Threading;
    
    class Program
    {
        static void Main()
        {
            using (var httpClient = new HttpClient())
            {
                var response = httpClient.PostAsJsonAsync(
                    "http://localhost:26845/api/account", 
                    new { username = "john", password = "secret" }, 
                    CancellationToken.None
                ).Result;
                response.EnsureSuccessStatusCode();
    
                bool success = response.Content.ReadAsAsync<bool>().Result;
                if (success)
                {
                    var secret = httpClient.GetStringAsync("http://localhost:26845/api/users");
                    Console.WriteLine(secret.Result);
                }
                else
                {
                    Console.WriteLine("Sorry you provided wrong credentials");
                }
            }
        }
    }
    

    And here's how the 2 HTTP requests look on the wire:

    Authentication request:

    POST /api/account HTTP/1.1
    Content-Type: application/json; charset=utf-8
    Host: localhost:26845
    Content-Length: 39
    Connection: Keep-Alive
    
    {"username":"john","password":"secret"}
    

    Authentication response:

    HTTP/1.1 200 OK
    Server: ASP.NET Development Server/10.0.0.0
    Date: Wed, 13 Jun 2012 13:24:41 GMT
    X-AspNet-Version: 4.0.30319
    Set-Cookie: .ASPXAUTH=REMOVED FOR BREVITY; path=/; HttpOnly
    Cache-Control: no-cache
    Pragma: no-cache
    Expires: -1
    Content-Type: application/json; charset=utf-8
    Content-Length: 4
    Connection: Close
    
    true
    

    Request for protected data:

    GET /api/users HTTP/1.1
    Host: localhost:26845
    Cookie: .ASPXAUTH=REMOVED FOR BREVITY
    

    Response for protected data:

    HTTP/1.1 200 OK
    Server: ASP.NET Development Server/10.0.0.0
    Date: Wed, 13 Jun 2012 13:24:41 GMT
    X-AspNet-Version: 4.0.30319
    Cache-Control: no-cache
    Pragma: no-cache
    Expires: -1
    Content-Type: application/json; charset=utf-8
    Content-Length: 66
    Connection: Close
    
    "This is a top secret material that only authorized users can see"
    

    I take android as example.

    public abstract class HttpHelper {
    
    private final static String TAG = "HttpHelper";
    private final static String API_URL = "http://your.url/api/";
    
    private static CookieStore sCookieStore;
    
    public static String invokePost(String action, List<NameValuePair> params) {
        try {
            String url = API_URL + action + "/";
            Log.d(TAG, "url is" + url);
            HttpPost httpPost = new HttpPost(url);
            if (params != null && params.size() > 0) {
                HttpEntity entity = new UrlEncodedFormEntity(params, "UTF-8");
                httpPost.setEntity(entity);
            }
            return invoke(httpPost);
        } catch (Exception e) {
            Log.e(TAG, e.toString());
        }
    
        return null;
    }
    
    public static String invokePost(String action) {
        return invokePost(action, null);
    }
    
    public static String invokeGet(String action, List<NameValuePair> params) {
        try {
            StringBuilder sb = new StringBuilder(API_URL);
            sb.append(action);
            if (params != null) {
                for (NameValuePair param : params) {
                    sb.append("?");
                    sb.append(param.getName());
                    sb.append("=");
                    sb.append(param.getValue());
                }
            }
            Log.d(TAG, "url is" + sb.toString());
            HttpGet httpGet = new HttpGet(sb.toString());
            return invoke(httpGet);
        } catch (Exception e) {
            Log.e(TAG, e.toString());
        }
    
        return null;
    }
    
    public static String invokeGet(String action) {
        return invokeGet(action, null);
    }
    
    private static String invoke(HttpUriRequest request)
            throws ClientProtocolException, IOException {
        String result = null;
        DefaultHttpClient httpClient = new DefaultHttpClient();
    
        // restore cookie
        if (sCookieStore != null) {
            httpClient.setCookieStore(sCookieStore);
        }
    
        HttpResponse response = httpClient.execute(request);
    
        StringBuilder builder = new StringBuilder();
        BufferedReader reader = new BufferedReader(new InputStreamReader(
                response.getEntity().getContent()));
        for (String s = reader.readLine(); s != null; s = reader.readLine()) {
            builder.append(s);
        }
        result = builder.toString();
        Log.d(TAG, "result is ( " + result + " )");
    
        // store cookie
        sCookieStore = ((AbstractHttpClient) httpClient).getCookieStore();
        return result;
    }
    

    Attention please: i.localhost cannot be used. Android device look localhost as itself host. ii.If deploy the web API in IIS, the Form authentication must be opened.


    使用此代码并访问数据库

    [HttpPost]
    [Route("login")]
    public IHttpActionResult Login(LoginRequest request)
    {
           CheckModelState();
           ApiResponse<LoginApiResponse> response = new ApiResponse<LoginApiResponse>();
           LoginResponse user;
           var count = 0;
           RoleName roleName = new RoleName();
           using (var authManager = InspectorBusinessFacade.GetAuthManagerInstance())
           {
               user = authManager.Authenticate(request); 
           } reponse(ok) 
    }
    
    链接地址: http://www.djcxy.com/p/20536.html

    上一篇: 浏览器取消请求时出现ASP.NET Web API OperationCanceledException

    下一篇: ASP.NET Web API身份验证