威势网络,为您的企业和团队注入互联网活力!
服务热线:138-9741-0341

[原创] IdentityServer4权限控制---使用 ASP.NET Core 的交互式应用程序(四)

发布日期:2022/9/4 作者: 浏览:904

  写了半天,不小心一关浏览器,没了!我也是醉了。。。又重新写一遍吧!

     前面三节课我们学习了用一个客户端先去申请令牌,得到令牌后再去访问API资源这样一个简单的流程,也是一个很常见的功能,通过前三节课的学习,我们搭建了一台API资源服务器,一台IDS4SERVER身份认证服务器,这节课我们接着上面的内容继续学习一下交互式登录的流程。

    开始之前,我先交待一下今天的学习任务吧!今天我们要用前面的IDS4SERVER服务器为我们新建的一个站点完成身份验证的过程,整个验证过程中有登录交互,有登录成功后的跳转,有登出功能,同样,客户拿到令牌后,对我们的网站拥有了“访问受保护资源的功能”。本文的标题后半部分是根据官方的文档直译的,想看原文的在这里,为了实现实验目的,我们需要做的工作有,创建一个MYMVC的新站点,该站点有首页、WHOAMI、LOGOUT等页面与功能,其中首页和隐私说明页是模板自带的,可以匿名浏览,而WHOAMI是登录后才可访问的,LOGOUT可以现在登出功能。除此之外,我们要做的工作还有搭建一台IDS4SERVER服务器,为站点提供身份验证功能。OK,我们开始吧!

    我们需要先搭建一台IDS4SERVER服务器,不会的朋友们请参考这里:


[原创] IdentityServer4权限控制---客户端授权模式之IDS4认证服务器搭建(二)

懒一些的朋友也可以直接这里下载: IdentityServer4 ,注意,因为我们要增加一些交互功能,而第二节课中的IDS4SERVER服务器并没有交互页面,所以我们还需要增加一个控制器和VIEW视图界面,如果你是用我刚刚提到的链接搭建的服务器,则把这些代码下下来放到项目中去,以给服务器添加控制器与视图交互功能,如果用的是官方的,则跳过这一步。上面链接提供的代码都是官方的DEMO,我只是改了一下命名空间名字。对了,代码放进去以后还要把控制器路由打开才行,不然代码无法访问,打开PROGRAM.CS文件,加入代码
app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}"); 这样控制器就可以使用了,我们试着运行一下,并在浏览器中访问一下试试。



OK,说明我们的代码可以正常运行了。

  紧接着我们再新建一个MYMVC站点。


新建一个MYMVC的站点


指定存放目录

然后选择.NET6.0,HTTPS支持,其它默认,一路生成下来,我们的新站点就OK了,我们为了让站点支持 OpenID Connect authentication协议,我们在PM命令行中运行命令,引入包

dotnet add package Microsoft.AspNetCore.Authentication.OpenIdConnect
打开新站点MYMVC的program.cs加入以下代码:



using System.IdentityModel.Tokens.Jwt;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllersWithViews();

JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = "Cookies";
    options.DefaultChallengeScheme = "oidc";
})
    .AddCookie("Cookies")
    .AddOpenIdConnect("oidc", options =>
    {
        options.Authority = "https://localhost:5001";

        options.ClientId = "mvc";
        options.ClientSecret = "secret";
        options.ResponseType = "code";

        options.SaveTokens = true;
    });

AddAuthentication 将认证服务注入到依赖中去."Cookies" 为默认 DefaultScheme,  DefaultChallengeScheme 登录质询方式改为oidc 指定 OpenID Connect 协议.然后用 AddCookie添加 cookies处理程序, AddOpenIdConnect 配置 OpenID Connect 协议执行. Authority受信 token 地址。 ClientId 和 ClientSecret. 用来标识客户。SaveTokens 用于将来自 IdentityServer 的令牌保存在 cookie 中(因为稍后将需要它们)。再添加以下代码,
app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

让以上设置生效。接下来,我们再改造一下我们的新站点,给它增加一些功能。打开HOMECONTROLLER,添加方法:


        public IActionResult Logout()
        {
            return SignOut("Cookies", "oidc");
        }
        [Authorize]
        public IActionResult Whoami()
        {
            return View();
        }
WHOAMI VIEW页面



@using Microsoft.AspNetCore.Authentication
<h2>Claims</h2>

<dl>
    @foreach (var claim in User.Claims)
    {
        <dt>@claim.Type</dt>
        <dd>@claim.Value</dd>
    }
</dl>

<h2>Properties</h2>

<dl>
    @foreach (var prop in (await Context.AuthenticateAsync()).Properties.Items)
    {
        <dt>@prop.Key</dt>
        <dd>@prop.Value</dd>
    }
</dl>
再改造一下模块布局页,加上相应的链接,运行一下,如下图



这时候我们不开身份认证服务器,HOME\PRIVACY均可正常访问,当我们点击WHOAMI页面时报以下错误:


An unhandled exception occurred while processing the request.

InvalidOperationException: IDX20803: Unable to obtain configuration from: 'System.String'.

Microsoft.IdentityModel.Protocols.ConfigurationManager<T>.GetConfigurationAsync(CancellationToken cancel)



接下来我们对IDS4SERVER服务器做一些配置

添加对 OpenID Connect 身份 scopes(范围)的支持

与 OAuth 2.0 类似,OpenID Connect 也使用 scopes(范围)概念。 同样, scopes范围代表您想要保护并且客户想要访问的东西。 与 OAuth 相比,OIDC 中的范围不代表 API,而是代表用户 ID、姓名或电子邮件地址等身份数据。

