GVKun编程网logo

asp.net-web-api – 使用WIF和OWIN中间件的角色与声明授权Asp.net web api-2(中间件 netcore)

17

最近很多小伙伴都在问asp.net-web-api–使用WIF和OWIN中间件的角色与声明授权Asp.netwebapi-2和中间件netcore这两个问题,那么本篇文章就来给大家详细解答一下,同时本

最近很多小伙伴都在问asp.net-web-api – 使用WIF和OWIN中间件的角色与声明授权Asp.net web api-2中间件 netcore这两个问题,那么本篇文章就来给大家详细解答一下,同时本文还将给你拓展ASP.NET Web API与Owin OAuth:调用与用户相关的Web API、Asp.Net Web Api基于令牌的授权,没有OWIN和AspNet.Identity、asp.net web-api – ASP.net Web API RESTful Web服务基本身份验证、asp.net – Webapi,Webhost和Owin之间的关系等相关知识,下面开始了哦!

本文目录一览:

asp.net-web-api – 使用WIF和OWIN中间件的角色与声明授权Asp.net web api-2(中间件 netcore)

asp.net-web-api – 使用WIF和OWIN中间件的角色与声明授权Asp.net web api-2(中间件 netcore)

我正在尝试使用 Windows Identity Foundation 2来保护asp.net web-api 2.0.我必须做出的选择是基于角色的授权和基于声明的授权.作为一种做法,我在DbInitializer中添加了一个用户,并为他分配了两个角色(管理员和经理).当我登录与用户,我看到ClaimsPrincipal在调试模式下,它已经具备,索赔有关的角色(管理员和经理).所以这里是问题:

>如果角色也被视为声明,那么b / w角色和声明的区别是什么?
>如果我远离角色,我如何使用声明保护web api控制器和相关的操作方法.就像,我有一个包含CRUD方法的订单控制器.我希望一个用户(比如一个经理)可以访问Create and Get方法,而第二个用户(一个管理员)可以访问所有这些方法.

我该怎么办?使用基于角色的系统,我只需使用适当的Authorize(Role =“Admin”)属性来修饰操作方法.我如何管理索赔?我是否需要将它们添加到数据库中并通过我的应用程序向不同用户授予/撤销这些声明?

解决方法

原则上,角色和索赔之间没有太大的区别.我已经全神贯注于基于声明的授权,做了大量的研究和一些测试项目.在一天结束时,一切都归结于你决定使用哪一个.

如您所述,角色被添加为声明类型.因此,在交货方面,它没有任何区别.但是MVC / WebApi已经有内置的基础设施来处理角色,并且如果用户没有所需的角色则拒绝.所以你不必自己做很多事情.
但是你必须在控制器/操作上提出一些属性,并确保它们都存在于数据库中,因此可以将用户分配给它们.

但是我发现你可以拥有太多的角色,而且他们的维护成本太高了.此外,您不能为用户分配太多角色 – 他们的身份验证cookie将变得庞大,最终由于浏览器中的cookie大小限制而无法登录(每个cookie 4K,所有HTTP头16K).

声称您可以更灵活.您可以有许多不同类型的声明(我们每个控制器少于一个)和一些声明值(读取,创建,编辑,删除).对于下降大小的应用程序(我们有100以上),您将需要有很多角色(每个控制器4个)来建模这种级别的权限控制.对于声明,我们有声明类型(人物,产品,订单)的枚举和声明值的枚举(创建,读取,删除).在cookie中,您可以将整数设置为声明类型和声明值 – 这可以在身份验证cookie上节省大量空间.

但有了声明,您必须自己编写身份验证机制的代码.

我一直在玩这个概念here,这对于MVC来说是authentication filter,但是WebApi过滤器看起来非常相似.现在这个原型的结果正在生产中并且运行良好.

总的来说,你的问题的答案是“它取决于”.主要是关于身份验证的细化程度以及应用程序的大小.

ASP.NET Web API与Owin OAuth:调用与用户相关的Web API

ASP.NET Web API与Owin OAuth:调用与用户相关的Web API

在前一篇博文中,我们通过以 OAuth 的 Client Credential Grant 授权方式(只验证调用客户端,不验证登录用户)拿到的 Access Token ,成功调用了与用户无关的 Web API。

在这篇博文中,我们将以 OAuth 的 Resource Owner Password Credentials Grant 的授权方式( grant_type=password )获取 Access Token,并以这个 Token 调用与用户相关的 Web API。

对应的应用场景是:为自家的网站开发手机 App(非第三方 App),只需用户在 App 上登录,无需用户对 App 所能访问的数据进行授权。

根据 OAuth 规范,客户端获取 Access Token 的请求方式如下:

复制代码
POST /token HTTP/1.1
Host: server.example.com
Authorization: Basic czZCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded

