6-16 Finishing Sign Up Mechanism
前幾章將登入完成以後,接著來製作註冊功能吧。註冊功能與登入功能非常相似,相信大家要自行完成註冊功能沒什麼難度。首先,在Client端新增SignupRequest,繼承Request,實作OnDefaultRequest。
完成發送Request的部分後,回到Inspector畫面,Operation Code選擇為Signup。
在NoliahFantasyServer.cs主類中記得要在Dictionary中新增新的SignupHandler。如不懂為何要做這一步的話,請記得將前兩章都看一下唷。
6-15 Using Handler To Respond Requisition In Photon Server
https://3dactionrpg.blogspot.tw/2018/05/6-15-using-handler-to-respond.html
6-14 Using Dictionary To Manage All Request
接下來處理我們在SignupHandler中的OnOperationRequest部分吧。先從Parameters中取得帳號跟密碼。
再使用UserManager確認該用戶是否已存在,如不存在才建立新帳號,如已存在則建立失敗。並使用ReturnCode方式回傳註冊結果。
回到Client端的SignupRequest,接收來自Server的ReturnCode後,將剩下的處理交給SignupWindow類。
主要因為註冊動作牽涉到UI變動,這部分的職責應劃分給SignupWindow。
以下提供本次有變動的原始碼。
Client端
SignupWindow.cs:
SignupRequest.cs:
Server端
SignupHandler.cs:
NoliahFantasyServer.cs:
接下來測試看看吧,首先輸入一個不存在的帳號密碼。嘗試登入後出現帳號或密碼錯誤。
接著來進行註冊,註冊成功。
再次按下註冊鈕,確實有檢查,並顯示該帳號已存在。
回到登入畫面,嘗試登入後顯示登入成功啦!
查詢MySQL資料庫後也確認該帳號確實有加進資料庫,不過這邊還是先提醒大家一點,密碼的儲存最好使用SHA-256並加鹽之類的方式儲存,才具有安全性唷,可不能這麼大喇喇地存在資料庫裡。
完成發送Request的部分後,回到Inspector畫面,Operation Code選擇為Signup。
接著到Server端新增SignupHandler繼承自BaseHandler,需要在建構子指定OperationCode為Signup。
在NoliahFantasyServer.cs主類中記得要在Dictionary中新增新的SignupHandler。如不懂為何要做這一步的話,請記得將前兩章都看一下唷。
6-15 Using Handler To Respond Requisition In Photon Server
https://3dactionrpg.blogspot.tw/2018/05/6-15-using-handler-to-respond.html
6-14 Using Dictionary To Manage All Request
接下來處理我們在SignupHandler中的OnOperationRequest部分吧。先從Parameters中取得帳號跟密碼。
再使用UserManager確認該用戶是否已存在,如不存在才建立新帳號,如已存在則建立失敗。並使用ReturnCode方式回傳註冊結果。
回到Client端的SignupRequest,接收來自Server的ReturnCode後,將剩下的處理交給SignupWindow類。
主要因為註冊動作牽涉到UI變動,這部分的職責應劃分給SignupWindow。
以下提供本次有變動的原始碼。
Client端
SignupWindow.cs:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class SignupWindow : Panel { [SerializeField] InputField accountInput; [SerializeField] InputField passwordInput; [SerializeField] LoginWindow loginWindow; [SerializeField] Text hintText; SignupRequest signupRequest; void Start(){ base.Start (); signupRequest = GetComponent(); } public void OnSignupButton(){ hintText.text = string.Empty; // 設定帳號及密碼參數後,呼叫OnDefaultRequest發送Request給Photon signupRequest.account = accountInput.text; signupRequest.password = passwordInput.text; signupRequest.OnDefaultRequest (); } public void OnShowLoginButton(){ this.Hide (); loginWindow.Show (); } public void OnSignupResponse(ReturnCode returnCode){ if (returnCode == ReturnCode.Success) { hintText.text = "註冊成功"; } else { hintText.text = "該帳號已存在"; } } }
SignupRequest.cs:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class SignupRequest : Request { [HideInInspector] public string account; [HideInInspector] public string password; SignupWindow signupWindow; void Start(){ base.Start (); signupWindow = GetComponent(); } public override void OnDefaultRequest () { Dictionary data = new Dictionary (); data.Add((byte)ParameterCode.Acccount, account); data.Add((byte)ParameterCode.Password, password); // 向Server發出Request,true代表建立可靠連接 PhotonEngine.Instance.GetPeer().OpCustom((byte)operationCode, data, true); } public override void OnOperationResponse (ExitGames.Client.Photon.OperationResponse operationResponse) { ReturnCode returnCode = (ReturnCode)operationResponse.ReturnCode; signupWindow.OnSignupResponse (returnCode); } }
Server端
SignupHandler.cs:
using System; using Photon.SocketServer; using NoliahFantasyServer.Constant; using NoliahFantasyServer.Manager; using NoliahFantasyServer.Model; namespace NoliahFantasyServer.Handler { public class SignupHandler : BaseHandler { public SignupHandler() { operationCode = OperationCode.Signup; } public override void OnOperationRequest(OperationRequest operationRequest, SendParameters sendParameters, ClientPeer clientPeer) { // 從OperationRequest取得帳號密碼資訊 object account; operationRequest.Parameters.TryGetValue((byte)ParameterCode.Acccount, out account); object password; operationRequest.Parameters.TryGetValue((byte)ParameterCode.Password, out password); // 從資料庫中查詢用戶是否已存在 UserManager userManager = new UserManager(); Users users = userManager.GetByAccount(account as string); // 使用short類型的ReturnCode簡單回傳結果 OperationResponse operationResponse = new OperationResponse((byte)OperationCode.Signup); // 用戶不存在,建立帳號 if(users == null){ users = new Users() { Account = account as string, Pwd = password as string, Registerdate = DateTime.Now }; userManager.Add(users); operationResponse.ReturnCode = (short)ReturnCode.Success; }else{ // 用戶已存在,回傳訊息 operationResponse.ReturnCode = (short)ReturnCode.Failed; } // 發送Response clientPeer.SendOperationResponse(operationResponse, sendParameters); } } }
NoliahFantasyServer.cs:
using System; using System.IO; using System.Collections.Generic; using Photon.SocketServer; using ExitGames.Logging; using ExitGames.Logging.Log4Net; using log4net.Config; using NHibernate; using NHibernate.Cfg; using NoliahFantasyServer.Constant; using NoliahFantasyServer.Handler; using NoliahFantasyServer.Model; using NoliahFantasyServer.Manager; namespace NoliahFantasyServer { public class NoliahFantasyServer : ApplicationBase { public static readonly ILogger logger = LogManager.GetCurrentClassLogger(); public static DictionaryhandlerDict = new Dictionary (); // 當Client端發出Request的時候 protected override PeerBase CreatePeer(InitRequest initRequest) { return new MyClientPeer(initRequest); } // Server端啟動的時候初始化 protected override void Setup() { InitLogger(); InitHandler(); } // Server端關閉的時候 protected override void TearDown() { } void InitLogger() { // 日誌初始化 log4net.GlobalContext.Properties["Photon:ApplicationLogPath"] = Path.Combine(this.ApplicationRootPath, "bin_Win64", "log"); FileInfo loggerConfig = new FileInfo(Path.Combine(this.BinaryPath, "log4net.config")); if (loggerConfig.Exists) { // 設置使用log4net的Log功能 LogManager.SetLoggerFactory(ExitGames.Logging.Log4Net.Log4NetLoggerFactory.Instance); // 讓log4net讀取config XmlConfigurator.ConfigureAndWatch(loggerConfig); } logger.Info("Setup Log4Net Compeleted!"); } void InitHandler(){ LoginHandler loginHandler = new LoginHandler(); handlerDict.Add(loginHandler.operationCode, loginHandler); SignupHandler signupHandler = new SignupHandler(); handlerDict.Add(signupHandler.operationCode, signupHandler); } } }
接下來測試看看吧,首先輸入一個不存在的帳號密碼。嘗試登入後出現帳號或密碼錯誤。
接著來進行註冊,註冊成功。
再次按下註冊鈕,確實有檢查,並顯示該帳號已存在。
回到登入畫面,嘗試登入後顯示登入成功啦!
查詢MySQL資料庫後也確認該帳號確實有加進資料庫,不過這邊還是先提醒大家一點,密碼的儲存最好使用SHA-256並加鹽之類的方式儲存,才具有安全性唷,可不能這麼大喇喇地存在資料庫裡。
留言
張貼留言