如何实现共享软件网络授权认证,包括注册新用户、登录、修改密码等操作
开发共享软件,传统的是采用注册码验证方式,这种方式是大多数共享软件采用的方式,另外还有一种常见的验证方式,就是通过网络授权认证的方式,这种方式通过在程序中调用服务器的服务进行。一般具有验证用户名可用、注册新用户、用户登录认证、用户修改密码等操作,另外还需要配备一个网络授权入口给管理员对注册的用户进行授权控制。
这个是为了进行网络授权认证搭建的一个简单的管理后台,用户在共享软件客户端通过调用服务器的服务连接,可以注册一个新用户,或者进行登录获取身份信息(试用、已注册、已禁用等状态),还可以通过服务接口来进行密码修改,提高安全性及使用合理性。
网络认证有几个好处,一是可以不受限于传统的机器码限制,可以在多个计算机中登录使用;二是方便软件开发者集中管理用户信息,动态授权或者取消授权用户的身份信息,还可以获取更多用户的信息,以便进行推广沟通。
开发网络授权业务后台的时候,需要创建一个服务接口给软件客户端进行调用,这个服务接口可以通过创建ashx这样的处理程序来进行处理,这种类和ASPX页面处理有些少不同,这个提供更原始的输出,需要什么输出什么。
这个处理页面和传统的aspx页面一样,都接受类似test.aspx?id=1&name=test 这样的参数,它的处理代码如下所示。
/// <summary> /// 用户测试账号可用性、注册新用户、登录验证、修改密码等操作业务处理类 /// </summary> [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] public class UserAction : IHttpHandler { public void ProcessRequest(HttpContext context) { //context.Response.ContentType = "text/plain"; //context.Response.Write("Hello World"); context.Request.ContentEncoding = Encoding.Default ; string action = context.Request["action"]; string usr = context.Request["usr"]; string password = context.Request["pass"]; string machineCode = context.Request["code"];
通过获取参数的内容,我们就可以进行不同的业务处理,这里我使用了一个Action的标志,用来区分是做什么操作的。
string action = context.Request["action"]; string usr = context.Request["usr"]; string password = context.Request["pass"]; string machineCode = context.Request["code"]; bool result = false; switch (action) { case "r"://检测注册 UserAction.ashx?action=r&usr=&pass=&code= string reg = BLLFactory<SoftwareRegister>.Instance.CheckRegisterd(usr, password, machineCode); context.Response.ContentType = "text/plain"; context.Response.Write(reg); break;
以上就是执行一个检测用户是否注册的操作代码,如果授权注册了,返回true,如果用户登录成功但没有授权,返回False,其他错误返回字符串描述。具体的BLLFactory<SoftwareRegister>.Instance.CheckRegisterd逻辑处理代码如下所示。
public string CheckRegisterd(string username, string passwod, string code) { bool result = VerifyUser(username, passwod, code); if (result) { string condition = string.Format(" Username='{0}' and IsForbid <> true", username); SoftwareRegisterInfo info = base.FindSingle(condition); if (info != null) { if (info.IsRegister) { if (info.MachineCode != code && info.LastAccessed.AddMinutes(10) >= DateTime.Now) { return "一个账号多处登录!"; } else { info.MachineCode = code; info.LastAccessed = DateTime.Now; base.Update(info, info.ID.ToString()); return "true"; } } else { return "false"; } } else { return "账号被锁定"; } } else { return "账号密码不正确"; } }
那我们在共享软件的地方如何验证用户身份呢,就是通过传递页面参数并调用ashx接口处理,判断返回值即可。具体操作代码如下所示。为了简化操作,里面使用了一个我的公用类库来提交数据(辅助类HttpHelper)。
private void btnOK_Click(object sender, EventArgs e) { if (this.txtUserName.Text.Length == 0) { MessageExUtil.ShowTips("请输入账号密码登录"); return; } string data = string.Format("action=r&usr={0}&pass={1}&code={2}", this.txtUserName.Text, this.txtPassword.Text, WHC.OrderWater.Commons.HardwareInfoHelper.GetMacAddress()); HttpHelper helper = new HttpHelper(); string result = helper.GetHtml(Portal.gc.UserActionUrl, data, true); if (!string.IsNullOrEmpty(result)) { if (result.ToLower() == "true") { Portal.gc.UserName = this.txtUserName.Text; Portal.gc.Registered = true; MessageExUtil.ShowTips("登录成功"); this.DialogResult = DialogResult.OK; } else if (result.ToLower() == "false") { MessageExUtil.ShowTips("未授权用户,但可继续使用"); Portal.gc.UserName = this.txtUserName.Text; Portal.gc.Registered = false; this.DialogResult = DialogResult.OK; } else { MessageExUtil.ShowTips("操作失败:" + result); } } else { MessageExUtil.ShowTips("操作失败"); } }
以上就是一个功能的完整实现流程,其他的功能也是类似操作,下面给出ashx的完整代码实现,供大家参考,并指正。
/// <summary> /// 用户测试账号可用性、注册新用户、登录验证、修改密码等操作业务处理类 /// </summary> [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] public class UserAction : IHttpHandler { public void ProcessRequest(HttpContext context) { //context.Response.ContentType = "text/plain"; //context.Response.Write("Hello World"); context.Request.ContentEncoding = Encoding.Default ; string action = context.Request["action"]; string usr = context.Request["usr"]; string password = context.Request["pass"]; string machineCode = context.Request["code"]; string conditon = ""; bool result = false; switch (action) { case "r"://检测注册 UserAction.ashx?action=r&usr=&pass=&code= string reg = BLLFactory<SoftwareRegister>.Instance.CheckRegisterd(usr, password, machineCode); context.Response.ContentType = "text/plain"; context.Response.Write(reg); break; case "g"://测试登录UserAction.ashx?action=g&usr=&pass=&code= result = BLLFactory<SoftwareRegister>.Instance.VerifyUser(usr, password, machineCode); context.Response.ContentType = "text/plain"; context.Response.Write(result); break; case "t"://测试用户名UserAction.ashx?action=t&usr= result = BLLFactory<SoftwareRegister>.Instance.IsExistKey("Username", usr); context.Response.ContentType = "text/plain"; context.Response.Write(!result);//如果存在则返回False,否则True break; case "a"://添加用户UserAction.ashx?action=a&usr=&pass=&sex=&code=&qq=&email= bool exist = BLLFactory<SoftwareRegister>.Instance.IsExistKey("Username", usr); if (!exist) { password = context.Request["pass"]; machineCode = context.Request["code"]; string sex = context.Request["sex"]; string qq = context.Request["qq"]; string email = context.Request["email"]; SoftwareRegisterInfo newInfo = new SoftwareRegisterInfo(); newInfo.Username = usr; newInfo.Password = MD5Util.GetMD5_16(password); newInfo.Sex = sex; newInfo.MachineCode = machineCode; newInfo.QQ = qq; newInfo.Email = email; result = BLLFactory<SoftwareRegister>.Instance.Insert(newInfo); } context.Response.ContentType = "text/plain"; context.Response.Write(result); break; case "ep"://修改用户密码UserAction.ashx?action=ep&usr=&pass=&newp= conditon = string.Format("Username='{0}'", usr); password = context.Request["pass"]; string newpass = context.Request["newp"]; SoftwareRegisterInfo info = BLLFactory<SoftwareRegister>.Instance.FindSingle(conditon); if (info != null) { if (MD5Util.GetMD5_16(password) == info.Password) { info.Password = MD5Util.GetMD5_16(newpass); result = BLLFactory<SoftwareRegister>.Instance.Update(info, info.ID.ToString()); } } context.Response.ContentType = "text/plain"; context.Response.Write(result); break; } } public bool IsReusable { get { return false; } } }
如果要考虑安全性,可能整体还需要进行一定的调整,不过具体操作,已经实现了我们所需要的功能了。欢迎大家一起探讨。
转载请注明出处:撰写人:伍华聪 http://www.iqidi.com