当前位置: 移动技术网 > IT编程>开发语言>.net > 从Client应用场景介绍IdentityServer4(一)

从Client应用场景介绍IdentityServer4(一)

2018年12月18日  | 移动技术网IT编程  | 我要评论

中国梦我的梦想作文,兔展微信红包 功能,随身翻译

一、背景

identityserver4的介绍将不再叙述,百度下可以找到,且官网的快速入门例子也有翻译的版本。然而发现关于它应用方面的文章介绍稍微欠缺,所以这里主要从client应用场景方面介绍对identityserver4的应用。

首先简要介绍id token和access token:

access token是授权第三方客户端访问受保护资源的令牌。 id token是第三方客户端标识用户身份认证的问令牌,是json web token格式。

 


 

二、client应用场景介绍

client类是为openid connect或oauth 2.0 协议建模的。

我们先看官网快速入门中给的client例子

 public static ienumerable<client> getclients()
        {
            // client credentials client
            return new list<client>
            {
                new client
                {
                    clientid = "client",
                    allowedgranttypes = granttypes.clientcredentials,
                    clientsecrets =
                    {
                        new secret("secret".sha256())
                    },
                    allowedscopes = { "api1" }
                },

                // resource owner password grant client
                new client
                {
                    clientid = "ro.client",
                    allowedgranttypes = granttypes.resourceownerpassword,

                    clientsecrets = 
                    {
                        new secret("secret".sha256())
                    },
                    allowedscopes = { "api1" }                },

                // openid connect hybrid flow and client credentials client (mvc)
                new client
                {
                    clientid = "mvc",
                    clientname = "mvc client",
                    allowedgranttypes = granttypes.hybridandclientcredentials,

                    clientsecrets =
                    {
                        new secret("secret".sha256())
                    },

                    redirecturis = { "http://localhost:5002/signin-oidc" },
                    postlogoutredirecturis = { "http://localhost:5002/signout-callback-oidc" },

                    allowedscopes =
                    {
                        identityserverconstants.standardscopes.openid,
                        identityserverconstants.standardscopes.profile,
                        "api1"
                    },
                    allowofflineaccess = true
                },

                // javascript client
                new client
                {
                    clientid = "js",
                    clientname = "javascript client",
                    allowedgranttypes = granttypes.implicit,
                    allowaccesstokensviabrowser = true,

                    redirecturis = { "http://localhost:5003/callback.html" },
                    postlogoutredirecturis = { "http://localhost:5003/" },
                    allowedcorsorigins = { "http://localhost:5003" },

                    allowedscopes =
                    {
                        identityserverconstants.standardscopes.openid,
                        identityserverconstants.standardscopes.profile,
                        "api1"
                    },
                }
            };
        }

里面主要介绍四种client应用场景。

