Mvc Api 从请求获取凭据

问题描述 投票:0回答:1

我花了很长时间才找到这方面的东西,尽管我认为它非常简单......

我正在使用 .NET MVC 4.5 开发 API。我希望最终用户能够发送类似(PowerShell)的请求:

$webclient = new-object System.Net.WebClient
$webclient.Credentials = new-object System.Net.NetworkCredential($username, 
$securePassword)
$doc = $webclient.DownloadString("http://localhost:60023/api/getData?id=200")

但我不知道如何从我的应用程序中的请求中提取凭据。

我的控制器看起来像:

namespace App.Controllers
{
    public IEnumerable<MyStruct> Get(int id)
    {
        // TODO: get credentials from request

        // validate credentials
        // code to create IEnumerable<MyStruct>
        return DataList;
    }
}

到目前为止,如果我对凭据进行硬编码,一切都会正常,我需要弄清楚的是如何从最终用户的

$webclient.Credentials
获取凭据。

我确定以前已经讨论过这个问题,但我已经搜索了几个小时但找不到答案。

我还差吗?

这不是验证 API 请求的好方法吗?我知道有一个 [Authorize] 属性可以使用内置身份验证系统,但我的应用程序使用自定义登录验证,所以我认为这不起作用。是否有理由以我想要的方式在控制器方法中验证凭据是一个坏主意?

c# .net asp.net-mvc
1个回答
5
投票

通常

MVC
不用于 API 工作。虽然
MVC
可以处理服务 API 调用,但 Microsoft 有一个类似
MVC
的产品,称为
WebApi
,它更适合为 API 提供服务,例如返回 JSON 或 XML 而不是视图。

MVC
WebApi
中,不建议在方法内处理身份验证和授权。虽然它有效,但它会让您忘记保护 API 调用的安全。 因此微软制作了
AuthenticationFilter
AuthorizationFilter
属性。这些允许您通过方法、类或应用程序来标记要保护哪些 API 或视图。

要从

MVC
中的请求访问基本凭据,您将访问授权标头。这将是一个
Basic [Base64Encoded, colon delimited strings]
形式的字符串。

以下代码显示了如何读取凭据的粗略示例:

public ActionResult TestView()
{
    bool isAuthenticated;
    var base64Header = Request.Headers["Authorization"];
    //The header is a string in the form of "Basic [base64 encoded username:password]"
    if (base64Header != null)
    {
        var authHeader = AuthenticationHeaderValue.Parse(base64Header);
        if (authHeader != null
            && authHeader.Scheme.Equals("basic", StringComparison.OrdinalIgnoreCase)
            && authHeader.Parameter != null)
        {
            //Decode the username:password pair
            var credentialPair = Encoding.ASCII.GetString(Convert.FromBase64string(authHeader.Parameter));

            //Split into pieces
            var credentials = credentialPair.Split(new [] {":"}, StringSplitOptions.None);
            var userName = credentials[0];
            var plainTextPassword = credentials[1];
            isAuthenticated = SomeAuthenticator.Authenticate(userName, password);
        }
    }
    if (isAuthenticated)
       return Foo();
    else
       RedirectResult("your login view");
}

但是最好将此代码插入到

AuthenticationFilter
中。这使您能够通过方法、类或应用程序打开/关闭授权。

public class CustomAuthFilter : IAuthenticationFilter
{
    public void OnAuthentication(AuthenticationContext filterContext)
    {
        var header = filterContext.RequestContext.HttpContext.Request.Headers["Authorization"];
        if (!Authenticate(header))
            filterContext.Result = new HttpUnauthorizedResult();
    }

    public void OnAuthenticationChallenge(AuthenticationChallengeContext filterContext)
    {
       filterContext.Result = new RedirectResult(@"https:\\foo\YourLoginPage");
    }

    private bool Authenticate(string rawAuthorizationHeader)
    {
        try
        {
            if (rawAuthorizationHeader != null)
            {
                var authHeader = AuthenticationHeaderValue.Parse(rawAuthorizationHeader);
                if (authHeader != null
                    && authHeader.Scheme.Equals("basic", StringComparison.OrdinalIgnoreCase)
                    && authHeader.Parameter != null)
                {
                    var credentialPair = Encoding.ASCII.GetString(Convert.FromBase64String(authHeader.Parameter));
                    var credentials = credentialPair.Split(new[] { ":" }, StringSplitOptions.None);
                    var userName = credentials[0];
                    var plainTextPassword = credentials[1];
                    return SomeAuthenticator.Authenticate(userName, plainTextPassword);
                }
            }

            return false;
        }
        catch (Exception)
        {
            return false;
        }
    }
}

然后被

消耗
[CustomAuthFilter] //Secure all methods in the class
public class SecureApiController
{

    public ActionResult SecuredApiCall()
    {
        return Foo();
    }

    public ActionResult AnotherSecuredCall()
    {
        return Bar();
    }

    [AllowAnonymous]
    public ActionResult UnsecuredApiCall()
    {
        return UnsecureFoo();
    }
}

请注意,在典型的 Microsoft 方式中,身份验证授权是两个不同的东西。如果您想通过“此用户有一个帐户”以外的方式来保护 API,您将需要设置授权过滤器。

© www.soinside.com 2019 - 2024. All rights reserved.