IdentityServer3——入门教程:创建简单的OAuth2.0服务器,客户端和API

本教程的目的在于创造尽可能简单的identityserver安装作为一个oauth2授权服务器。这应该能够让你了解一些基本功能和配置选项(完整的源代码可以发现在这里)。在后面的文档中会介绍更多的高级功能。本教程包括:

  • 创建一个自托管identityserver
  • 设置为使用一个应用程序的帐户以及用户对通信应用的客户服务代表
  • 注册一个API
  • 请求访问令牌
  • 调用API
  • 验证一个访问令牌

创建一个授权服务器(IdentityServer3)

创建一个控制台应用程序,并且在程序包管理器控制台中输入

install-package identityserver3

注册API

API作为请求范围,您需要注册所有您希望能够请求访问令牌的所有API,然后我们创建一个类用于返回在这个作用范围内所有的API

using IdentityServer3.Core.Models;

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

注册客户端

现在我们要注册一个客户端。这个客户将能够申请api1 scope的资源。对于我们的第一次迭代,将有没有人参与,客户端将简单地要求代表自己的令牌(认为机器与机器通信)。

对于这个客户端,我们配置以下的东西:

  • 显示名称和编号(唯一的名称)
  • 客户端密钥
  • 客户端凭据
  • 使用所谓的引用标记。参考标记不需要签名证书。
  • 允许访问的作用域("api1")
using IdentityServer3.Core.Models;

static class Clients
{
    public static List<Client> Get()
    {
        return new List<Client>
        {
           // no human involved
            new Client
            {
                ClientName = "Silicon-only Client",
                ClientId = "silicon",
                Enabled = true,
                AccessTokenType = AccessTokenType.Reference,

                Flow = Flows.ClientCredentials,

                ClientSecrets = new List<Secret>
                {
                    new Secret("F621F470-9731-4A25-80EF-67A6F7C5F4B8".Sha256())
                },

                AllowedScopes = new List<string>
                {
                    "api1"
                }
            }
        };
    }
}

配置 IdentityServer

identityserver作为OWIN的中间件的实现,它是通过UseIdentityServer扩展方法在Startup类中配置。

下面的代码配置一个使用我们之前定义的客户端个作用域的授权服务器,稍后我们会添加用户进来。

using Owin;
using System.Collections.Generic;
using IdentityServer3.Core.Configuration;
using IdentityServer3.Core.Services.InMemory;

namespace IdSrv
{
    class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            var options = new IdentityServerOptions
            {
                Factory = new IdentityServerServiceFactory()
                            .UseInMemoryClients(Clients.Get())
                            .UseInMemoryScopes(Scopes.Get())
                            .UseInMemoryUsers(new List<InMemoryUser>()),

                RequireSsl = false
            };

            app.UseIdentityServer(options);
        }
    }
}

添加日志记录

因为我们在一个控制台中运行,它是非常方便的日志输出直接到控制台窗口。Serilog是一个很好的日志库

install-package serilog
install-package serilog.sinks.literate

托管 IdentityServer

最后一步是托管identityserver。在程序包管理控制台添加OWIN

install-package Microsoft.Owin.SelfHost

在Program.cs文件中添加一下代码:

// logging
Log.Logger = new LoggerConfiguration()
    .WriteTo
    .LiterateConsole(outputTemplate: "{Timestamp:HH:MM} [{Level}] ({Name:l}){NewLine} {Message}{NewLine}{Exception}")
    .CreateLogger();

// hosting identityserver
using (WebApp.Start<Startup>("http://localhost:5000"))
{
    Console.WriteLine("server running...");
    Console.ReadLine();
}

然后当你启动控制台程序的时候你会看到控制台输出“server running...”

添加一个 API

在这一部分中我们将添加一个简单的Web API,我们只需要从identityserver设置一个访问令牌。

创建API应用程序

在的解决方案中添加一个新的ASP.NET Web API 应用程序,选择空模板

添加必要的NuGet包:

install-package Microsoft.Owin.Host.SystemWeb
install-package Microsoft.AspNet.WebApi.Owin
install-package IdentityServer3.AccessTokenValidation

添加Controller

添加这个简单的测试控制器:

[Route("test")]
public class TestController : ApiController
{
    public IHttpActionResult Get()
    {
        var caller = User as ClaimsPrincipal;

        return Json(new
        {
            message = "OK computer",
            client =  caller.FindFirst("client_id").Value
        });
    }
}

控制器上的用户属性让您从访问令牌中访问该请求的权限。

添加Startup

添加以下Startup.cs为建立Web API和identityserver配置信任启动类

using IdentityServer3.AccessTokenValidation;

public void Configuration(IAppBuilder app)
{
    // accept access tokens from identityserver and require a scope of ‘api1‘
    app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions
        {
            Authority = "http://localhost:5000",
            ValidationMode = ValidationMode.ValidationEndpoint,

            RequiredScopes = new[] { "api1" }
        });

    // configure web api
    var config = new HttpConfiguration();
    config.MapHttpAttributeRoutes();

    // require authentication for all controllers
    config.Filters.Add(new AuthorizeAttribute());

    app.UseWebApi(config);
}

