ASP.NET 웹 API 인증 올바르게 넣으면 401 Unauthorized상태가 반환 됩니다. 그러나

ASP.NET Web API 를 사용하는 동안 클라이언트 응용 프로그램에서 사용자를 인증하려고 합니다 . 나는 사이트의 모든 비디오를 보았고이 포럼 게시물 도 읽었 습니다 .

[Authorize]속성을 올바르게 넣으면 401 Unauthorized상태가 반환 됩니다. 그러나 사용자가 API에 로그인하도록 허용하는 방법을 알아야합니다.

Android 애플리케이션의 사용자 자격 증명을 API에 제공하고 사용자가 로그인 한 다음 모든 후속 API 호출을 사전 인증하고 싶습니다.



답변

사용자가 API에 로그인하도록 허용

요청과 함께 유효한 양식 인증 쿠키를 보내야합니다. 이 쿠키는 일반적으로 메서드 LogOn를 호출하여 인증 ( 작업) 할 때 서버에서 전송됩니다 [FormsAuthentication.SetAuthCookie( MSDN 참조 ).

따라서 클라이언트는 다음 두 단계를 수행해야합니다.

  1. LogOn사용자 이름과 비밀번호를 보내 HTTP 요청을 작업에 보냅니다. 이 작업은 FormsAuthentication.SetAuthCookie차례로 응답에서 양식 인증 쿠키를 설정하는 메서드 (자격 증명이 유효한 경우)를 호출합니다 .
  2. [Authorize]첫 번째 요청에서 검색 한 양식 인증 쿠키를 함께 전송 하여 보호 된 작업에 HTTP 요청을 보냅니다 .

예를 들어 보겠습니다. 웹 애플리케이션에 2 개의 API 컨트롤러가 정의되어 있다고 가정합니다.

인증 처리를 담당하는 첫 번째 사람 :

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;
    }
}

두 번째는 인증 된 사용자 만 볼 수있는 보호 된 작업을 포함합니다.

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

이제이 API를 사용하는 클라이언트 애플리케이션을 작성할 수 있습니다. 다음은 간단한 콘솔 애플리케이션 예제입니다 ( Microsoft.AspNet.WebApi.ClientMicrosoft.Net.HttpNuGet 패키지를 설치했는지 확인 ).

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");
            }
        }
    }
}

다음은 2 개의 HTTP 요청이 연결되는 방식입니다.

인증 요청 :

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"}

인증 응답 :

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

보호 데이터 요청 :

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

보호 데이터에 대한 대응 :

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"


답변

나는 안드로이드를 예로 든다.

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;
}

주의 사항 : i.localhost는 사용할 수 없습니다. Android 장치는 localhost를 자체 호스트로 보입니다. ii. IIS에 웹 API를 배포하는 경우 양식 인증을 열어야합니다.


답변

이 코드를 사용하고 데이터베이스에 액세스하십시오.

[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)
}


답변