zoukankan      html  css  js  c++  java
  • 基于 IdentityServer3 实现 OAuth 2.0 授权服务【客户端模式(Client Credentials Grant)】

    github:https://github.com/IdentityServer/IdentityServer3/
    documentation:
    https://identityserver.github.io/Documentation/
    samples
    https://github.com/IdentityServer/IdentityServer3.Samples/

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

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

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

    授权角色

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

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

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

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

    Client Credentials Grant 模式只需要关注 授权服务器,资源服务器,客户端三个角色  具体:https://identityserver.github.io/Documentation/docsv2/overview/terminology.html

    授权服务器

    Install-Package IdentityServer3

    服务配置

    public class Startup
        {
            /// <summary>
            /// 配置idsv授权服务
            /// </summary>
            /// <param name="app"></param>
            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<InMemoryUser>()),
                    //.UseInMemoryUsers(Users.Get())
                    RequireSsl = false,
                    //SigningCertificate = new X509Certificate2(string.Format(@"{0}inidentityServeridsrv3test.pfx", AppDomain.CurrentDomain.BaseDirectory), "idsrv3test")
                };
                app.UseIdentityServer(opts);
    
                /*
                    //自定义路由
                    app.Map("/identity", idsrvApp =>
                    {
                        idsrvApp.UseIdentityServer(opts);
                    });
                */
            }
        }

    客户端

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

    作用域

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

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

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

    {
    
        "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 配置中需配置:

    <system.webServer>
      <modules runAllManagedModulesForAllRequests="true">
      </modules>
    </system.webServer

    资源服务器

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

    服务配置

    public class Startup
        {
            /// <summary>
            /// 配置授权服务
            /// </summary>
            /// <param name="app"></param>
            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,完成,由于是一台测试服务器,部署到 http://192.168.210.165:88/ 端口。

    客户端

    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

    image

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

    image

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

    其他细节

    REFER:
    Announcing IdentityServer for ASP.NET 5 and .NET Core
    http://leastprivilege.com/2016/01/11/announcing-identityserver-for-asp-net-5-and-net-core/
    OAuth2 Implicit Flow with Angular and ASP.NET Core 1.0 IdentityServer
    http://damienbod.com/2015/11/08/oauth2-implicit-flow-with-angular-and-asp-net-5-identity-server
    理解OAuth 2.0
    http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html

  • 相关阅读:
    Makefile 一点一滴(三)—— 尝试简单的变量替换
    Makefile 一点一滴(二)—— 输出文件到指定路径
    Makefile 一点一滴(一)—— 从最简单的makefile模板写起
    用fxc.exe编译shader文件(*.fx, *.hlsl)的设置
    全国管理系统
    [原]产品经理和韦小宝
    [原]详细分析 javascript 的内存分配
    [原]看看腾讯是怎么做产品设计分析的 - 腾讯QQ音乐业务产品规划
    [原]Android布局管理器
    [原]ubuntu wubi.exe 直接加载下载好的 amd64.tar.xz
  • 原文地址:https://www.cnblogs.com/Irving/p/5707215.html
Copyright © 2011-2022 走看看