grant_type=password&username=johndoe&password=A3ddj3w
复制代码

根据上面的请求方式,在 C# 中用 HttpClient 实现一个简单的客户端,代码如下:

复制代码
public class OAuthClientTest
{ private HttpClient _httpClient; public OAuthClientTest()
    {
        _httpClient = new HttpClient();
        _httpClient.BaseAddress = new Uri("http://openapi.cnblogs.com");
    } 

    [Fact] public async Task Get_Accesss_Token_By_Resource_Owner_Password_Credentials_Grant()
    {
        Console.WriteLine(await GetAccessToken());
    } private async Task<string> GetAccessToken()
    { var clientId = "1234"; var clientSecret = "5678"; var parameters = new Dictionary<string, string>();            
        parameters.Add("grant_type", "password");
        parameters.Add("username", "博客园团队");
        parameters.Add("password", "cnblogs.com");

        _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue( "Basic",
            Convert.ToBase64String(Encoding.ASCII.GetBytes(clientId + ":" + clientSecret))
            ); var response = await _httpClient.PostAsync("/token", new FormUrlEncodedContent(parameters)); var responseValue = await response.Content.ReadAsStringAsync(); if (response.StatusCode == System.Net.HttpStatusCode.OK)
        { return JObject.Parse(responseValue)["access_token"].Value<string>();
        } else {
            Console.WriteLine(responseValue); return string.Empty;
        }
    }
}
复制代码

(注:与之前相比,这里的 client_id/client_secret 改为了 Basic Authorization,以更好的遵循 OAuth 规范)

在服务端,基于 Owin OAuth, 针对 Resource Owner Password Credentials Grant 的授权方式,只需重载 OAuthAuthorizationServerProvider.GrantResourceOwnerCredentials() 方法即可。代码如下:

复制代码
public class CNBlogsAuthorizationServerProvider : OAuthAuthorizationServerProvider
{ //... public override async Task GrantResourceOwnerCredentials(
        OAuthGrantResourceOwnerCredentialsContext context)
    { //调用后台的登录服务验证用户名与密码 var oAuthIdentity = new ClaimsIdentity(context.Options.AuthenticationType);
        oAuthIdentity.AddClaim(new Claim(ClaimTypes.Name, context.UserName)); var ticket = new AuthenticationTicket(oAuthIdentity, new AuthenticationProperties());
        context.Validated(ticket); await base.GrantResourceOwnerCredentials(context);
    }
}
复制代码

完整的CNBlogsAuthorizationServerProvider实现代码如下(与之前相比,context.TryGetFormCredentials 改为了 context.TryGetBasicCredentials):

复制代码
public class CNBlogsAuthorizationServerProvider : OAuthAuthorizationServerProvider
{ public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
    { string clientId; string clientSecret;
        context.TryGetBasicCredentials(out clientId, out clientSecret); if (clientId == "1234" && clientSecret == "5678")
        {
            context.Validated(clientId);
        } await base.ValidateClientAuthentication(context);
    } public override async Task GrantClientCredentials(OAuthGrantClientCredentialsContext context)
    { var oAuthIdentity = new ClaimsIdentity(context.Options.AuthenticationType); var ticket = new AuthenticationTicket(oAuthIdentity, new AuthenticationProperties());
        context.Validated(ticket); await base.GrantClientCredentials(context);
    } public override async Task GrantResourceOwnerCredentials(
        OAuthGrantResourceOwnerCredentialsContext context)
    { //调用后台的登录服务验证用户名与密码 var oAuthIdentity = new ClaimsIdentity(context.Options.AuthenticationType);
        oAuthIdentity.AddClaim(new Claim(ClaimTypes.Name, context.UserName)); var ticket = new AuthenticationTicket(oAuthIdentity, new AuthenticationProperties());
        context.Validated(ticket); await base.GrantResourceOwnerCredentials(context);
    }
}
复制代码

这样,运行客户端程序就可以拿到 Access Token 了。

接下来,我们拿着以这种方式获取的 Access Token,就可以调用与用户相关的 Web API 了。

在服务端我们通过一个简单的 Web API 测试一下,代码如下:

复制代码
public class UsersController : ApiController
{
    [Authorize] public string GetCurrent()
    { return User.Identity.Name; //这里可以调用后台用户服务,获取用户相关数所,或者验证用户权限进行相应的操作  }
}
复制代码

然后,客户端用以 grant_type=password 方式拿到的 Access Token 调用这个Web API,客户端增加的代码如下:

复制代码
[Fact] public async Task Call_WebAPI_By_Resource_Owner_Password_Credentials_Grant()
{ var token = await GetAccessToken();
    _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
    Console.WriteLine(await (await _httpClient.GetAsync("/api/users/current")).Content.ReadAsStringAsync());
}
复制代码

客户端运行结果如下:

"博客园团队"

调用成功!运行结果正是获取 Access Token 时所用的 username 。 

结合 ASP.NET 现有的安全机制,借助 OWIN 的威力,Microsoft.Owin.Security.OAuth 的确让开发基于 OAuth 的 Web API 变得更简单。

Asp.Net Web Api基于令牌的授权,没有OWIN和AspNet.Identity

Asp.Net Web Api基于令牌的授权,没有OWIN和AspNet.Identity

我打算使用下面的代码来实现我的web api安全性,但我不确定这是否足够安全和​​合理.我不想使用OWIN和AspNet.Identity,因为它对我来说非常复杂,我不完全理解,我不知道我如何定制数据库表,用户角色等.但我的方式很简单,非常可定制我.

这是CustomAuthorizeAttribute;

public class CustomAuthorize : AuthorizeAttribute
{
    public override void OnAuthorization(HttpActionContext actionContext)
    {
        if ((actionContext.Request.Headers.GetValues("Host").FirstOrDefault().Contains("localhost:15742")))
        {
            IEnumerable<string> access_token;
            if (actionContext.Request.Headers.TryGetValues("Authorization",out access_token))
            {
                var user = GetUserByToken(access_token);
                if (user!=null && !user.TokenIsExpired)
                {
                    HttpContext.Current.response.addheader("WWW-Authenticate","Custom " + access_token.FirstOrDefault());
                    return;
                }
                else
                {
                    actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
                    HttpContext.Current.response.addheader("WWW-Authenticate","Custom");
                    return;
                }
            }
            else
            {
                actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
            }
        }
        else
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Forbidden);
        }
    }
}

这是前端使用

<script type="text/javascript">
    $(function () {
        var access_token = $.cookie('access_token');
        if (access_token == undefined) {
            $.cookie('access_token','test-token');
        }


        $.ajax({
            url: '/api/account',headers: { access_token: access_token },success: function (data) {
                document.write(data.name + " " + data.lastname);
            }
        });
    });
</script>

顺便说一句,我为我的英语感到抱歉.我希望你理解我的问题,我在等你的建议.

解决方法

Necroreply为那些想要制作自定义身份验证属性的人:)

首先检查是多余的,因为HTTP请求只是TCP连接上的一串文本,因此任何人都可以使用TCP客户端连接到您的服务器并发送他想要的任何标头.
actionContext.Request.Headers.GetValues( “主机”)FirstOrDefault()包含.( “本地主机:15742”))

根据https://docs.microsoft.com/en-us/aspnet/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api

Authorization filters run before the controller action. If the request is not authorized,the filter returns an error response,and the action is not invoked.

属性的唯一方法是不设置响应是用户!= null&& !user.TokenIsExpired所以这个属性可以完成工作,可以认为是安全的.

这个头可以删除HttpContext.Current.response.addheader(“WWW-Authenticate”,“Custom”);

另外,为什么你会在成功的情况下再次发送身份验证令牌? HttpContext.Current.response.addheader(“WWW-Authenticate”,“Custom”access_token.FirstOrDefault());

只需减少IF-s嵌套级别,以便代码更易于阅读:

public override void OnAuthorization(HttpActionContext actionContext)
    {
        IEnumerable<string> access_token;

        if (!actionContext.Request.Headers.TryGetValues("Authorization",out access_token))
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
            return;
        }

        var user = GetUserByToken(access_token);

        if (user == null || user.TokenIsExpired)
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);                
            return;
        }

        // OK
        return;
    }

许多ASP.NET代码似乎过度设计(有时是:)包括OWIN.但它有一个目的 – 声明一种标准的方式来做各种各样的事情,例如auth.

想象一下,每个人都会开始构建他们的自定义attrbiutes,然后就不可能只安装Google nuget包并做类似的事情

public void ConfigureAuth(IAppBuilder app)
{
     app.UseGoogleAuthentication(
         clientId: "000-000.apps.googleusercontent.com",clientSecret: "00000000000");
}

asp.net web-api – ASP.net Web API RESTful Web服务基本身份验证

asp.net web-api – ASP.net Web API RESTful Web服务基本身份验证

我正在使用ASP.Net Web Api实现RESTful Web服务。我已经得出结论使用基本认证SSL做认证部分。什么是最好/正确的方法来实现呢?

我的第一个尝试是手动,解析授权头,解码和验证用户对我的数据库。它的工作,但我不知道,如果我缺少的东西。

我见过一些使用用户角色和原则的解决方案。虽然我不知道这些实际做什么,我几乎肯定我不会需要这些,因为在我的数据库中,我定义了我自己的用户和他们的角色。

还有我还没有完全理解,是如果服务的消费者必须发送凭证与每个请求或他们以某种方式缓存。我的服务应该做些什么才能发生,还是完全由消费者来处理?