通过修改 Config.cs 中的 IdentityResources 属性,添加对标准 openid(subject id)和配置文件(first name, last name 等)范围的支持:
打开config.cs (无语的输入法...)


        public static IEnumerable<IdentityResource> IdentityResources =>
        new List<IdentityResource>
        {
            new IdentityResources.OpenId(),
            new IdentityResources.Profile(),
        };
然后打开PROGRAM.CS把上面的代码在 IdentityServer 身份资源中注册



builder.Services.AddIdentityServer()
    .AddInMemoryIdentityResources(Config.IdentityResources)
    .AddInMemoryApiScopes(Config.ApiScopes)
    .AddInMemoryClients(Config.Clients)
    .AddTestUsers(TestUsers.Users)
    .AddDeveloperSigningCredential();

注意,官网在这里漏写了最下面一条,如果是测试用,会报错,用我上面的代码。标准scopes \claims 的申明,大家可以参考这个链接 :All standard scopes and their corresponding claims can be found in the OpenID Connect specification

添加测试用户:

  官方说:示例 UI 带有一个内存中的“用户数据库”。 您可以通过添加 AddTestUsers 扩展方法在 IdentityServer 中启用此功能:AddTestUsers(TestUsers.Users)

我们打开TestUsers.Users

可以看到有alice\bob两个用户。注意一下他们的一些NAME/FAMILYNAME等字段信息,后面会用到。

将客户端标识注册IdentityServer 服务中:

最后一步是将 MVC 客户端的新配置条目添加到 IdentityServer。

基于 OpenID Connect 的客户端与我们目前添加的 OAuth 2.0 客户端非常相似。 但由于 OIDC 中的流程始终是交互式的,因此我们需要在配置中添加一些重定向 URL。

public static IEnumerable<Client> Clients =>
    new List<Client>
    {
        // machine to machine client (from quickstart 1)
        new Client
        {
            ClientId = "client",
            ClientSecrets = { new Secret("secret".Sha256()) },

            AllowedGrantTypes = GrantTypes.ClientCredentials,
            // scopes that client has access to
            AllowedScopes = { "api1" }
        },
        // interactive ASP.NET Core MVC client
        new Client
        {
            ClientId = "mvc",
            ClientSecrets = { new Secret("secret".Sha256()) },

            AllowedGrantTypes = GrantTypes.Code,

            // where to redirect to after login
            RedirectUris = { "https://localhost:5002/signin-oidc" },

            // where to redirect to after logout
            PostLogoutRedirectUris = { "https://localhost:5002/signout-callback-oidc" },

            AllowedScopes = new List<string>
            {
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Profile
            }
        }
    };
OK,大功告成!不出意外的话,我们的服务器已经搭建好了。我们把它运行起来,然后把我们新建的MYMVC站点也运行起来,再去点击WHOAMI页面试试,发现被导航到了认证服务器登录页面,注意看后面的端口后5002变成5001了,这是两个不同的站点。


我们用ALICE:ALICE(小写,该死的输入法!)登录,成功以后又返回到我们的新站点,注意看前后端口号的变化

这时候还要注意一个细节,我让大家在前面注意的那些NAME之类的字段并没有成功返回。我们打开MYMVC的PROGRAM.CS,改动代码如下:

    .AddOpenIdConnect("oidc", options =>  //AddOpenIdConnect is used to configure the handler that performs the OpenID Connect protocol.
    {
        options.Authority = "https://localhost:5001"; //The Authority indicates where the trusted token service is located.

        options.ClientId = "mvc";  //We then identify this client via the ClientId and the ClientSecret
        options.ClientSecret = "secret";
        options.ResponseType = "code";

        options.SaveTokens = true; //SaveTokens is used to persist the tokens from IdentityServer in the cookie (as they will be needed later).

        // ... 让服务器返回profile identity scop,如名称,网站,家庭等
        options.Scope.Add("profile");
        options.GetClaimsFromUserInfoEndpoint = true;
        // ...
    });
然后登出重新请求试试,字段成功返回了。大家自己测试,我就不配图了。

写一个控制器Alice,只允许Alice一个人访问,其他用户拒绝,该如何实现呢?方法:注册一个安全策略,

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("Alice", policy => policy.RequireClaim("name", "Alice Smith"));
});

var app = builder.Build();
控制器

[Authorize(Policy = "Alice")]
        public IActionResult Alice()
        {
            return View();
        }

进一步的实验


随意向测试用户添加更多声明 - 以及更多身份资源。
定义身份资源的过程如下:
将新的身份资源添加到列表中 - 为其命名并指定在请求此资源时应返回哪些声明
通过客户端配置上的 AllowedScopes 属性授予客户端对资源的访问权限
通过将资源添加到客户端中 OpenID Connect 处理程序配置上的 Scopes 集合来请求资源
(可选)如果身份资源与非标准声明(例如 myclaim1)相关联,则在客户端添加出现在 JSON 中的声明(从 UserInfo 端点返回)和用户声明之间的 ClaimAction 映射
使用 Microsoft.AspNetCore.Authentication
// ...
.AddOpenIdConnect("oidc", options=>
{
    // ...
    options.ClaimActions.MapUniqueJsonKey("myclaim1", "myclaim1");
    // ...
});
还值得注意的是,令牌声明的检索是一个可扩展点 - IProfileService。由于我们使用的是 AddTestUsers,因此默认使用 TestUserProfileService。您可以在此处检查源代码以了解其工作原理。

mymvc源码下载        IDS4Server.rar

原创文章,创作不易,转载请注明出处https://www.qhwins.com/article-30



下拉加载更多评论
最新评论
暂无!