试着打开浏览器,访问测试控制器-你应该看到一个401,因为必要的访问令牌丢失。

添加Console客户端

在下一部分中,我们将添加一个简单的控制台客户端,该客户端将请求访问令牌,并使用该接口进行身份验证。

首先添加一个新的控制台项目并安装一oauth2客户端需要的NuGet包:

install-package IdentityModel

第一段代码 获取客户端Token使用客户端证书:

using IdentityModel.Client;

static TokenResponse GetClientToken()
{
    var client = new TokenClient(
        "http://localhost:5000/connect/token",
        "silicon",
        "F621F470-9731-4A25-80EF-67A6F7C5F4B8");

    return client.RequestClientCredentialsAsync("api1").Result;
}

第二段代码 使用访问令牌调用API:

static void CallApi(TokenResponse response)
{
    var client = new HttpClient();
    client.SetBearerToken(response.AccessToken);

    Console.WriteLine(client.GetStringAsync("http://localhost:14869/test").Result);
}

如果你启动控制台程序,你应该看到{"message":"OK computer","client":"silicon"}在您的控制台。

添加一个用户

到目前为止,客户端请求一个访问令牌本身,没有用户参与。让我们介绍一个人。

添加一个获取用户的服务

用户服务管理用户-对于这个示例,我们将使用简单的内存用户服务。首先我们需要定义一些用户:

using IdentityServer3.Core.Services.InMemory;

static class Users
{
    public static List<InMemoryUser> Get()
    {
        return new List<InMemoryUser>
        {
            new InMemoryUser
            {
                Username = "bob",
                Password = "secret",
                Subject = "1"
            },
            new InMemoryUser
            {
                Username = "alice",
                Password = "secret",
                Subject = "2"
            }
        };
    }
}

用户名和密码被用来验证用户,subject是该用户将被嵌入到访问令牌的唯一标识符。使用Users.Get()替换Startup.cs中的new List<InMemoryUser>()

添加一个客户端

接下来,我们将添加一个客户定义,使用流称为资源所有者的密码证书授予。此流程允许客户端将用户的用户名和密码发送到令牌服务,并在返回中获取访问令牌。

using IdentityServer3.Core.Models;
using System.Collections.Generic;

namespace IdSrv
{
    static class Clients
    {
        public static List<Client> Get()
        {
            return new List<Client>
            {
                // no human involved
                new Client
                {
                    ClientName = "Silicon-only Client",
                    ClientId = "silicon",
                    Enabled = true,
                    AccessTokenType = AccessTokenType.Reference,

                    Flow = Flows.ClientCredentials,

                    ClientSecrets = new List<Secret>
                    {
                        new Secret("F621F470-9731-4A25-80EF-67A6F7C5F4B8".Sha256())
                    },

                    AllowedScopes = new List<string>
                    {
                        "api1"
                    }
                },

                // human is involved
                new Client
                {
                    ClientName = "Silicon on behalf of Carbon Client",
                    ClientId = "carbon",
                    Enabled = true,
                    AccessTokenType = AccessTokenType.Reference,

                    Flow = Flows.ResourceOwner,

                    ClientSecrets = new List<Secret>
                    {
                        new Secret("21B5F798-BE55-42BC-8AA8-0025B903DC3B".Sha256())
                    },

                    AllowedScopes = new List<string>
                    {
                        "api1"
                    }
                }
            };
        }
    }
}

更新API

当涉及到人的时候,访问令牌将包含子请求以唯一标识用户。让我们对API的控制器做小的修改,:

[Route("test")]
public class TestController : ApiController
{
    public IHttpActionResult Get()
    {
        var caller = User as ClaimsPrincipal;

        var subjectClaim = caller.FindFirst("sub");
        if (subjectClaim != null)
        {
            return Json(new
            {
                message = "OK user",
                client = caller.FindFirst("client_id").Value,
                subject = subjectClaim.Value
            });
        }
        else
        {
            return Json(new
            {
                message = "OK computer",
                client = caller.FindFirst("client_id").Value
            });
        }
    }
}

更新客户端

下一个向客户端添加一个新的方法,代表用户请求访问令牌:

static TokenResponse GetUserToken()
{
    var client = new TokenClient(
        "http://localhost:5000/connect/token",
        "carbon",
        "21B5F798-BE55-42BC-8AA8-0025B903DC3B");

    return client.RequestResourceOwnerPasswordAsync("bob", "secret", "api1").Result;
}

现在再次尝试获取token看看API返回的信息吧

时间: 2024-08-06 11:36:36

IdentityServer3——入门教程:创建简单的OAuth2.0服务器,客户端和API的相关文章