(1)客户端授权模式(allowedgranttypes = granttypes.clientcredentials

    这是一种最简单的授权方式,应用于服务于服务之间的通信,token通常代表的是客户端的请求,而不是用户。

    使用这种授权类型,会向token endpoint发送token请求,并获得代表客户机的access token。客户端通常必须使用token endpoint的client id和secret进行身份验证。

    适用场景:用于和用户无关,机器与机器之间直接交互访问资源

(2)资源的密码授权模式(clientallowedgranttypes = granttypes.resourceownerpassword

    该方式发送用户名和密码到token endpoint,向资源服务器请求令牌。这是一种“非交互式”授权方法。

    官网上称,为了解决一些历史遗留的应用场景,所以保留了这种授权方式,但不建议使用。

    适用场景:用于当前的app是专门为服务端设计的情况。

(3)hybrid和客户端授权模式(clientallowedgranttypes =granttypes.hybridandclientcredentials

    clientcredentials授权方式在第一种应用场景已经介绍了,这里主要介绍hybrid授权方式。hybrid是由implicit和authorization code结合起来的一种授权方式。其中implicit用于身份认证,id token在浏览器传输;而authorization code使用反向通道检索token和刷新token。

    推荐适用hybrid模式。

    适用场景:用于mvc框架,服务器端 web 应用程序和原生桌面/移动应用程序。

(4)简化模式(clientallowedgranttypes =granttypes.implicit

    implicit要么仅用于服务端和javascript应用程序端进行身份认证,要么用于身份身份验证和access token的传输。

    在implicit中,所有token都通过浏览器传输的。

    适用场景:javascript应用程序。


 

三、server端搭建

为了介绍identityserver4的client应用场景,我们需要先搭建identityserver服务端。

这里搭建的是使用ef core来做数据操作,保存到sql server中。

(1)新建api项目

(2)安装identityserver4.entityframework包

(3)安装identityserver4包

(4)右键项目的属性,编辑项目的.csproj文件

添加如下元素

<itemgroup>
    <dotnetclitoolreference include="microsoft.entityframeworkcore.tools.dotnet" version="2.0.0" />
</itemgroup>

如图:

(5)cmd管理员身份进入项目目录路径(d:\identityserver4\server),运行:dotnet ef

(6)项目内添加config.cs类,代码如下

 public class config
    {
        public static list<testuser> getusers()
        {
            return new list<testuser>
            {
                new testuser
                {
                    subjectid = "1",
                    username = "alice",
                    password = "password",

                  claims = new list<claim>(){new claim(jwtclaimtypes.role,"superadmin") }
                },
                new testuser
                {
                    subjectid = "2",
                    username = "bob",
                    password = "password",

                    claims = new list<claim>
                    {
                        new claim("name", "bob"),
                        new claim("website", "https://bob.com")
                    },
                }
            };
        }

        public static ienumerable<client> getclients()
        {
            // client credentials client
            return new list<client>
            {
                new client
                {
                    clientid = "client",
                    allowedgranttypes = granttypes.clientcredentials,
                    clientsecrets =
                    {
                        new secret("secret".sha256())
                    },
                    allowedscopes = { "api1" }
                },

                // resource owner password grant client
                new client
                {
                    clientid = "ro.client",
                    allowedgranttypes = granttypes.resourceownerpassword,

                    clientsecrets =
                    {
                        new secret("secret".sha256())
                    },
                    allowedscopes = { "api1" }
                },

                // openid connect hybrid flow and client credentials client (mvc)
                new client
                {
                    clientid = "mvc",
                    clientname = "mvc client",
                    allowedgranttypes = granttypes.hybridandclientcredentials,

                    clientsecrets =
                    {
                        new secret("secret".sha256())
                    },

                    redirecturis = { "http://localhost:5002/signin-oidc" },
                    postlogoutredirecturis = { "http://localhost:5002/signout-callback-oidc" },

                    allowedscopes =
                    {
                        identityserverconstants.standardscopes.openid,
                        identityserverconstants.standardscopes.profile,
                        "api1"
                    },
                    allowofflineaccess = true
                },

                // javascript client
                new client
                {
                    clientid = "js",
                    clientname = "javascript client",
                    allowedgranttypes = granttypes.implicit,
                    allowaccesstokensviabrowser = true,

                    redirecturis = { "http://localhost:5003/callback.html" },
                    postlogoutredirecturis = { "http://localhost:5003/" },
                    allowedcorsorigins = { "http://localhost:5003" },

                    allowedscopes =
                    {
                        identityserverconstants.standardscopes.openid,
                        identityserverconstants.standardscopes.profile,
                        "api1"
                    },
                }
            };
        }
        public static ienumerable<identityresource> getidentityresources()
        {
            return new list<identityresource>
            {
                new identityresources.openid(),
                new identityresources.profile(),
            };
        }

        public static ienumerable<apiresource> getapiresources()
        {
            return new list<apiresource>
            {
                new apiresource("api1", "my api")
            };
        }

添加引用:

using identitymodel;

using identityserver4;

using identityserver4.models;

using identityserver4.test;

using system.collections.generic;

using system.security.claims;

(7)编辑startup.cs文件的configureservices方法,改成如下代码。

public void configureservices(iservicecollection services)
        {
            const string connectionstring = @"server=localhost;database=identityserver4;user id=sa;password=pwd;trusted_connection=yes";
            var migrationsassembly = typeof(startup).gettypeinfo().assembly.getname().name;

            // configure identity server with in-memory stores, keys, clients and scopes
            services.addidentityserver()
                .adddevelopersigningcredential()
                .addtestusers(config.getusers())
                // this adds the config data from db (clients, resources)
                .addconfigurationstore(options =>
                {
                    options.configuredbcontext = builder =>
                        builder.usesqlserver(connectionstring,
                            sql => sql.migrationsassembly(migrationsassembly));
                })
                // this adds the operational data from db (codes, tokens, consents)
                .addoperationalstore(options =>
                {
                    options.configuredbcontext = builder =>
                        builder.usesqlserver(connectionstring,
                            sql => sql.migrationsassembly(migrationsassembly));

                    // this enables automatic token cleanup. this is optional.
                    options.enabletokencleanup = false;//是否从数据库清楚令牌数据,默认为false
                    options.tokencleanupinterval = 300;//令牌过期时间,默认为3600秒,一个小时
                });
            //.addinmemoryclients(config.getclients());
            services.addmvc().setcompatibilityversion(compatibilityversion.version_2_1);
        }

添加引用:

using microsoft.entityframeworkcore;

using system.reflection;

(8)cmd管理员身份进入到项目目录路径(d:\identityserver4\server\server),注意,多了一层目录,分别运行以下两条指令:

dotnet ef migrations add initialidentityserverpersistedgrantdbmigration -c persistedgrantdbcontext -o data/migrations/identityserver/persistedgrantdb

dotnet ef migrations add initialidentityserverconfigurationdbmigration -c configurationdbcontext -o data/migrations/identityserver/configurationdb

运行完后,项目中会多了一个data文件夹

(9)在startup.cs中添加初始化数据库方法。

private void initializedatabase(iapplicationbuilder app)
{
    using (var servicescope = app.applicationservices.getservice<iservicescopefactory>().createscope())
    {
        servicescope.serviceprovider.getrequiredservice<persistedgrantdbcontext>().database.migrate();

        var context = servicescope.serviceprovider.getrequiredservice<configurationdbcontext>();
        context.database.migrate();
        if (!context.clients.any())
        {
            foreach (var client in config.getclients())
            {
                context.clients.add(client.toentity());
            }
            context.savechanges();
        }

        if (!context.identityresources.any())
        {
            foreach (var resource in config.getidentityresources())
            {
                context.identityresources.add(resource.toentity());
            }
            context.savechanges();
        }

        if (!context.apiresources.any())
        {
            foreach (var resource in config.getapiresources())
            {
                context.apiresources.add(resource.toentity());
            }
            context.savechanges();
        }
    }
}

添加引用:

using identityserver4.entityframework.dbcontexts;

using identityserver4.entityframework.mappers;

(10)在startup.cs中的configure方法修改成以下代码。

  public void configure(iapplicationbuilder app, ihostingenvironment env)
        {
            //if (env.isdevelopment())
            //{
            //    app.usedeveloperexceptionpage();
            //}
            initializedatabase(app);
            //app.usemvc();
        }

到这里,把项目以控制台形式运行

点击运行,可以跑起来,且生成数据库identityserver4db。

关于client的说明可以查阅官网资料:https://identityserver4.readthedocs.io/en/release/reference/client.html

源码地址:https://github.com/bingjian-zhu/server.git

服务端准备好之后,下篇文章开始介绍client客户端的应用。

文中如有错漏,欢迎指正,将对此系列文章进行维护。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网