欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

asp.net core系列 55 IS4使用Identity密码保护API

程序员文章站 2022-06-18 09:55:50
一.概述 OAuth 2.0资源(web api)所有者密码授权,允许客户端(Client项目)向令牌服务(IdentityServer项目)发送用户名和密码,并获取代表该用户的访问令牌。在官方文档中讲到:规范通常建议不要使用“资源所有者密码授权”。当用户进行身份验证并请求访问令牌时,使用一个交互式 ......

一.概述

  oauth 2.0资源(web api)所有者密码授权,允许客户端(client项目)向令牌服务(identityserver项目)发送用户名和密码,并获取代表该用户的访问令牌。在官方文档中讲到:规范通常建议不要使用“资源所有者密码授权”。当用户进行身份验证并请求访问令牌时,使用一个交互式openid connect流程通常要好得多(下篇再了解)。

  本篇介绍“资源所有者密码授权”是因为这种授权允许我们快速启动identityserver。开源地址:github 

  下面示例与官方示例有点区别,该示例使用了identity密码保护api。关于asp.net core identity的了解实现,查看之前章节或官方文档。示例中分别是identityserver令牌项目、 api资源项目、 client访问项目。与上篇相比一样,还是三个项目,区别在于:

  (1) identityserver令牌项目换成了含有asp.net core identity的mvc项目。

  (2) api资源项目没有变动。

  (3) client访问项目使用了用户名和密码访问受保护的api。

 

二. identityserver项目

  identityserver令牌项目是包含了 identity功能(安装:install-package identityserver4),在项目中,添加了config.cs类和startup.cs中加入了identityserver的启动配置。下面是mvc项目目录结构:

asp.net core系列 55 IS4使用Identity密码保护API

  (1) 添加用户

    identityserver类库中自带testuser测试类,是dto数据传输对象,存储用户及其声明(claims)。testuser是用于测试中的内存(in-memory)用户对象。在正式环境下,获取数据库中的用户表(user),需要结合identityserver的iresourceownerpasswordvalidator接口(不再本篇讲述中)。 下面通过在config.cs类中添加getusers方法获取用户密码,存储在testuser数据传输对象中。

        /// <summary>
        ///获取用户,这些用户可以访问受密码保护的api
        /// </summary>
        /// <param name="provider"></param>
        /// <returns></returns>
        public static list<testuser> getusers(serviceprovider provider)
        {
            var webappidentitydemouser = provider.getrequiredservice<usermanager<webappidentitydemouser>>();
            ilist<webappidentitydemouser> users = null;
            //获取identity的user表用户,条件是属于administrator角色的用户
            users = webappidentitydemouser.getusersinroleasync("administrator").result;

            list<testuser> testuserlist = new list<testuser>();
            foreach (webappidentitydemouser user in users)
            {
                testuserlist.add(new testuser() { subjectid = user.id.tostring(), username = user.username, password = user.passwordhash });
            }
            return testuserlist;
        }

  (2) 然后在startup类的configureservices方法中使用identityserver注入测试用户:

            serviceprovider provider = services.buildserviceprovider();

            var builder = services.addidentityserver()
                .addinmemoryidentityresources(config.getidentityresources())
                .addinmemoryapiresources(config.getapis())
                .addinmemoryclients(config.getclients())
                .addtestusers(config.getusers(provider));

  (3) 定义客户端, 使用密码授予访问此api(资源范围:api1)

    在config.cs类中,定义客户端,通过修改allowedgranttypes枚举来简单地向现有客户端添加对授权类型的支持, 将以下代码添加到客户端配置中, 里面支持二个client授权类型,分别是clientcredentials使用凭证来访问令牌和resourceownerpassword 使用密码来访问令牌。

      public static ienumerable<client> getclients()
        {
            return new list<client>
            {
                new client
                {
                    clientid = "client",

                    // no interactive user, use the clientid/secret for authentication
                    allowedgranttypes = granttypes.clientcredentials,

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

                    // scopes that client has access to
                    allowedscopes = { "api1" }
                },
                // resource owner password grant client
                new client
                {
                    clientid = "ro.client",
                    allowedgranttypes = granttypes.resourceownerpassword,

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

  

三.client项目

  该client项目类似于上篇介绍的client项目,该项目名为resourceownerclient, 该client将收集用户名和密码,并在令牌请求期间,将其发送到identityserver令牌服务(webappidentitydemo项目)

            // request token 请求令牌
            var tokenresponse = await client.requestpasswordtokenasync(new passwordtokenrequest
            {
                address = disco.tokenendpoint,
                clientid = "ro.client",
                clientsecret = "secret",

                username = "924964690@qq.com",
                password = "aqaaaaeaaccqaaaaeh4xhui5bbyq6d8vs5z+s2o2snlkyrp5pn9cmmpgj4qiivrt7lblzdlewa6adlpxpa==",
                scope = "api1"
            });

            if (tokenresponse.iserror)
            {
                console.writeline(tokenresponse.error);
                return;
            }

            console.writeline(tokenresponse.json);
            console.writeline("\n\n");

  最后测试,先启动webappidentitydemo项目程序,再启动api程序,最后启动client客户端来访问api,通过下图可以了解到:(1)客户端请求使用“用户名和和密码”访问令牌(token)成功, (2) 客户端使用令牌(accesstoken)来访问受密码保护的web api接口成功。

asp.net core系列 55 IS4使用Identity密码保护API

  

  

  参考文献

    使用密码保护api