티스토리 뷰

반응형

WebAPI를 사용하려면 Authentication을 하는 방법에 대해서도 알아야 한다. 그래서 해당 내용을 찾았는데.. 설명이 너무 추상적으로 되어 있어서, 좀더 자세하게 c#으로 만들어 보았다. 역시나 PCLSample에 추가를 하고 테스트를 한 내용이다.

 

참고 포스트

Individual Accounts in ASP.NET Web API

http://www.asp.net/web-api/overview/security/individual-accounts-in-web-api

 

인증 방법은 크게

1) Individual Accounts in ASP.NET Web API

2) Forms Authentication

3) Integrated Windows Authentication

이렇게 3가지 정도 인것 같다. 여기서는 1번에 대해서만 다루도록 하겠다.

 

1. Create the Web API Project

 

File -> New Project -> Web -> ASP .NET Web Application -> 이름 입력 -> OK

이 포스트에서 사용할 프로젝트의 이름은 PCLSample.WebAPISecurity 이다. 아래 이미지는 참고 포스트의 있는 것을 그래도 사용한다.

 

Web API 템플릿 선택

 

Change Authentication 클릭 -> Individual User Accounts 선택

 

프로젝트가 생성이 되면 F5를 눌러서 실행해 본다.

 

위와 같이 따라 하면 기본적인 WebAPI 프로젝트가 생성이되고, 서비스를 추가할 수 있게 된다.

 

2. Send an HTTP Request to the Web API

참고 포스트에서는 Fiddler를 사용하여 직접 서버에 Request를 날려서 작업을 하는데, 여기서는 c# 코드로 작업된 내용을 보도록 하자.

 

PCLSample.PCL -> AccountHelper.cs

BaseUri : "http://localhost:22926"

 

        public async Task<string> GetValueTest()
        {
            var returnValue = string.Empty;

            using (var http = new HttpClient())
            {
                var uri = string.Format("{0}{1}", BaseUri, "/api/values");
                var resp = await http.GetStringAsync(uri);
                if (string.IsNullOrEmpty(resp) == false)
                {
                    returnValue = resp;
                }
            }
            return returnValue;
        }

 

위와 같이 호출하면 포스트에 있는 내용과 비슷하게 호출한 것이다.

 

/api/values를 찾아 보도록 하자.

새로운 프로젝트가 템플릿을 이용해서 생성될 때 테스트 용으로 등록된 WebAPI이다.

 

    [Authorize]
    public class ValuesController : ApiController
    {
        // GET api/values
        public IEnumerable<string> Get()
        {
            return new string[] { "value1", "value2" };
        }

        // GET api/values/5
        public string Get(int id)
        {
            return "value";
        }

        // POST api/values
        public void Post([FromBody]string value)
        {
        }

        // PUT api/values/5
        public void Put(int id, [FromBody]string value)
        {
        }

        // DELETE api/values/5
        public void Delete(int id)
        {
        }
    }

 

컨트롤러의 위에 [Authorize]를 추가한 것은, 해당 컨트롤러는 인증된 사용자만이 사용할 수 있다는 것을 의미한다.

그래서 GetValueTest()를 실행해서 데이터를 요청하면, 인증이 되어있지 않기 때문에 결과를 받을 수 없다.

 

3. Register a User

사용자 등록을 하도록 한다. 사용자 등록시 사용하는 Password는 6글자가 넘어야 한다.

 

클라이언트 사이드

PCLSample.PCL -> AccountHelper.cs

            BaseUri = "http://localhost:22926";
            ServiceUri = "/api/Account/";
...

        public async Task<bool> RegistUser(string id, string pw)
        {
            var returnValue = false;

            //등록자 데이터를 JSON 형태로 만든다.

            var data = new PCLUser
                    {
                        UserName = id,
                        Password = pw,
                        ConfirmPassword = pw
                    };

            var json = JsonConvert.SerializeObject(data);

            using (var http = new HttpClient())
            {
                HttpContent hc = new StringContent(json);
                hc.Headers.ContentType = new MediaTypeHeaderValue("application/json");
                var uri = string.Format("{0}{1}{2}", BaseUri, ServiceUri, "Register");
                var resp = await http.PostAsync(uri, hc);
                if (resp != null && resp.IsSuccessStatusCode == true)
                {

                    //등록이 완료되면 토큰을 가지고 온다.
                    returnValue = await GetToken(id, pw);
                }

            }
            return returnValue;
        }

...

 

    class PCLUser
    {
        public string UserName { get; set; }
        public string Password { get; set; }
        public string ConfirmPassword { get; set; }
    }

 

