IdentityServer客户端授权模式

Posted linhuiy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了IdentityServer客户端授权模式相关的知识,希望对你有一定的参考价值。

前言

客户端授权模,客户端直接向Identity Server申请token并访问资源。客户端授权模式比较适用于服务之间的通信。
技术图片

搭建Identity服务

新建名为 IdentityServer 的WebApi空项目,设置端口为5000,作为我们的授权认证服务。
新建名为 Api 的WebApi空项目,设置端口为5001,作为我们的Api资源。
技术图片

通过NuGet安装 IdentityServer4 或者通过程序包管理执行 Install-Package IdentityServer4 安装依赖包。

技术图片

新一个 Config 文件来定义Identity资源

using System.Collections.Generic;
using IdentityServer4;
using IdentityServer4.Models;

namespace IdentityServer
{
    public static class Config
    {
        public static IEnumerable<IdentityResource> GetIdentityResourceResources()
        {
            return new List<IdentityResource>
            {
                new IdentityResources.OpenId(), //必须要添加,否则报无效的scope错误
            };
        }
        // scopes define the API resources in your system
        public static IEnumerable<ApiResource> GetApiResources()
        {
            //api资源({资源名称}{描述})
            return new List<ApiResource>
            {
                new ApiResource("Api", "Api"),
            };
        }

        // clients want to access resources (aka scopes)
        public static IEnumerable<Client> GetClients()
        {
            return new List<Client>
            {
                new Client
                {
                    //客户端id,必须唯一
                    ClientId = "client_a",
                    //授权方式,这里采用的是客户端认证模式,只要ClientId,以及ClientSecrets正确即可访问对应的AllowedScopes里面的api资源
                    AllowedGrantTypes = GrantTypes.ClientCredentials,
                    ClientSecrets =
                    {
                        new Secret("secret".Sha256())
                    },
                    AllowedScopes =
                    {
                        "Api",
                    }
                }
            };
        }
    }
}

Startup 中配置IdentityServer

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace IdentityServer
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            //注入DI
            services.AddIdentityServer()
                 .AddDeveloperSigningCredential()
                .AddInMemoryApiResources(Config.GetApiResources())//Api资源信息
                .AddInMemoryClients(Config.GetClients());//客户端信息
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            //放入HTTP管道中
            app.UseIdentityServer();
        }
    }
}

运行当前项目,并访问 http://localhost:5000/.well-known/openid-configuration 就会看到当前IdentityServer的一些信,首次启动会创建一个名为tempkey.rsa 的文件,里面保存的是你的签名密钥。

技术图片

定义Api资源

通过NuGet安装 IdentityServer4.AccessTokenValidation 或者通过程序包管理执行 IInstall-Package IdentityServer4.AccessTokenValidation 安装依赖包。

Api 项目中新增一个ValuesController并添加一个 Print 接口 Authorize表示该接口被身份认证所保护

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace Api.Controllers
{
    [Route("api/[controller]")]
    public class ValuesController : Controller
    {
        [HttpGet("Print")]
        [Authorize]
        public ActionResult Print()
        {
            return new JsonResult("hello word");
        }
    }
}

Startup 中把身份认证服务注入DI,并放入HTTP管道。

uusing Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace Api
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            //将身份认证注入到DI
            services.AddAuthentication("Bearer")
                .AddJwtBearer("Bearer", options =>
                {
                    options.Authority = "http://localhost:5000";
                    options.RequireHttpsMetadata = false;
                    options.Audience = "Api";
                });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            //身份认证添加到HTTP管道
            app.UseAuthentication();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

测试效果

我们同时运行两个项目。这时候我们直接访问Api资源。会直接抛出401(用户没有权限访问)

技术图片

我们用配置的client向IdentityServer申请token来访问Api资源

技术图片

client_id - 我们配置的客户端id
client_secret - 签名密钥。
grant_type - 授权模式
access_token - 访问令牌
expires_in - 过去时间(秒)
token_type - 令牌类型
scope - 可以访问资源名称

使用资源访问Api资源,在Hraders中加入 authorization 传入刚申请的token(Bearer后面有一个空格)

技术图片

以上是关于IdentityServer客户端授权模式的主要内容,如果未能解决你的问题,请参考以下文章

IdentityServer4-客户端的授权模式原理分析

IdentityServer4授权模式应用场景

IdentityServer4系列 | 授权码模式

使用IdentityServer4实现一个简单的Oauth2客户端模式授权

IdentityServer4-前后端分离的授权验证

IdentityServer4-前后端分离的授权验证