在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
在通常情况下,如果使用AJAX方式调用WebService,则可能被恶意用户利用,造成性能以及安全性的问题,所以我们需要使用一些验证方式来保护WebService,最常见方式就是Forms Authentication,这也是一种用法很简单的方式 一个使用FormsAuthentication保护WebService调用的示例首先创建一个名为ProtectedService的WebService,代码如下 using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Services; using System.Web.Security; using System.Security.Authentication; /// <summary> ///ProtectedService 的摘要说明 /// </summary> [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] //若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。 [System.Web.Script.Services.ScriptService] public class ProtectedService : System.Web.Services.WebService { [WebMethod] public int GetRandom() { return new Random(DateTime.Now.Millisecond).Next(); } } 这个WebService很简单啦,就是简单的返回一个随机数, 这样,这个WebService,是可以随意的被访问的,我们对这个WebService作如下修改 public int GetRandom() { if (!HttpContext.Current.User.Identity.IsAuthenticated)//验证当前用户是否已经登陆 { throw new AuthenticationException("Error:please login first!");//若没有登陆,抛出一个异常 } return new Random(DateTime.Now.Millisecond).Next(); }
然后才创建aspx页面 前台代码: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="FormsAuth.aspx.cs" Inherits="Demo09_FormsAuth" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <title></title> <script language="javascript" type="text/javascript"> function getRandom() { ProtectedService.GetRandom(callback, failedCallback); } function callback(result) { alert(result); } function failedCallback(error) { alert(error.get_message()); } </script> </head> <body> <form id="form1" runat="server"> <asp:ScriptManager ID="ScriptManager1" runat="server"> <Services> <asp:ServiceReference Path="~/Demo09/ProtectedService.asmx" /> </Services> </asp:ScriptManager> <input type="button" value="Get Random" onclick="getRandom()" /> <hr /> <asp:Button ID="btnLogin" runat="server" Text="Login" onclick="btnLogin_Click" /> <asp:Button ID="btnLogout" runat="server" Text="Logout" onclick="btnLogout_Click" /> </form> </body> </html>
后台代码: using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.Security; public partial class Demo09_FormsAuth : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { } protected void btnLogin_Click(object sender, EventArgs e) { FormsAuthentication.SetAuthCookie("xiaoyaojian", false);//使用FormsAuthentication,登陆Username为xiaoyaojian的用户,false表示不使用持久化的Cookie } protected void btnLogout_Click(object sender, EventArgs e) { FormsAuthentication.SignOut();//注销用户 } } 这样,当我们直接点击Get Random按钮,则会出现一个Please login first,的错误提示,点击登陆后,再点击Get Random,正常出现一个随机数,再点击Logout,再去点击Get Random,则又会出现Please login first 我们使用了FormsAuthectication,只允许登陆用户正常调用我们创建的WebService,在一定程度上保护了WebService
Authentication Service它提供了一种使用AJAX的方式进行身份验证的功能,他是基于ASP.NET的Membership的功能,可以使用VS理工的ASP.NET 2.0应用程序的配置工具来配置 使用Authentication Service出于安全性的考虑,ASP.NET AJAX 在默认情况下不会开发Authentication Service功能 <authenticationService enabled="true|false" requireSSL="true|false" /> 这里的第二个属性,是指定是否使用SSL连接,这是一个安全的连接方式,常在一些高安全性的应用中使用
身份验证的功能//登陆 Sys.Service.AuthenticationService.login( userName,//用户名 password,//密码 isPersistent,//是否生成持久化Cookie customInfo,//预留字段 redirectUrl,//登陆成功后跳转目标 loginCompletedCallback,//身份验证完成回调函数(是完成,而不是成功) failedCallback,//身份验证出错回调函数(出错,而不是没有通过验证,比如超时) userContext//用户任意指定的上下文对象 );
//完成回调函数的签名 function loginCompletedCallback( validCredentials,//身份验证是否成功,所以要看验证是否成功,是在这里看,而不是看是不是调用了failedCallback userContext,//以后不写啦,浪费键盘 methodName,//Sys.Service.AuthenticationService.login ){…}
//出错回调函数签名 function failedCallback( error,//错误对象 userContext, methodName ){…}
//注销 Sys.Services.AuthenticationService.logout( redirectUrl,//注销后跳转页面 logoutCompletedCallback,//注销成功的回调函数 failedCallback,//注销失败回调函数 userContext );
//注销完成回调函数的签名 function loginCompletedCallback( result,//预留参数 userContext,// methodName,//Sys.Service.AuthenticationService.logout ){…}
//注销出错回调函数签名 function failedCallback( error,//错误对象 userContext, methodName ){…}
一个使用Authentication Service的示例首先,我们需要运行ASP.NET 配置来给应用添加一个用户 在VS里打开我们创建的网站,然后点击“网站”——“asp.net配置”,在弹出的网页中选择"安全"选项卡,然后点击“创建用户”,输入一些必要信息,点确定就可以了(这里我使用:用户名“xiaoyaojian”,密码“123123.”)
然后创建一个ASPX页面 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="AuthService.aspx.cs" Inherits="Demo09_AuthService" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> <title></title> <script language="javascript" type="text/javascript"> function getRandom() { ProtectedService.GetRandom(callback, failedCallback); } function callback(result) { alert(result); } function failedCallback(error) { alert(error.get_message()); } function login() { Sys.Services.AuthenticationService.login( document.getElementById("txtName").value, document.getElementById("txtPassword").value, false, null, null, loginCompleted, failedCallback, null); } function loginCompleted(validCridentials, userContext, methodName) { alert(validCridentials ? "Congratulations!" : "Failed to login to the system."); } function failedCallback(error) { alert(error.get_message()); } function logout() { Sys.Services.AuthenticationService.logout( null, logoutCompleted, failedCallback, null); } function logoutCompleted(result, userContext, methodName) { alert("You have logged out of the system"); } </script> </head> <body> <form id="form1" runat="server"> <asp:ScriptManager runat="server" ID="ScriptManager1"> <Services> <asp:ServiceReference Path="ProtectedService.asmx" /> </Services> </asp:ScriptManager> <div> <input type="button" onclick="getRandom()" value="Get Random" /> <hr /> Name: <input type="text" id="txtName" /><br /> Password: <input type="password" id="txtPassword" /><br /> <input type="button" onclick="login()" value="Login" /> <input type="button" onclick="logout()" value="Logout" /> </div> </form> </body> </html> 这个例子的用法是和我们上一个一样的,但是这里我们使用的是AJAX方式来验证
Authentication Service属性
Authentication Service实现Authentication Service的功能就是为我们提供一种以AJAX方式登陆和注销用户的功能,如果我们自己来实现,就会使用客户端调用WebService来实现这样的功能,而它给我们提供了更多的,比如跳转之类,实际上他的内部还是通过FormsAuthentication来实现的,他是对客户端执行服务器端方法给出一个特殊实现,调用了定义在程序集中的AuthenticationService类,最终工作的为Login(string,string.bol)和logout()两个方法
Authentication Service扩展扩展AuthenticationService的功能,就是要改变用户认证的方式,在ASP.NET中与用户认证相关的模型就有Membership,正常情况下,我们扩展Membership,就可以实现这个功能了,但是事实上,如果我们要扩展一个Membership,就需要实现多达27个成员, 那么我们就可以找到一个简便的方法 ,就是实现MembershipProvider的ValidateUser方法
一个扩展Membership的示例创建一个类文件,名为SampleMembershipProvider.cs using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; public class SampleMembershipProvider : MembershipProvider { public override string ApplicationName { get { return "Sample Membership Provider"; } set { } } public override bool ChangePassword(string username, string oldPassword, string newPassword) { throw new Exception("The method or operation is not implemented."); } public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer) { throw new Exception("The method or operation is not implemented."); } public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status) { throw new Exception("The method or operation is not implemented."); } public override bool DeleteUser(string username, bool deleteAllRelatedData) { throw new Exception("The method or operation is not implemented."); } public override bool EnablePasswordReset { get { throw new Exception("The method or operation is not implemented."); } } public override bool EnablePasswordRetrieval { get { throw new Exception("The method or operation is not implemented."); } } public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords) { throw new Exception("The method or operation is not implemented."); } public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords) { throw new Exception("The method or operation is not implemented."); } public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords) { throw new Exception("The method or operation is not implemented."); } public override int GetNumberOfUsersOnline() { throw new Exception("The method or operation is not implemented."); } public override string GetPassword(string username, string answer) { throw new Exception("The method or operation is not implemented."); } public override MembershipUser GetUser(string username, bool userIsOnline) { throw new Exception("The method or operation is not implemented."); } public override MembershipUser GetUser(object providerUserKey, bool userIsOnline) { throw new Exception("The method or operation is not implemented."); } public override string GetUserNameByEmail(string email) { throw new Exception("The method or operation is not implemented."); } public override int MaxInvalidPasswordAttempts { get { throw new Exception("The method or operation is not implemented."); } } public override int MinRequiredNonAlphanumericCharacters { get { throw new Exception("The method or operation is not implemented."); } } public override int MinRequiredPasswordLength { get { throw new Exception("The method or operation is not implemented."); } } public override int PasswordAttemptWindow { get { throw new Exception("The method or operation is not implemented."); } } public override MembershipPasswordFormat PasswordFormat { get { throw new Exception("The method or operation is not implemented."); } } public override string PasswordStrengthRegularExpression { get { throw new Exception("The method or operation is not implemented."); } } public override bool RequiresQuestionAndAnswer { get { throw new Exception("The method or operation is not implemented."); } } public override bool RequiresUniqueEmail { get { throw new Exception("The method or operation is not implemented."); } } public override string ResetPassword(string username, string answer) { throw new Exception("The method or operation is not implemented."); } public override bool UnlockUser(string userName) { throw new Exception("The method or operation is not implemented."); } public override void UpdateUser(MembershipUser user) { throw new Exception("The method or operation is not implemented."); } public override bool ValidateUser(string username, string password) { if (username == "xiaoyaojian" && password == "123123..") { return true; } return false; } } 我们继承了MembershipProvider,它是个抽象类,有好多方法要我们实现,实际上如果我们要简单实现,只需要重写他的ValidateUser类就可以了,所以我们只需要在那个方法里写如下代码 if (username == "xiaoyaojian" && password == "123123.") { return true; } return false; 定义好这个类以后,我们就需要在web.config中进行配置 在<system.web>节点下添加如下内容 <membership defaultProvider="SampleProvider"> <providers> <add name="SampleProvider" type="SampleMembershipProvider"/> </providers> </membership>
因为我们只实现了一个方法,所以就不要也不可以在配置中配置其他属性 再次打开上面的页面,回发现只有在Name为“xiaoyaojian” Password为“123123..”的情况下,验证才会通过,也就是说,系统现在调用的是我们定义的membershipprovider
如果扩展Authentication Service
那么,如果我们决定要这么做了,就需要写一个WebService,把它配置给ScriptManager,这个WebService主体结构如下 [System.Web.Script.Services.ScriptService] public class SessionAuthenticationService : System.Web.Services.WebService { [WebMethod] public bool Login(string userName, string password, bool createPersistentCookie) { } [WebMethod] public void Logout() { } } 注意:这里的参数列表包括参数名都必须与示例完全的相同
一个扩展Authentication Service示例创建一个名为SessionAuthenticationService.asmx的WebService using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Services; using System.Web.Security; /// <summary> ///SessionAuthenticationService 的摘要说明 /// </summary> [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] //若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。 [System.Web.Script.Services.ScriptService] public class SessionAuthenticationService : System.Web.Services.WebService { [WebMethod(EnableSession = true)] public bool Login(string userName, string password, bool createPersistentCookie) { if (Membership.Provider.ValidateUser(userName, password)) { HttpContext.Current.Session["User"] = true; return true; } else { return false; } } [WebMethod] public void Logout() { HttpContext.Current.Session.Remove("User"); } } 然后我们再次修改上面的页面, <%@ Page Language="C#" AutoEventWireup="true" CodeFile="AuthService.aspx.cs" Inherits="Demo09_AuthService" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head id="Head1" runat="server"> <title></title> <script language="javascript" type="text/javascript"> function getRandom() { ProtectedService.GetRandom(callback, failedCallback); } function callback(result) { alert(result); } function failedCallback(error) { alert(error.get_message()); } function login() { Sys.Services.AuthenticationService.login( document.getElementById("txtName").value, document.getElementById("txtPassword").value, false, null, null, loginCompleted, failedCallback, null); } function loginCompleted(validCridentials, userContext, methodName) { alert(validCridentials ? "Congratulations!" : "Failed to login to the system."); } function failedCallback(error) { alert(error.get_message()); } function logout() { Sys.Services.AuthenticationService.logout( null, logoutCompleted, failedCallback, null); } function logoutCompleted(result, userContext, methodName) { alert("You have logged out of the system"); } </script> </head> <body> <form id="form1" runat="server"> <asp:ScriptManager runat="server" ID="ScriptManager1"> <Services> <asp:ServiceReference Path="ProtectedService.asmx" /> </Services> <AuthenticationService Path="~/Demo09/SessionAuthenticationService.asmx" /> </asp:ScriptManager> <div> <input type="button" onclick="getRandom()" value="Get Random" /> <hr /> Name: <input type="text" id="txtName" /><br /> Password: <input type="password" id="txtPassword" /><br /> <input type="button" onclick="login()" value="Login" /> <input type="button" onclick="logout()" value="Logout" /> </div> </form> </body> </html> 输入用户名xiaoyaojian密码123123..,点击Login,弹出成功的提示,但是我们点击GetRandom,是不会出现随机数的,因为我们没有执行FormsAuthentication.setAuthCookie,这也正好证明了我们扩展的AuthenticationService正常工作啦 |
请发表评论