Asp.net Webservice - 使用 jquery AJAX 安全调用 Web 服务

Posted

技术标签:

【中文标题】Asp.net Webservice - 使用 jquery AJAX 安全调用 Web 服务【英文标题】:Asp.net Webservice - Secure call the webservice with jquery AJAX 【发布时间】:2013-07-04 21:53:02 【问题描述】:

我想将 Web 服务与 Ajax 一起使用。使用 ajax 调用 web 服务时,安全性的最佳方法是什么?我想防止远程调用应用程序。

我有以下 webservice 例如:

[WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    [System.Web.Script.Services.ScriptService]
    public class Users : System.Web.Services.WebService
    

        [WebMethod]
        public List<User> GetUsers()
        
            List<User> listUsers = new List<User>();
            User user = new User();
            user.Id = 1;
            user.Name = "John";

            User user2 = new User();
            user2.Id = 2;
            user2.Name = "Martin";


            listUsers.Add(user);
            listUsers.Add(user2);

            return listUsers;
         
    

我用 jquery ajax 调用 web 服务:

<script type="text/javascript">
    $(function () 

        getUsers();


        function getUsers() 

            $.ajax(
                type: "POST",

                url: "Webservices/Users.asmx/GetUsers",

                data: "",

                contentType: "application/json; charset=utf-8",

                dataType: "json",

                success: function (response) 

                    var users = response.d;

                    $.each(users, function (index, user) 

                        console.log(user.Name);

                    );

                ,

                failure: function (msg) 
                
            );
        
    );
</script>

【问题讨论】:

调用 Web 服务的应用程序是什么? ASP.NET Web 窗体,MVC? .asmx 是同一个应用程序的一部分吗?调用 .asmx 的 Web 应用程序如何保护?您是否为此使用表单身份验证? @Badri - 感谢您的提问。我使用 ASP.NET Web 窗体。 asmx 在同一个应用程序中。我做一个聊天应用程序,我想使用网络服务来保存消息和检索新消息。我想做安全的网络服务来在聊天中发送消息。聊天只能使用注册用户。对于身份验证,我想使用表单身份验证。 【参考方案1】:

没有最好的方法,答案总是it depends,尽管它非常无用。例如,您可以使用forms authentication。如果您使用 Web 服务的 Web 应用程序和 Web 服务是同一 ASP.NET application 的一部分,则浏览器可以为每次调用 Web 服务时无缝地发送表单身份验证票证 (cookie)。

在配置文件中可以有

<authorization>
        <deny users="?" />
</authorization>

这将拒绝匿名用户的访问,这也将涵盖网络服务。换句话说,除非用户登录并使用票证获得有效的 cookie,否则无法使用服务。当然,你必须HTTPS。否则,中间的任何人都可以获取标头中的 cookie 并调用您的服务。

最后,绝对不能确保没有人在您的应用程序之外调用 Web 服务。上述方法确保中间没有人调用您的服务。但是没有办法确保有效的用户直接在您的应用程序之外调用服务,因为 Web 服务调用者是 JavaScript,并且您在 JavaScript 中构建的任何安全性都可以通过查看脚本甚至查看浏览器之间的流量。任何有点技术的最终用户都可以重放请求或修改请求并使用有效凭据提交到您的 Web 服务。

编辑:-

以下是启用 FormsAuthentication 所需的更多详细信息。

(1) 在Web.config&lt;system.web&gt; 下,确保你有这个。

<authentication mode="Forms">
     <forms loginUrl="Login.aspx" defaultUrl="~/" />
</authentication>
<authorization>
     <deny users="?" />
</authorization>

这将确保所有未经身份验证(匿名)的用户都被重定向到 Login.aspx。

(2) 使用您的登录逻辑实现Login.aspx 以获取用户ID 和密码,并根据数据库或其他方式验证它们。一旦身份验证成功,即用户输入的 ID 和密码与您在数据库中的匹配,可能在登录按钮单击处理程序中,设置票证。

protected void Button1_Click(object sender, EventArgs e)

    // Do all your login logic here
    // once user ID and password entered by the user are okay, call this

    string ticket = FormsAuthentication.Encrypt(
                        new FormsAuthenticationTicket("userId", false, 15));
    HttpCookie FormsCookie = new HttpCookie(
               FormsAuthentication.FormsCookieName, ticket)  HttpOnly = true ;
    HttpContext.Current.Response.Cookies.Add(FormsCookie);

(3) 像这样将PrincipalPermissionAttribute 添加到web 方法中。

public class Users : System.Web.Services.WebService

    [PrincipalPermissionAttribute(SecurityAction.Demand)]
    [WebMethod]
    public List<User> GetUsers()
    
        // Same code as what you have now
    

如果您现在转到任何页面,您将被重定向到 login.aspx,您需要在其中输入用户 ID 和密码并登录。登录时,将创建表单身份验证 cookie 并将其写入响应。从那时起,对您的应用程序的所有请求都将带入 cookie(浏览器将为您执行此操作)。在不登录的情况下,如果您直接访问 Web 服务,您仍然会被重定向到登录页面。正如我在原始答案中提到的那样,登录用户仍然可以直接访问 Web 服务。如果 JavaScript 可以做某事,那么用户也可以做同样的事情。

顺便说一句,Web 服务 (asmx) 是一种已弃用的技术。

【讨论】:

现在用什么类型代替asmx? 非常感谢您的精彩提醒 - “Web 服务 (asmx) 是一种已弃用的技术”。我使用 WCF 服务。您可以编辑您对使用 wcf 服务的回答吗?谢谢。 我的回答对于 WCF 也是一样的。对于pt。 #3,不要在web方法上应用[PrincipalPermissionAttribute(SecurityAction.Demand)],而是在实现WCF服务契约的类的方法中应用同样的方法。如果您计划使用 ASP.NET Web API(用于构建 HTTP 服务的 f/w)而不是 WCF,那么同样的方法也可以工作。 Web API 提供了一个Authorize 属性,您可以使用它来代替PrincipalPermission,但基本上,它都是关于以声明方式检查是否存在与当前主体关联的经过身份验证的身份。【参考方案2】:

这是一个非常重要的讨论话题。 有很多方法可以做到这一点。

我们个人将服务堆栈用于 API,并在访问 API 时使用密钥。 密钥是客户端和服务器保持相同的 guid。 如果客户端和服务器是同一个系统,那么发布密钥不会有任何问题。

这里给出了一个非常详细的安全方法 http://www.stormpath.com/blog/secure-your-rest-api-right-way http://codebetter.com/johnvpetersen/2012/04/02/making-your-asp-net-web-apis-secure/

还有进一步的例子 Building Secure Public API with php/mysql

【讨论】:

【参考方案3】:

您可以做的一件事是在构建页面时将一次性令牌放入您的页面,然后在您的 AJAX 调用期间发布该令牌,以帮助防止浏览器外部调用。一个简单的实现是一个带有一堆随机值(可能是 32 个字母数字或类似的)的数据库表。当您构建页面时,从表中检索一个值并将其放入您的页面 - 当您发布 AJAX 表单时,请包含该值。

在服务器端,确保值存在于表中,然后将其从表中删除。

如果使用该值再次调用该服务,它将失败,因为该值不再在表中。

这意味着为了生成一个有效的token,你必须先获取页面,然后你只能使用那个token一次。

您可以在其中添加额外的检查,例如 IP 地址、用户代理、cookie 值、到期日期等,并执行诸如使用密钥散列值或其他隐蔽安全方法之类的操作。

最后,正如巴德里指出的那样,如果有人真的想要通过简单地手动创建浏览器将为 AJAX 调用发出的 HTTP 请求,所有这些都可以被欺骗。您能做的最好的事情是确保只有有效的用户才能调用服务(无论他们使用何种客户端技术),这通过传统的表单身份验证来完成。

【讨论】:

以上是关于Asp.net Webservice - 使用 jquery AJAX 安全调用 Web 服务的主要内容,如果未能解决你的问题,请参考以下文章

Asp.net Webservice - 使用 jquery AJAX 安全调用 Web 服务

在 asp.net 中阻止对 WebService.asmx 的访问

asp.net WebService的一个简单示例

如何使用 Asp.net 设置 .asmx webservice 启用跨域

asp.net webservice cookie 保存后NAME有值,Value却没有值 代码如下:

使用 jquery 从 asp.net webservice 解析简单的 xml