티스토리 뷰

반응형

이전에 완성 했던 Authentication in Silverlight 5 & SQL CE 4.0 포스트에서 사용되었던 인증 서비스를 이번에는 윈폰에서 사용 하도록 하겠다. 실버라이트에서는 DomainService를 OData Endpoint로 연결 했다면, WP7에서는 Soap Endpoint로 연결한다는 점만 유의 하면 된다.

이전 포스트
Authentication in Silverlight 5 & SQL CE 4.0
http://kaki104.tistory.com/67
* 이 포스트의 자료를 다운 받아서 WP7Host.Web 프로젝트를 실행을 시켜 놓은 상태에서 아래에 있는 내용을 따라 한다.


1. Service References에 인증용 서비스를 추가한다.
추가할 주소는 http://localhost:33113/Services/WP7Host-Web-AuthenticationService.svc , 이름은 AuthenticationServiceReference 로 한다.

1) 일단, 서비스 레퍼런스를 추가하면 한가지 문제가 발생한다.
기존에 조회를 하고 있던 WP7ServiceReference의 서비스와 새로 추가한 AuthenticationServiceReference가 서로 충돌이 발생하는데. 기존에 만들어 놓았던 내용들에 NMessenger.WP7ServiceReference. 를 추가해서 구분을 시켜 준다.

2) 로그인 후의 정보는 쿠키를 이용해야 하기 때문에 쿠키를 사용 가능하도록 변경한다.
ServiceReferences.ClientConfig 파일을 열어서

  <basicHttpBinding>
      <binding name="BasicHttpBinding_WP7DomainServiceSoap" maxBufferSize="2147483647"
          enableHttpCookieContainer="true"
          maxReceivedMessageSize="2147483647">
          <security mode="None" />
      </binding>
      <binding name="BasicHttpBinding_AuthenticationServiceSoap" maxBufferSize="2147483647"
          enableHttpCookieContainer="true"
          maxReceivedMessageSize="2147483647">
          <security mode="None" />
      </binding>
  </basicHttpBinding>


2. MainPageViewModel.cs 추가 코드

  //Authentication Soap Client
  AuthenticationServiceSoapClient authClient;

...

  private string userID;
  /// <summary>
  /// 사용자 아이디
  /// </summary>
  public string UserID
  {
      get { return userID; }
      set
      {
          userID = value;
          FirePropertyChanged("UserID");
      }
  }

  private string userPW;
  /// <summary>
  /// 사용자 비밀번호
  /// </summary>
  public string UserPW
  {
      get { return userPW; }
      set
      {
          userPW = value;
          FirePropertyChanged("UserPW");
      }
  }

  private string userName;
  /// <summary>
  /// 사용자 이름
  /// </summary>
  public string UserName
  {
      get { return userName; }
      set
      {
          userName = value;
          FirePropertyChanged("UserName");
      }
  }

  private bool isLogin;
  /// <summary>
  /// 로그인 여부
  /// </summary>
  public bool IsLogin
  {
      get { return isLogin; }
      set
      {
          isLogin = value;
          FirePropertyChanged("IsLogin");
      }
  }