서버 사이드 : 서버 소스는 처음에 만들어진 그대로 사용

AccountController -> Register

 

        // POST api/Account/Register
        [AllowAnonymous]
        [Route("Register")]
        public async Task<IHttpActionResult> Register(RegisterBindingModel model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            IdentityUser user = new IdentityUser
            {
                UserName = model.UserName
            };

            IdentityResult result = await UserManager.CreateAsync(user, model.Password);
            IHttpActionResult errorResult = GetErrorResult(result);

            if (errorResult != null)
            {
                return errorResult;
            }

            return Ok();
        }

위의 메소드를 이용해서 사용자를 등록하면 ASP.Net 사용자 인증 db와 table들이 생성된다.

 

 

로컬DB에 2명의 사용자가 추가되어 있는 모습.

로컬db에 Account DB를 생성하려면, Web.config의 ConnectionString을 변경해 준다.

(자신의 DB설정에 맞는 값을 입력한다.)

  <connectionStrings>
    <add name="DefaultConnection" connectionString="Data Source=(local)\sqlexpress;Initial Catalog=PCLSample_Account;Integrated Security=SSPI" providerName="System.Data.SqlClient" />
  </connectionStrings>


 

4. Authenticate and Get a Bearer Token

인증하고 토큰 가져오기

 

클라이언트 사이드

AccountHelper -> GetToken

 

...

        public async Task<bool> GetToken(string id, string pw)
        {
            var returnValue = false;

            using (var http = new HttpClient())
            {
                HttpContent loginData = new FormUrlEncodedContent(
                        new List<KeyValuePair<string, string>>
                            {
                                new KeyValuePair<string, string>("grant_type", "password"),
                                new KeyValuePair<string, string>("username", id),
                                new KeyValuePair<string, string>("password", pw)
                            }
                    );
                try
                {
                    var apiLogin = string.Format("{0}{1}", BaseUri, "/Token");
                    var resp = await http.PostAsync(apiLogin, loginData);

                    if (resp != null && resp.IsSuccessStatusCode == true)
                    {

                        //인증 성공
                        var result = await resp.Content.ReadAsStringAsync();
                        if (string.IsNullOrEmpty(result) == false)
                        {

                            //토큰obj 저장
                            _clientToken = JsonConvert.DeserializeObject<PCLToken>(result);
                            returnValue = true;
                        }
                    }
                    else
                    {
                        if (resp.StatusCode == HttpStatusCode.BadRequest)
                        {

                           //인증 실패
                        }
                    }
                }
                catch (Exception ex)
                {
                    System.Diagnostics.Debug.WriteLine(ex.Message);
                }
            }

            return returnValue;
        }

...

 

    class PCLToken
    {
        public string access_token { get; set; }
        public string token_type { get; set; }
        public int expires_in { get; set; }
        public string userName { get; set; }
    }

 

서버 사이드 : 서버 소스는 그대로 사용

ApplicationOAuthProvider -> GrantResourceOwnerCredentials(), TokenEndpoint()

사용자 인증, 토큰 생성, 반환 과정

 

 

5. Using Token

클라이언트에서 반환된 토큰 사용하기

 

AccountHelper -> GetAuthHttp(), GetValue()

 

        public HttpClient GetAuthHttp()
        {
            HttpClient returnValue = new HttpClient();

            if (_clientToken == null) return returnValue;

            returnValue.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue(_clientToken.token_type, _clientToken.access_token);

            return returnValue;
        }

 

        public async Task<string> GetValue()
        {
            var returnValue = string.Empty;

            using (var http = GetAuthHttp())
            {
                var uri = string.Format("{0}{1}", BaseUri, "/api/values");
                var resp = await http.GetStringAsync(uri);
                if (string.IsNullOrEmpty(resp) == false)
                {
                    returnValue = resp;
                }
            }
            return returnValue;
        }

6. 실행 화면

 

 

실행은 PCLSample.WebAPISecurity 프로젝트와 PCLSample.W8 프로젝트만을 실행한다.

 

 

ID와 PW를 입력 후 Authentication버튼을 클릭하고, 정상적으로 처리가 되면 화면에 위와 같이 뜬다.

만약 인증을 할 수 없다는 메시지가 출력되면, Regist 버튼을 눌러서 등록을 시도한다. 등록시 비밀번호는 6자리 이상 입력해야 한다.

 

 

 

GetValue 버튼을 클릭하면 가지고 온 데이터를 화면에 출력한다.

 

7. 전체 소스

http://sdrv.ms/1bJHJPD

 

반응형
댓글