创建自己的OAuth2.0服务端(一)

如果对OAuth2.0有任何的疑问,请先熟悉OAuth2.0基础的文章:http://www.cnblogs.com/alunchen/p/6956016.html 1. 前言 本篇文章时对 客户端的授权模式-授权码模式 的创建,当然你理解的最复杂的模式之后,其他模式都是在授权码模式上面做一些小改动即可.对于授权码模式有任何的疑问,请看上面提到的文章. 注意:本文是创建OAuth的Server端,不是Client请求端. 2. 开始授权码模式的概念.流程 第2点其实就是复制了上一篇文章,为了提高

IdentityServer3——入门教程:.NET开源OpenID Connect 和OAuth解决方案IdentityServer v3 术语

你应该知道的在文档和对象模型中使用一些特定的术语: OpenID Connect Provider (OP) 授权服务器 Thinktecture IdentityServer v3 是一个.NET 平台上开源的OpenID Connect 提供者 和 OAuth2 验证服务器,OpenID Connect Provider在不同的著作中有不同的说法,你可能发现有的叫安全令牌服务提供商,授权服务器,ip-sts和更多. 简单来说他们的共同点:为客户端提供一块安全令牌的软件. IdentitySe

Spring Cloud 入门教程(六): 用声明式REST客户端Feign调用远端HTTP服务

首先简单解释一下什么是声明式实现? 要做一件事, 需要知道三个要素,where, what, how.即在哪里( where)用什么办法(how)做什么(what).什么时候做(when)我们纳入how的范畴. 1)编程式实现: 每一个要素(where,what,how)都需要用具体代码实现来表示.传统的方式一般都是编程式实现,业务开发者需要关心每一处逻辑 2)声明式实现: 只需要声明在哪里(where )做什么(what),而无需关心如何实现(how).Spring的AOP就是一种声明式实现,

Asp.net Api中使用OAuth2.0实现“客户端验证”

一.实现继承自OAuthAuthorizationServerProvider的类,实现以"客户端验证"方式传入的相关认证和access_token发放. public class MyOwnOAuthProvider:OAuthAuthorizationServerProvider { private static readonly Logger logger = LogManager.GetLogger("MyOwnOAuth"); /// <summar

怎么使用获得的OAuth2.0 Access Token调用API

String url=" url?access_token="+access_token; HttpGet request=new HttpGet(url); System.out.println("保存的access_token="+access_token);HttpClient client=new GetDefaultClient().getNewHttpClient(); try{ HttpResponse response=client.execute(

Spring Security 入门(1-3)Spring Security oauth2.0 指南

入门 这是支持OAuth2.0的用户指南.对于OAuth1.0,一切都是不同的,所以看它的用户指南. 本用户指南分为两个部分,第一部分是OAuth2.0提供端(OAuth 2.0 Provider),第二部分是OAuth2.0的客户端(OAuth 2.0 Client) OAuth2.0提供端 OAuth2.0的提供端的用途是负责将受保护的资源暴露出去.建立一个可以访问受保护的资源的客户端列表. 提供端是通过管理和验证可用于访问受保护的资源的OAuth 2令牌来做的. 在适当的地方,提供端必须为

Spring Cloud 入门教程(五): Ribbon实现客户端的负载均衡

接上节,假如我们的Hello world服务的访问量剧增,用一个服务已经无法承载, 我们可以把Hello World服务做成一个集群. 很简单,我们只需要复制Hello world服务,同时将原来的端口8762修改为8763.然后启动这两个Spring Boot应用, 就可以得到两个Hello World服务.这两个Hello world都注册到了eureka服务中心.这时候再访问http://localhost:8761, 可以看到两个hello world服务已经注册.(服务与注册参见Spr

phaser学习总结之phaser入门教程

前言 最近公司做项目的时候正好使用到phaser,在这里做一下自己整理出来的一些心得,方便大家参考,phaser这一个游戏引擎通常是做2d游戏的,入门也非常简单,只需你会一点的javascript,但是你想做一个比较完美的游戏的话,那么光靠一点点的javascript是远远不够的,本篇博客将快速带你入门phaser. phaser简介 phaser是一款快速,免费及开源HTML5游戏框架,它支持WebGL和Canvas两种渲染模式,可以在任何web浏览器环境下运行,游戏可以通过第三方工具转为iO

基于OWIN+DotNetOpenOAuth实现OAuth2.0

这几天时间一直在研究怎么实现自己的OAuth2服务器,对于太了解OAuth原理以及想自己从零开始实现的,我建议可以参考<Apress.Pro ASP.NET Web API Security>里面的章节.最后发现其实微软在这方面也已经做了实现,所以文介绍下怎么基于OWIN来实现自己的OAuth2.0授权服务器,,以及怎么使用DotNetOpenAuth作为客户端来访问受保护的资源.  OWIN是一套specification,微软的Katana开源项目是基于OWIN标准开发的,所以本本文更准确