博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于 IdentityServer3 实现 OAuth 2.0 授权服务【客户端模式(Client Credentials Grant)】
阅读量:5994 次
发布时间:2019-06-20

本文共 8027 字,大约阅读时间需要 26 分钟。

github:

documentation:
samples

OAuth 2.0定义的四种授权方式。

  • 授权码模式(authorization code)
  • 简化模式(implicit)
  • 密码模式(resource owner password credentials)
  • 客户端模式(client credentials)

虽然已经基于 实现了 OAuth 2.0 的相关模式,后面发现 IdentityServer 要相对完善一些,IdentityServer 是属于 的一个子项目,IdentityServer3 是基于 开发的 OpenID Connect/OAuth 2.0 服务框架,虽然 Katana 微软已经不维护了,现已经属于 ASP.NET Core 的一部分,相应对应 ASP.NET Core 的版本是 ,还处于 Beta 版本;不过 IdentityServer3 的扩展 支持 ASP.NET Core , 个人觉得 ASP.NET Core 设计很好,但是现在还不成熟,可能还需要等一段时间,所以选择了 IdentityServer3 。

授权角色

资源拥有者(resource owner):能授权访问受保护资源的一个实体,如新浪微博用户 irving;

资源服务器(resource server):存储受保护资源,客户端通过 access token 请求资源,资源服务器响应受保护资源给客户端;存储着用户 irving 的微博等信息。

授权服务器(authorization server):成功验证资源拥有者并获取授权之后,授权服务器颁发授权令牌(Access Token)给客户端。