...

  /// <summary>
  /// 생성자
  /// </summary>
  public MainPageViewModel()
  {
      //도메인 서비스 솝 클라이언트
      soapClient = new WP7DomainServiceSoapClient();
      //조회 완료 이벤트 처리
      soapClient.GetWP7UriListSetCompleted += new EventHandler<GetWP7UriListSetCompletedEventArgs>(soapClient_GetWP7UriListSetCompleted);
      //저장 완료 이벤트 처리
      soapClient.SubmitChangesCompleted += new EventHandler<NMessenger.WP7ServiceReference.SubmitChangesCompletedEventArgs>(soapClient_SubmitChangesCompleted);

      //인증 서비스 솝 클라이언트
      authClient = new AuthenticationServiceSoapClient();
      authClient.LoginCompleted += new EventHandler<LoginCompletedEventArgs>(authClient_LoginCompleted);
      authClient.LogoutCompleted += new EventHandler<LogoutCompletedEventArgs>(authClient_LogoutCompleted);

  }

  /// <summary>
  /// 로그아웃 완료
  /// </summary>
  /// <param name="sender"></param>
  /// <param name="e"></param>
  void authClient_LogoutCompleted(object sender, LogoutCompletedEventArgs e)
  {
      if (e.Error == null)
      {
          var logout = e.Result.LogoutResult.RootResults.FirstOrDefault().DisplayName;
          UserName = "";
          IsLogin = false;
          MessageData = "You have been logged out.";
      }
  }

  /// <summary>
  /// 로그인 완료
  /// </summary>
  /// <param name="sender"></param>
  /// <param name="e"></param>
  void authClient_LoginCompleted(object sender, LoginCompletedEventArgs e)
  {
      if (e.Error == null && e.Result.LoginResult.RootResults != null)
      {
          UserName = e.Result.LoginResult.RootResults.FirstOrDefault().DisplayName;
          IsLogin = true;
          MessageData = "Login was successful.";
      }
      else
      {
          MessageData = "Can not login.";
      }
  }

  private ICommand loginCommand;
  /// <summary>
  /// 로그인 커맨드
  /// </summary>
  public ICommand LoginCommand
  {
      get
      {
          if (loginCommand == null)
          {
              loginCommand = new ActionCommand(() =>
              {
                  var login = new LoginRequest(UserID, UserPW, false, null);
                  authClient.LoginAsync(login);
              });
          }
          return loginCommand;
      }
  }

  private ICommand logoutCommand;
  /// <summary>
  /// 로그아웃 커맨드
  /// </summary>
  public ICommand LogoutCommand
  {
      get
      {
          if (logoutCommand == null)
          {
              logoutCommand = new ActionCommand(() =>
              {
                  var logout = new LogoutRequest();
                  authClient.LogoutAsync(logout);
              });
          }
          return logoutCommand;
      }
  }

3. MainPage.xaml은 적당히 수정하고 로그인을 시켜보자

Id : kaki104 , Pw : p@ssw0rd, role : Basic
Id : Administrator, Pw : mvc4dmin, role : administrator

먼저 kaki104로 로그인 해본다.

오른쪽에 로그인 사용자의 이름이 나오면 로그인 된 것이다.
그러면 이번에는 Input User Name에 서버에 등록할 이름을 입력하고 Regist를 눌러보자(이 등록은 채팅을 위한 이름이다. 인증 사용자를 등록하는 것은 아니다.)

kaki라는 이름으로 서버에 등록을 했다. 여기까지는 사실 로그인을 하지 않더라도 할 수 있다. 문제는 Unregist 버튼을 눌러서 서버에서 내 정보를 삭제를 할 경우이다. 이전 포스트에서도 삭제를 하기 위해서는 로그인을 해야 했고, administrator권한을 가지고 있어야지만 삭제가 가능 했었다. 그런 기능을 여기서도 구현을 해보자.

App.xaml.cs

  // Code to execute on Unhandled Exceptions
  private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
  {
      if (System.Diagnostics.Debugger.IsAttached)
      {
          e.Handled = true;
          switch (e.ExceptionObject.GetType().ToString())
          {
              case "FaultException":
                  break;
              default:
                  // An unhandled exception has occurred; break into the debugger
                  System.Diagnostics.Debugger.Break();
                  break;

          }
      }
  }


