asp.net core系列 55 IS4使用Identity密码保护API
一.概述
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项目目录结构:
(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系列 57 IS4 使用混合流(OIDC+OAuth2.0)添加API访问
-
asp.net core系列 56 IS4使用OpenID Connect添加用户认证
-
asp.net core系列 55 IS4使用Identity密码保护API
-
asp.net core系列 54 IS4用客户端凭据保护API
-
asp.net core系列 55 IS4使用Identity密码保护API
-
asp.net core系列 56 IS4使用OpenID Connect添加用户认证
-
asp.net core系列 57 IS4 使用混合流(OIDC+OAuth2.0)添加API访问
-
asp.net core系列 54 IS4用客户端凭据保护API