zoukankan      html  css  js  c++  java
  • IdentityServer4 学习笔记(一)客户端模式

    今天跟大家分享的是第一种模式,客户端模式

    上一章我们讲过,客户端模式是跟用户无关的,只是通过获取token,得到授权,进而请求API资源而已。

    下面我们就详细讲述,如何实现客户端模式。

    在这里,我们需要新建3个项目,身份认证的服务端、Api资源站、客户端。

    以下项目均在Net Core 2.2上开发。

    一、身份认证服务端

           我们新建一个ASP.NET Core MVC项目,命名 ServerDemo

          从nuget上,引入IdentityServer4的安装包

          在根目录下,新建一个配置类 Config.cs

       public class Config
        {
            //定义身份资源
            public static IEnumerable<IdentityResource> GetIdentityResources()
            {
                return new List<IdentityResource>() {
                new IdentityResources.OpenId(),
                new IdentityResources.Profile(),
                };
            }
    
            //定义Api资源
    
            public static IEnumerable<ApiResource>GetApiResources()
            {
                return new List<ApiResource>
                {
                    new ApiResource("api1","测试Api") //定义Api站点的name和显示名称,这个name必须唯一,作为站点资源识别,在Api站点上也需要指定这个name,必须相等,表示请求这个Api站点
                };
            }
    
            //定义客户端授权类型
    
            public static IEnumerable<Client> GetClients()
            {
                return new List<Client> {
                    //第一个,客户端模式Client Credentials
                    new Client{ 
                           ClientId="CredentialsClient", //客户端Id,必须且唯一
                           AllowedGrantTypes=GrantTypes.ClientCredentials, //指定为客户端授权模式
                           ClientSecrets={ 
                        new Secret("111111".Sha256()) //自定义密码,客户端请求时,密码传参数,必须与这个密码一致
                        },
                           AllowedScopes={ "api1"}//设置允许授权请求的范围,表示这个客户端Id可请求的资源范围,若不在范围内,请求会被拒绝。
                    },
                };
            }
    
    
    
        }

    在这个配置类里面,我们定义了3个方法

    第一个是身份资源信息,因客户端模式下,与用户无关,所以这个在客户端模式下,没有也没关系,这里只是与其他模式同个项目,写一块了。

    第二个是Api资源,主要陈列API站点的name和显示名称,主要是name,必须唯一。

    第三个是客户端,陈列所有客户端标识,授权方式、密码和允许请求的资源范围。

    接下来,我们需要在Startup.cs文件中进行注入。

        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.Configure<CookiePolicyOptions>(options =>
                {
                    // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                    options.CheckConsentNeeded = context => true;
                    options.MinimumSameSitePolicy = SameSiteMode.None;
                });
    
                //配置IdentityServer4服务
                services.AddIdentityServer()
                    .AddDeveloperSigningCredential() //客户端授权时,必须增加这行,不然客户端会出现keyset missing的错误
                        .AddInMemoryApiResources(Config.GetApiResources())
                        .AddInMemoryIdentityResources(Config.GetIdentityResources())
                        .AddInMemoryClients(Config.GetClients())
                        ;
                    
    
    
    
                services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
            }
    
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IHostingEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
                else
                {
                    app.UseExceptionHandler("/Home/Error");
                    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                    app.UseHsts();
                }
    
                app.UseHttpsRedirection();
                app.UseStaticFiles();
                app.UseCookiePolicy();
                //使用IdS中间件
                app.UseIdentityServer();
    
                app.UseMvc(routes =>
                {
                    routes.MapRoute(
                        name: "default",
                        template: "{controller=Home}/{action=Index}/{id?}");
                });
            }
        }

    主要是下面2个

    //配置IdentityServer4服务
                services.AddIdentityServer()
                    .AddDeveloperSigningCredential() //客户端授权时,必须增加这行,不然客户端会出现keyset missing的错误
                        .AddInMemoryApiResources(Config.GetApiResources()) //加载定义的Api资源
                        .AddInMemoryIdentityResources(Config.GetIdentityResources())//加载定义的身份资源
                        .AddInMemoryClients(Config.GetClients())//加载定义的客户端
                        ;
       //使用IdS中间件
                app.UseIdentityServer();

    自此,我们就完成了服务端的开发。

    但有一点需要注意的是AddInMemoryApiResources是存储内存里面的,若是要自定义存储的介质,比如redis、数据库等中间件上,则可以对Memory进行重载定义,再注入即可。

    在id4的官网文档上有写,一时找不到哪个页面上,大家自己去找哈,https://identityserver4.readthedocs.io/en/latest/topics/signin.html#cookie-authentication

    同时,我们在项目中右键-属性-调试,设置身份认证服务端启动端口号为7000,这个自定义。

    二、新建API站点资源

    新建一个asp.net core WebApi项目,命名 ApiSourcce

    从Nuget上引入 IdentityServer4.AccessTokenValidation 包

    新建一个 命名为 IdentityController 的控制器,定义接口

    namespace ApiSourcce.Controllers
    {
        [Route("[controller]")] //设置路由
        [Authorize]  //身份验证,添加了这个,就会去身份认证服务端进行验证
        public class IdentityController : Controller
        {
            [HttpGet]
            public IActionResult Get()
            {
                //这里是返回当前授权通过后的一些声明信息,当然,这个信息我们也可以自定义,返回字符串类型也可以
                return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
            }
        }
    }

    这里,我们返回授权通过后,获取到的一些声明,当然这个内容可以自定义,在实际项目当中,返回的是业务需求的内容。

    第二步就是在Startup中进行服务注册

     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.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
                //
                services.AddAuthorization(); //注册授权
                services.AddAuthentication("Bearer") //采用Bearer token的接口认证方式
                    .AddIdentityServerAuthentication(option => {
                        option.ApiName = "api1"; //这里的name必须与客户端定义的Api资源中的name一致,不然请求不通过
                        option.Authority = "http://localhost:7000"; //身份认证服务端
                        option.RequireHttpsMetadata = false; //非https,设置为false
                    });
               
            }
    
            // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
            public void Configure(IApplicationBuilder app, IHostingEnvironment env)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
    
                //使用身份验证中间件
                app.UseAuthentication();
              
    
                app.UseMvc();
            }
        }

    就是添加标红的几行代码。

    设置Api资源站的端口

    这样,我们就完成了API资源站点的设置

    三、客户端

    客户端,即调用端。

    客户端通过身份认证服务端获取到token,带着token去请求API资源

    我们新建一个asp.net core mvc项目 ClientCredentials

    从nuget上引入IdentityModel包

    在Home控制器上,编写我们的测试代码

     public async Task<IActionResult> Index()
            {
                var client = new HttpClient();
    
                var disco = await client.GetDiscoveryDocumentAsync("http://localhost:7000"); //请求身份认证服务端,即Id4的服务端
    
                if (disco.IsError)
                {
                    Console.WriteLine(disco.Error);
                    return View();
                }
    
                // request token 请求获取token
                var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
                {
                    Address = disco.TokenEndpoint,
                    ClientId = "CredentialsClient", //必须与身份认证服务端定义的客户端Id一致
                    ClientSecret = "111111",//密码
                    Scope = "api1" //请求的api name,必须与身份认证服务端定义的Api name一致
                });  
    
                if (tokenResponse.IsError)
                {
                    Console.WriteLine(tokenResponse.Error);
                    return View();
                }
    
                Console.WriteLine(tokenResponse.Json);
                Console.WriteLine("
    
    ");
    
                // call api
                var apiClient = new HttpClient();
                apiClient.SetBearerToken(tokenResponse.AccessToken);
    
                var response = await apiClient.GetAsync("http://localhost:6010/identity/"); //带着token请求api资源站点
                if (!response.IsSuccessStatusCode) 
                {
                    Console.WriteLine(response.StatusCode);
                }
                else
                {
                    var content = await response.Content.ReadAsStringAsync(); //调用成功
                    Console.WriteLine(JArray.Parse(content));
                    return Content(content);
                }
                return View();
            }

    这样,我们就完成了整个客户端模式的编码工作。

    我们运行起来看看,看客户端返回了什么

    客户端收到了这个,这个就是我们Api资源 Identity控制器下接口返回的用户声明的信息。

    至此,我们就完成了客户端模式的调用。

  • 相关阅读:
    POJ1741 Tree
    BZOJ3674 可持久化并查集加强版
    BZOJ3673 可持久化并查集 by zky
    BZOJ3174 [Tjoi2013]拯救小矮人
    BZOJ2733 永无乡【splay启发式合并】
    AtCoder Grand Contest 007 E:Shik and Travel
    BZOJ2599:[IOI2011]Race
    AtCoder Regular Contest 063 E:Integers on a Tree
    SPOJ1825:Free Tour II
    AtCoder Grand Contest 012 C:Tautonym Puzzle
  • 原文地址:https://www.cnblogs.com/fei686868/p/12356046.html
Copyright © 2011-2022 走看看