MVC 4 应用,EF 和 Web API 结构以及用户身份验证

3
我使用以下技术开发网站:
MVC 4 EF 5 Web API 未来可能会开发Windows Phone/Windows 8应用。
我使用Web API,这样我就可以在其他客户端上使用已开发的API。
但是,每次向API发送请求时,我需要对用户进行授权。我的最初想法是通过HTTP标头来完成此操作。然而,我想知道是否应该只使用MVC控制器代替Web API用于MVC应用程序,并且如果我要开发电话/Win 8应用程序,则创建一个RESTful API,再次需要对用户进行身份验证。所以最初的问题仍然存在。
大家有什么想法吗?是否可以指点我如何通过HTTP标头安全地传递经过身份验证的用户详细信息,还需要一个逐步教程,因为我从零开始学习并需要理解它。

这是你正在寻找的内容吗? https://dev59.com/CGgu5IYBdhLWcg3w3qx7 - user1797792
1个回答

1

我使用基本身份验证来传递凭据进行授权。这将把凭据放在头部中。通过使用JQuery ajax函数的beforeSend事件处理程序,这样做非常简单。以下是如何执行此操作的示例。

    getAuthorizationHeader = function (username, password) {
      var authType;
      var up = $.base64.encode(username + ":" + password);
      authType = "Basic " + up;
    };
    return authType;
 };

    $.ajax({
        url: _url,
        data: _data,
        type: _type,
        beforeSend: function (xhr) {
            xhr.setRequestHeader("Authorization", getAuthorizationHeader(username, password));
        },
        success: ajaxSuccessHandler,
        error: ajaxErrHandler
    });

这个编码了在头部发送的用户名/密码。请注意,仅仅使用编码是不够安全的,因为它很容易被解码。您仍然需要使用HTTPS/SSL来确保通过网络发送的信息是安全的。

在Web API方面,您可以创建一个自定义的AuthorizeAttribute,从头部获取凭据,对其进行解码,并执行授权过程。与控制器不同,Web API使用单独的AuthorizeAttribute。在创建自定义AuthorizeAttribute时,请确保使用System.Web.Http.AuthorizeAttribute作为基类。它们有不同的行为。控制器的AuthorizeAttribute将要重定向到登录页面,而Web API的AuthorizeAttribute则返回表示成功或失败的HTTP代码。如果授权失败,则我会返回HTTP代码Forbidden,以区分由于授权而不是身份验证导致的失败,以便客户端可以相应地做出反应。

以下是一个示例方法,用于从头部获取凭据,可用于自定义AuthorizeAttribute

    private bool GetUserNameAndPassword(HttpActionContext actionContext, out string username, out string password)
    {
        bool gotIt = false;
        username = string.Empty;
        password = string.Empty;
        IEnumerable<string> headerVals;
        if (actionContext.Request.Headers.TryGetValues("Authorization", out headerVals))
        {
            try
            {
                string authHeader = headerVals.FirstOrDefault();
                char[] delims = { ' ' };
                string[] authHeaderTokens = authHeader.Split(new char[] { ' ' });
                if (authHeaderTokens[0].Contains("Basic"))
                {
                    string decodedStr = SecurityHelper.DecodeFrom64(authHeaderTokens[1]);
                    string[] unpw = decodedStr.Split(new char[] { ':' });
                    username = unpw[0];
                    password = unpw[1];
                }
                gotIt = true;
            }
            catch { gotIt = false; }
        }

        return gotIt;
    }

这里是用于解码此方法中使用的头数据的代码。

    public static string DecodeFrom64(string encodedData)
    {

        byte[] encodedDataAsBytes

            = System.Convert.FromBase64String(encodedData);

        string returnValue =

           System.Text.Encoding.ASCII.GetString(encodedDataAsBytes);

        return returnValue;

    }

一旦您拥有用户名和密码,您可以执行授权过程并返回适当的HTTP代码以供客户端处理。

更新于2013年3月8日

我写了一篇博客文章,详细介绍了如何使用SimpleMembership(MVC 4互联网应用程序的默认成员资格提供程序)实现此功能。它还包括一个可下载的VS 2012项目来实现这一点。


谢谢您,如果我想要在每次服务器调用时检查用户是否已经通过身份验证,但他们不会每次都提供密码怎么办? - dotnethaggis
如果客户端支持cookies,您可以使用它们。当您验证用户时,请设置cookie。然后在身份验证/授权逻辑中,如果标头中没有凭据,则可以尝试使用cookie进行身份验证。有关在SimpleMembership提供程序中使用此功能的更多详细信息,请参见此处[http://kevin-junghans.blogspot.com/2013/02/mixing-forms-authentication-basic.html]。 - Kevin Junghans
非常棒 - 非常感谢Kevin。我会在适当的时候阅读这篇文章。 - dotnethaggis
评论中的链接似乎有问题(末尾多了一个“]”字符),我无法编辑它。我已经更新了答案,在末尾包含了链接。 - Kevin Junghans

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接