MainPageViewModel.cs

  private ICommand removeCommand;
  /// <summary>
  /// 삭제 커맨드 - 현재 사용자의 정보를 서버에서 완전히 삭제 한다
  /// </summary>
  public ICommand RemoveCommand
  {
      get
      {
          if (removeCommand == null)
          {
              removeCommand = new ActionCommand(() =>
              {
                  if (CurrentData != null)
                  {
                      //체인지셋 구성
                      ObservableCollection<NMessenger.WP7ServiceReference.ChangeSetEntry> removeItems = new ObservableCollection<NMessenger.WP7ServiceReference.ChangeSetEntry>();
                      NMessenger.WP7ServiceReference.ChangeSetEntry removeChangeSetEntry = new NMessenger.WP7ServiceReference.ChangeSetEntry
                      {
                          OriginalEntity = CurrentData,
                          Entity = CurrentData,
                          Operation = NMessenger.WP7ServiceReference.DomainOperation.Delete
                      };
                      //체인지셋에 수정할 데이터 입력
                      removeItems.Add(removeChangeSetEntry);
                      //SubmitChangeRequest 생성
                      NMessenger.WP7ServiceReference.SubmitChangesRequest request = new NMessenger.WP7ServiceReference.SubmitChangesRequest(removeItems);

                      //인증 쿠키 입력
                      soapClient.CookieContainer = authClient.CookieContainer;

                      //SubmitChangeAsync 실행
                      soapClient.SubmitChangesAsync(request, this);
                  }
              });
          }
          return removeCommand;
      }
  }

...

  /// <summary>
  /// 저장 완료 이벤트 처리
  /// </summary>
  /// <param name="sender"></param>
  /// <param name="e"></param>
  void soapClient_SubmitChangesCompleted(object sender, NMessenger.WP7ServiceReference.SubmitChangesCompletedEventArgs e)
  {
      if (e.Error == null)
      {
          //저장 완료 후 반환된 결과를 받아서
          ObservableCollection<NMessenger.WP7ServiceReference.ChangeSetEntry> returnChangeSet = e.Result.SubmitChangesResult;
          //그중 처음 데이터의 오퍼레이션을 확인하고
          var operation = returnChangeSet.FirstOrDefault().Operation;
          //오퍼레이션 종류에 따라 메시지 출력
          switch (operation)
          {
              case NMessenger.WP7ServiceReference.DomainOperation.Insert:
                  MessageData = "My channel uri regist successfully";
                  CurrentData = returnChangeSet.FirstOrDefault().Entity as WP7UriList;
                  break;
              case NMessenger.WP7ServiceReference.DomainOperation.Update:
                  MessageData = "My channel uri modify successfully";
                  break;
              case NMessenger.WP7ServiceReference.DomainOperation.Delete:
                  MessageData = "My channel uri unregist successfully";
                  CurrentData = null;
                  break;
          }
          if (1 == 1)
          {
          }
      }
      else
      {
          MessageData = "The operation failed.[" + e.Error.Message + "]";
      }
  }

이제 Unregist 버튼을 눌러서 확인을 해보자

서버에서 보낸 오류 메시지가 출력된다. 로그인을 하지 않았다면, 로그인이 필요한 서비스라는 메시지가 출력이 되었을 것이다.
Logout 버튼을 눌러서 Logout을 한 후 Administrator로 다시 로그인 한다.

Unregist 버튼을 클릭한다.

삭제가 정상 적으로 처리 되었다는 메시지가 출력된다.

 4. 윈도우 폰에서의 앱에서는
 PC에서 사용하는 거의 대부분의 서비스들을 모두 사용 할 수 있다. 즉, 일반 PC에서 개발해서 사용하는 업무용 프로그램을 윈도우 폰용으로도 충분히 개발을 할 수 있다는 이야기이다. 앞으로는 윈도우 폰의 앱이 단순히 흥미 위주의 앱이 아니라, 업무와 연관된 유용한 앱으로 거듭 태어나기를 바라면서 이번 포스트를 마치겠다.

NMessenger.zip
다운로드


 

반응형

'Previous Platforms' 카테고리의 다른 글

Interactive WebBrowser Control and App  (0) 2012.02.22
Daum OAuth in Windows Phone 7.1  (2) 2012.02.22
SpeechRecognition in Kinect for Windows  (15) 2012.02.17
Kinect for Windows 개봉  (0) 2012.02.15
Prism 4.0 MEF Container 1  (2) 2012.02.13
댓글