客户端(client:如新浪微博第三方应用,也可以是它自己的官方应用;其本身不存储资源,而是资源拥有者授权通过后,使用它的授权(授权令牌)访问受保护资源,然后客户端把相应的数据展示出来。“客户端”术语不代表任何特定实现(如应用运行在一台服务器、桌面、手机或其他设备)。

Client Credentials Grant 模式只需要关注 授权服务器,资源服务器,客户端三个角色  具体:

授权服务器

Install-Package IdentityServer3

服务配置

public class Startup    {        ///         /// 配置idsv授权服务        ///         ///         public void Configuration(IAppBuilder app)        {            var opts = new IdentityServerOptions            {                SiteName = "Embedded OAuth2 Service",                EnableWelcomePage = true,                Factory = new IdentityServerServiceFactory()                              .UseInMemoryClients(Clients.Get())                              .UseInMemoryScopes(Scopes.Get())                              .UseInMemoryUsers(new List
()), //.UseInMemoryUsers(Users.Get()) RequireSsl = false, //SigningCertificate = new X509Certificate2(string.Format(@"{0}\bin\identityServer\idsrv3test.pfx", AppDomain.CurrentDomain.BaseDirectory), "idsrv3test") }; app.UseIdentityServer(opts); /* //自定义路由 app.Map("/identity", idsrvApp => { idsrvApp.UseIdentityServer(opts); }); */ } }

客户端

public class Clients    {        public static List
Get() { return new List
{ new Client { ClientName = "App接口服务", ClientId = "app_test_id", Enabled = true, AccessTokenType = AccessTokenType.Reference, Flow = Flows.ClientCredentials, ClientSecrets = new List
{ new Secret("F621F470-9731-4A25-80EF-67A6F7C5F4B8".Sha256()) }, AllowedScopes = new List
{ "user", "order" } } }; }

作用域

public class Scopes    {        public static List
Get() { return new List
{ new Scope { Name = "user" }, new Scope { Name = "order" } }; } }

用户(客户端模式不需要用户参与所以没有用户数据)

完成上述工作,服务端基础服务就完成了,访问 /.well-known/openid-configuration ,可以获得服务的配置信息,暂且部署到 服务器上,配置信息如下(官方也就有服务端的示例: )

{    "issuer": "http://192.168.210.165",    "jwks_uri": "http://192.168.210.165/.well-known/jwks",    "authorization_endpoint": "http://192.168.210.165/connect/authorize",    "token_endpoint": "http://192.168.210.165/connect/token",    "userinfo_endpoint": "http://192.168.210.165/connect/userinfo",    "end_session_endpoint": "http://192.168.210.165/connect/endsession",    "check_session_iframe": "http://192.168.210.165/connect/checksession",    "revocation_endpoint": "http://192.168.210.165/connect/revocation",    "introspection_endpoint": "http://192.168.210.165/connect/introspect",    "frontchannel_logout_supported": true,    "frontchannel_logout_session_supported": true,    "scopes_supported": [        "user",        "order"    ],    "claims_supported": [ ],    "response_types_supported": [        "code",        "token",        "id_token",        "id_token token",        "code id_token",        "code token",        "code id_token token"    ],    "response_modes_supported": [        "form_post",        "query",        "fragment"    ],    "grant_types_supported": [        "authorization_code",        "client_credentials",        "password",        "refresh_token",        "implicit"    ],    "subject_types_supported": [        "public"    ],    "id_token_signing_alg_values_supported": [        "RS256"    ],    "code_challenge_methods_supported": [        "plain",        "S256"    ],    "token_endpoint_auth_methods_supported": [        "client_secret_post",        "client_secret_basic"    ]}

注意:寄宿到 IIS 中需要 WebConfig 配置中需配置:

资源服务器

Install-Package Microsoft.Owin.Host.SystemWeb

Install-Package Microsoft.AspNet.WebApi.Owin
Install-Package IdentityServer3.AccessTokenValidation

服务配置

public class Startup    {        ///         /// 配置授权服务        ///         ///         public void Configuration(IAppBuilder app)        {            app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions            {                Authority = "http://192.168.210.165",                ValidationMode = ValidationMode.ValidationEndpoint,                EnableValidationResultCache = true,                ValidationResultCacheDuration = TimeSpan.FromMinutes(5),                RequiredScopes = new[] { "user", "order" }            });        }    }

控制器

[Route("api/v1/values")]    public class ValuesController : ApiController    {        public IHttpActionResult Get()        {            var caller = User as ClaimsPrincipal;            return Json(new            {                message = "OK computer",                client = caller.FindFirst("client_id").Value            });        }    }

OK,完成,由于是一台测试服务器,部署到 端口。

客户端

Install-Package serilog

Install-Package serilog.sinks.literate
Install-Package IdentityModel

class Program    {        static void Main(string[] args)        {            var log = new LoggerConfiguration()                          .WriteTo                          .LiterateConsole(outputTemplate: "{Timestamp:HH:mm} [{Level}] ({Name:l}){NewLine} {Message}{NewLine}{Exception}")                          .CreateLogger();            var token = new TokenClient(                         "http://192.168.210.165/connect/token",                         "app_test_id",                         "F621F470-9731-4A25-80EF-67A6F7C5F4B8");            var response = token.RequestClientCredentialsAsync("user").Result;            var client = new HttpClient();            client.SetBearerToken(response.AccessToken);            log.Information(client.GetStringAsync("http://192.168.210.165:88/api/v1/values").Result);            Console.ReadKey();        }    }

测试

顺便使用Fiddler抓了一下包

POST http://192.168.210.165/connect/token HTTP/1.1                Accept: application/json                Authorization: Basic YXBwX3Rlc3RfaWQ6RjYyMUY0NzAtOTczMS00QTI1LTgwRUYtNjdBNkY3QzVGNEI4                Content-Type: application/x-www-form-urlencoded                Host: 192.168.210.165                Content-Length: 40                Expect: 100-continue                Connection: Keep-Alive                grant_type=client_credentials&scope=user

GET http://192.168.210.165:88/api/v1/values HTTP/1.1                Authorization: Bearer 9f82476751e1f8b93f1ea6df7de83b51                Host: 192.168.210.165:88

个人比较喜欢使用 这个类库,可以扩展一下客户端,扩展的方法现在还有一些问题,就不贴代码了。

其他细节

  • 生产环境最好加证书与HTTPS
  • 客户端,作用域,持久化到DB(有EF的扩展 )
  • 票据的持久化与自定义验证

REFER:

Announcing IdentityServer for ASP.NET 5 and .NET Core
OAuth2 Implicit Flow with Angular and ASP.NET Core 1.0 IdentityServer
理解OAuth 2.0

转载地址:http://ivqlx.baihongyu.com/

你可能感兴趣的文章
备忘录模式
查看>>
第三方支付集成
查看>>
android 自定义radiogroup的两种方式
查看>>
T-SQL中return 返回语句学习
查看>>
C# .NET中的 反射的应用
查看>>
Codeigniter 利用加密Key(密钥)的对象注入漏洞
查看>>
【转】Android 二维码 生成和识别(附Demo源码)--不错
查看>>
adb shell dumpsys 命令 查看内存
查看>>
android 自定义命名空间
查看>>
apache和nginx支持SSI配置
查看>>
--@angularJS--一个最简单的指令demo
查看>>
Qt resizeEvent 控件居中设置
查看>>
深入理解spring中的各种注解(转)
查看>>
BootStrap安装
查看>>
ng-class的使用
查看>>
设计模式之建造者模式
查看>>
关于华为交换机bpdu enable. ntdp enable. ndp enable解析
查看>>
当你学不进去的时候,试试“普瑞马法则”
查看>>
编写DLL
查看>>
2015年第12本(英文第8本):the Old Man and the Sea 老人与海
查看>>