最后一个问题关于客户使用javascript请求。如果他们尝试使用该服务,是否会出现任何“跨域请求”问题?

解决方法

Jamie Kurtze提供了使用基本身份验证在这里 ASP.NET Web API REST Security Basics的一个很好的解释

从我的理解,如果你想要你的请求是无状态的,那么每个请求将需要设置验证字段

Jamie Kurtze在从DelegateHandler派生的类中包装必要的代码,而Rick Strahl使用过滤器检查调用是否有效。你可以在他的博客文章阅读更多在这个主题在A WebAPI Basic Authentication Authorization Filter

asp.net – Webapi,Webhost和Owin之间的关系

asp.net – Webapi,Webhost和Owin之间的关系

我只是想围绕webapi,webhost(iis)和owin之间的关系.我会写下我目前的理解,请你告诉我是否正确.

> Webapi与MVC不同,是以独立于主机的方式编写的.这是在欧文之前,但显然他们预计欧文会迟早会发生.主机独立性主要表示在Webapi代码中的任何地方都不使用System.Web.这是System.Web,它完全依赖IIS,如果没有它就不行.这样一来,Webapi可以理论上托管在任何地方 – 一旦其他主机可用.
> Webhost(Microsoft.Owin.Host.SystemWeb,Microsoft.AspNet.WebApi.WebHost)是一个层次之间的较高级别的API(如Webapi)和IIS.由于Webapi最初是独立于主机,因此需要一个中间层来使其在特定主机(如IIS)上运行. Webapi for Webapi(Microsoft.AspNet.WebApi.WebHost)提供了这个层.后来还将有针对Owin(Microsoft.Owin.Host.SystemWeb)的Webhost层,这将允许托管IIS上的任何Owin兼容.
欧文来了最后.它基本上提供了一个抽象,理论上可以允许在任何主机上托管任何Owin兼容的应用程序,只要在owin和该主机之间有一层. Owin带有Webhost(Microsoft.Owin.Host.SystemWeb)(类似于Webapi与Webhost一起使用),允许O IIS应用程序在IIS上托管.它还带有自主(Microsoft.Owin.SelfHost),允许Owin应用程序托管在任何可执行文件中.就Webapi而言,Owin还与Oapi主机一起使用Webapi(Microsoft.AspNet.WebApi.Owin),它允许在Owin堆栈上运行WebApi.

以上所有这一切意味着在IIS上托管Webapi有两种不同的方式.使用Webapi WebHost可以在没有Owin的情况下完成,也可以使用Oapi Host for Webapi和使用Webhost for Owin来完成.

Nuget参考文献

> Microsoft.Owin.SelfHost
> Microsoft.Owin.Host.SystemWeb
> Microsoft.AspNet.WebApi.WebHost
> Microsoft.AspNet.WebApi.Owin

这个理解正确吗?

解决方法

你的理解一般是正确的,但是OWIN的作用似乎被误解了.更完整的时间表将是:

> OWIN Standard开发描述通用.NET Web界面,一个Wsgi / Rake / Connect(first commit in 2010).
ASP.NET WebAPI是与主机无关开发的,但随着https://www.nuget.org/packages/Microsoft.AspNet.WebApi.WebHost/发布.
> Katana Project实现了几个OWIN主机:

> https://www.nuget.org/packages/Microsoft.Owin.SelfHost/
> https://www.nuget.org/packages/Microsoft.Owin.Host.HttpListener/
> https://www.nuget.org/packages/Microsoft.Owin.Host.IIS/
> https://www.nuget.org/packages/Microsoft.Owin.Host.SystemWeb/

> OWIN的ASP.NET WebAPI适配器发布:https://www.nuget.org/packages/Microsoft.AspNet.WebApi.Owin.

您的摘要:

All the above means that one has two different ways of hosting Webapi on IIS. It can be done without Owin,using Webapi WebHost,or it can be done with Owin Host for Webapi and with Webhost for Owin.

我会重申:

所有这些都意味着有两种不同的托管WebAPI的方式.可以在没有Owin的情况下使用WebAPI WebHost,或者可以使用OWIN adapter for WebAPI和任何OWIN兼容的主机完成. IIS上的托管选项为Microsoft.Owin.Host.IIS和Microsoft.Owin.Host.SystemWeb.还提供了Microsoft.AspNet.WebApi.OwinSelfHost.

关于asp.net-web-api – 使用WIF和OWIN中间件的角色与声明授权Asp.net web api-2中间件 netcore的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于ASP.NET Web API与Owin OAuth:调用与用户相关的Web API、Asp.Net Web Api基于令牌的授权,没有OWIN和AspNet.Identity、asp.net web-api – ASP.net Web API RESTful Web服务基本身份验证、asp.net – Webapi,Webhost和Owin之间的关系等相关知识的信息别忘了在本站进行查找喔。

本文标签: