ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

IdentityServer4+.net core+Docker认证授权和单点登录

2022-05-31 02:02:02  阅读:124  来源: 互联网

标签:core 登录 +. public new IdentityServer net options 客户端


操作环境:Centos7.8+.net Core3.1+Docker

由于IdentityServer4的认证授权功能太过强大和复杂,实现了OAuth2.0的四种授权模式——隐式模式(implicit)、授权码模式(Authorization Code)、密码凭证模式(Resource Owner Password Credentials)、客户端凭证模式(Client Credentials),本文仅以其中的客户端凭证模式和隐式模式,实现两种不同场景作为示例,供大家参考学习。

一、客户端凭证模式——实现接口资源认证授权

示例场景:Web应用(MVC)请求微服务接口资源(WebAPI)需要通过idetityserver认证中心授权(采用客户端凭证模式实现)

项目整体结构:

1、认证中心IdentityServer项目

使用Nuget引入IdentityServer4组件

创建Config配置类

using IdentityServer4;
using IdentityServer4.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace HPM.IdentityServer4
{
    public class Config
    {
        /// <summary>
        /// 获取自定义API资源列表
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<ApiResource> GetApiResources()
        {
            List<ApiResource> apiResources = new List<ApiResource>();
            apiResources.Add(new ApiResource() { Name = "ProductMicroService", DisplayName = "产品微服务",Scopes = { "ProductMicroService" } });//定义资源名称
            apiResources.Add(new ApiResource() { Name = "UserMicroService", DisplayName = "用户微服务", Scopes = { "UserMicroService" } });//定义资源名称

            return apiResources;
        }

        /// <summary>
        /// 获取自定义客户端配置列表
        /// 支持 授权码,隐藏式,密码式,凭证式、混合式
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<Client> GetClients()
        {
            List<Client> clients = new List<Client>();

            //客户端凭证授权模式(用于客户端访问微服务API资源授权认证)
            clients.Add(new Client()
            {
                ClientId="client",//定义客户端获取Token时指定的client_id值
                AllowedGrantTypes=GrantTypes.ClientCredentials,//指定grant_type为client_credentials客户端授权模式
                ClientSecrets = {new Secret("Secret".Sha256())},//定义客户端获取token时指定的client_secret值
                AllowOfflineAccess = true,//如果要获取refresh_tokens ,必须把AllowOfflineAccess设置为true
                AccessTokenLifetime = 3600,//token有效期,默认3600秒
                AllowedScopes = { "ProductMicroService", "UserMicroService" }//设置可访问范围的资源名称
            });return clients;
        }

        /// <summary>
        /// 获取IdentityServer4自身API资源列表
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<IdentityResource> GetIdentityResources()
        {
            return new List<IdentityResource> { new IdentityResources.OpenId(), new IdentityResources.Profile() };
        }

        public static IEnumerable<ApiScope> GetApiScopes()
        {
            return new List<ApiScope> { new ApiScope("ProductMicroService"), new ApiScope("UserMicroService") };
        }

    }
}

修改StartUp类

在ConfigureServices方法中添加IdentityServer的依赖注入

services.AddIdentityServer().AddDeveloperSigningCredential()
                .AddInMemoryIdentityResources(Config.GetIdentityResources())
                .AddInMemoryApiScopes(Config.GetApiScopes())
                .AddInMemoryApiResources(Config.GetApiResources())
                .AddInMemoryClients(Config.GetClients());

在Configure方法中启用IdentityServer中间件及认证授权

// 配置管道中间件
        // 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();
            }

            //暂时禁用Https
            //app.UseHttpsRedirection();

            app.UseStaticFiles();

            app.UseRouting();

            //身份认证中间件(身份验证必须在授权的前面)
            app.UseAuthentication();

            //授权中间件
            app.UseAuthorization();

            //这个必须在UseRouting和UseEndpoints中间。如果IdentityServer服务端和API端要写在一起,
            //那么这个必须在UseAuthorization和UseAuthentication的上面。
            //通过访问https://localhost:端口/.well-known/openid-configuration默认配置地址可以查看IdentityServer提供的endpoint
            app.UseIdentityServer();//使用IdentityServer中间件

            app.UseEndpoints(endpoints =>
            {
                //endpoints.MapControllers();
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }

2、微服务ProductMicroService接口资源项目(其他微服务同样调整)

修改StartUp类

在ConfigureServices方法中添加IdentityServer的认证授权依赖注入

//指定使用IdentityServer作为API资源的授权模式
            services.AddAuthentication("Bearer").AddIdentityServerAuthentication(options => {
                options.Authority = "https://www.aaa.vip:5050";//设置IdentityServer授权端口地址
                options.ApiName = "ProductMicroService";//设置要开放访问的资源名称
                options.RequireHttpsMetadata = false;
            });

在Configure方法中启用认证授权中间件

            //身份验证中间件 (身份验证必须在授权的前面)
            app.UseAuthentication();

            //授权验证中间件
            app.UseAuthorization();   

然后在需要通过授权验证才能访问的API加上[Authorize]特性保护起来

3、Web应用客户端项目

Web客户端应用想要请求到微服务中带有[Authorize]特性标识的API资源,则必须在请求的同时,提供IdentityServer认证中心颁发的令牌,因此最好封装一个获取Token令牌的方法,如下

public async Task<string> GetAccessToken(string client_id,string client_secret,string scope)
        {
            //获取Redis中缓存的Token
            string accessToken = _redisService.GetTokenValue(scope);
            //string accessToken = _redisService.GetValue(scope + "_access_token");
            if (string.IsNullOrEmpty(accessToken))
            {
                //重新从Identityserver中获取token
                var tokenClient = new HttpClient();
                var tokenResponse = await tokenClient.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
                {
                    Address = "https://www.aaa.vip:5100" + "/connect/token",

                    ClientId = client_id,
                    ClientSecret = client_secret,
                    Scope = scope
                });

                accessToken = tokenResponse.AccessToken;
                //设置redis中的token字符串600秒过期
                _redisService.SetTokenValue(scope, accessToken);
                //_redisService.SetValue(scope + "_access_token", accessToken, 600);
            }
            

            ////获取Refresh_Token
            //tokenResponse = await tokenClient.RequestRefreshTokenAsync(new RefreshTokenRequest
            //{
            //    Address = identityServerUrl + "connect/token",

            //    ClientId = client_id,
            //    ClientSecret = client_secret,
            //    Scope = scope
            //});

            return accessToken;
        }

其中client_id、client_secret、scope参数分别是IdentityServer项目中配置类Config中定义的Client客户端信息,讲这些客户端ID和密钥信息保持一致传入即可获取AccessToken授权令牌。

然后在请求微服务接口资源时,将令牌带入请求头部即可,如下

 

 

二、隐式模式——实现单点登录

首先要想使用IdentityServer实现单点登录,必须要满足一个条件,那就是应用站点和认证站点必须是HTTPS,重要的事情说三遍,必须是HTTPS!必须是HTTPS!必须是HTTPS!否则登录认证回调环节会有问题,过不去。

至于怎么搭建.net core的HTTPS站点,我在之后其他的文章中会讲解,并不复杂,主要是要花钱,没有氪金心理准备的就别玩IdentityServer的单点登录了。

示例场景:多个Web应用(mvc)通过请求IdentityServer认证中心实现单点登录(本文暂时仅以单个客户端应用进行演示)

项目整体结构:

1、认证中心IdentityServer项目

使用Nuget引入IdentityServer4组件

创建Config配置类

using IdentityServer4;
using IdentityServer4.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace HPM.IdentityServer4
{
    public class Config
    {

        /// <summary>
        /// 获取自定义客户端配置列表
        /// 支持 授权码,隐藏式,密码式,凭证式、混合式
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<Client> GetClients()
        {
            List<Client> clients = new List<Client>();

            //隐藏式授权模式(用于多客户端单点登录)
            clients.Add(new Client()
            {
                ClientId = "hpm_mvc_imp",
                ClientName = "hpm",
                AllowedGrantTypes = GrantTypes.Implicit,
                //设置是否显示授权提示界面
                //RequireConsent=true,

                //指定允许令牌或授权码返回的地址(URL)-登录成功后重定向地址
                //RedirectUris = { "http://www.b.net:5001/signin-oidc", "http://www.a.cn:5002/signin-oidc" },
                RedirectUris = { "https://www.aaa.vip:5050/signin-oidc" },
                //指定允许注销后返回的地址(URL),这里写两个客户端-注销成功后的重定向地址
                //PostLogoutRedirectUris = { "http://www.b.net:5001/signout-callback-oidc", "http://www.a.cn:5002/signout-callback-oidc" },
                PostLogoutRedirectUris = { "https://www.aaa.vip:5050/signout-callback-oidc" },
                ClientSecrets = { new Secret("SSOSecret".Sha256()) },
                AllowedScopes = new List<string>
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                    }
            });

            return clients;
        }

        /// <summary>
        /// 获取IdentityServer4自身API资源列表
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<IdentityResource> GetIdentityResources()
        {
            return new List<IdentityResource> { new IdentityResources.OpenId(), new IdentityResources.Profile() };
        }


    }
}

修改StartUp类

在ConfigureServices方法中添加IdentityServer的依赖注入

#region 添加IdentityServer单点登录依赖注入,要使用IdentityServer的单点登录,则必须启用https
            //我们使用的IdentityModel这个组件,它默认限制了当 Ids4 非localhost地址时,必须启用HTTPS。详情见https://ask.csdn.net/questions/753220
            //同时谷歌浏览器,对于cookies的写入,也必须要求https
            services.AddIdentityServer(options =>
            {
                //可以通过此设置来指定登录路径,默认的登陆路径是/account/login
                options.UserInteraction.LoginUrl = "/Account/Login";//【必备】登录地址  
                options.UserInteraction.LogoutUrl = "/Account/Logout";//【必备】退出地址 
                //options.UserInteraction.ConsentUrl = "/Account/Consent";//【必备】允许授权同意页面地址
                //options.UserInteraction.ErrorUrl = "/Account/Error";//【必备】错误页面地址
                options.UserInteraction.LoginReturnUrlParameter = "ReturnUrl";//【必备】设置传递给登录页面的返回URL参数的名称。默认为returnUrl 
                options.UserInteraction.LogoutIdParameter = "logoutId"; //【必备】设置传递给注销页面的注销消息ID参数的名称。缺省为logoutId 
                //options.UserInteraction.ConsentReturnUrlParameter = "ReturnUrl"; //【必备】设置传递给同意页面的返回URL参数的名称。默认为returnUrl
                //options.UserInteraction.ErrorIdParameter = "errorId"; //【必备】设置传递给错误页面的错误消息ID参数的名称。缺省为errorId
                //options.UserInteraction.CustomRedirectReturnUrlParameter = "ReturnUrl"; //【必备】设置从授权端点传递给自定义重定向的返回URL参数的名称。默认为returnUrl
                //options.UserInteraction.CookieMessageThreshold = 5; //【必备】由于浏览器对Cookie的大小有限制,设置Cookies数量的限制,有效的保证了浏览器打开多个选项卡,一旦超出了Cookies限制就会清除以前的Cookies值

            }).AddDeveloperSigningCredential()
                .AddInMemoryIdentityResources(Config.GetIdentityResources())
                .AddInMemoryClients(Config.GetClients());

            services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
  .AddCookie(options =>
  { // all your options
      options.Cookie.HttpOnly = false;
      // in dev
      options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
      //options.Cookie.SecurePolicy = CookieSecurePolicy.None;
      //谷歌浏览器对SameSite有安全要求,否则无法写入Cookie,详情见https://stackoverflow.com/questions/51912757/identity-server-is-keep-showing-showing-login-user-is-not-authenticated-in-c
      //options.Cookie.SameSite = SameSiteMode.None;
      options.Cookie.SameSite = SameSiteMode.Lax;
  });

            #endregion

在Configure方法中启用IdentityServer中间件及认证授权

// 配置管道中间件
        // 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();
            }

            //暂时禁用Https
            //app.UseHttpsRedirection();

            app.UseStaticFiles();

            app.UseRouting();

            //身份认证中间件(身份验证必须在授权的前面)
            app.UseAuthentication();

            //授权中间件
            app.UseAuthorization();

            //这个必须在UseRouting和UseEndpoints中间。如果IdentityServer服务端和API端要写在一起,
            //那么这个必须在UseAuthorization和UseAuthentication的上面。
            //通过访问https://localhost:端口/.well-known/openid-configuration默认配置地址可以查看IdentityServer提供的endpoint
            app.UseIdentityServer();//使用IdentityServer中间件

            app.UseEndpoints(endpoints =>
            {
                //endpoints.MapControllers();
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }

创建登录及注销控制器,其中/Account/Login和/Account/Logout分别是StartUp的ConfigureServices中给IdentityServer设定好的登入和登出时自动回调的地址(即MVC里的Action)。这2个地址(Action)非常重要。除此之外,一般还会有一个处理登录信息提交的Action,也很重要。由于太过重要,我就直接将整段代码贴出来

public class AccountController : Controller
    {
        private readonly IIdentityServerInteractionService _interaction;
        private readonly IUserServiceClient _userServiceClient;//自定义用户信息服务

        public AccountController(IIdentityServerInteractionService interaction, IUserServiceClient userServiceClient)
        {
            this._interaction = interaction;
            this._userServiceClient = userServiceClient;
        }

        /// <summary>
        /// 登录页加载
        /// 登录时IdentityServer自动跳转到此登录页
        /// </summary>
        /// <param name="ReturnUrl"></param>
        /// <returns></returns>
        public IActionResult Login(string ReturnUrl)
        {
            if (HttpContext.User.Identity.IsAuthenticated)
            {
                return Redirect(ReturnUrl);
            }
            LoginInputViewModel vm = new LoginInputViewModel()
            {
                ReturnUrl = ReturnUrl
            };
            return View(vm);
        }

        /// <summary>
        /// 提交登录信息操作
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> Login(LoginInputViewModel model)
        {
            //当登录提交给后台的model为null,则返回错误信息给前台
            if (model == null)
            {
                ViewData["TipMessage"] = "登录失败,数据为空!";
                return View(model);
            }
            //这里同理,当信息不完整的时候,返回错误信息给前台
            if (string.IsNullOrEmpty(model.Username) || string.IsNullOrEmpty(model.Password))
            {
                //这里只是简单处理了
                ViewData["TipMessage"] = "登录失败,用户名和密码不能为空!";
                return View(model);
            }

            //自定义的方法获取数据库信息验证用户名和密码
            BaseResultModel<UserInfoForLoginDto> loginResult = await _userServiceClient.GetLoginUserInfo(model.Username, model.Password);
            if (loginResult.success)
            {
                //登录用户信息
                UserInfoForLoginDto loginUserInfo = loginResult.data;

                //配置Cookie
                AuthenticationProperties properties = new AuthenticationProperties()
                {
                    IsPersistent = true,
                    ExpiresUtc = DateTimeOffset.UtcNow.Add(TimeSpan.FromMinutes(30))
                    //ExpiresUtc = DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration) //记住登录
                };

                //使用IdentityServerUser来进行SignInAsync
                // issue authentication cookie with subject ID and username
                var isuser = new IdentityServerUser(loginUserInfo.Id.ToString())
                {
                    DisplayName = loginUserInfo.UserName
                };
                await HttpContext.SignInAsync(isuser, properties);

                //使用IIdentityServerInteractionService的IsValidReturnUrl来验证ReturnUrl是否有问题
                if (_interaction.IsValidReturnUrl(model.ReturnUrl))
                {
                    return Redirect(model.ReturnUrl);
                }
                else
                {
                    ViewData["TipMessage"] = "跳转地址有误:" + model.ReturnUrl;
                    return View(model);
                }
            }
            else
            {
                //return Content("<script >alert('"+ loginResult.message + "');</script>", "text/html");
                ViewData["TipMessage"] = loginResult.message;
                return View(model);
            }

            return View();
        }

        /// <summary>
        /// 登录注销
        /// 注销登录时IdentityServer会自动回调此路径
        /// </summary>
        /// <param name="logoutId"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<IActionResult> Logout(string logoutId)
        {
            //var logoutId = await _interaction.CreateLogoutContextAsync();
            Console.WriteLine("准备注销登录,logoutId为:" + logoutId);
            var logout= await _interaction.GetLogoutContextAsync(logoutId);
            await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
            if (logout.PostLogoutRedirectUri != null)
            {
                Console.WriteLine("注销登录,跳转PostLogoutRedirectUri地址:" + logout.PostLogoutRedirectUri);
                return Redirect(logout.PostLogoutRedirectUri);
            }
            var refererUrl = Request.Headers["Referer"].ToString();
            return Redirect(refererUrl);
        }

    }

这其中登录Login的ReturnUrl参数,以及注销Logout的logoutId参数,可以不用管,因为它们是IdentityServer回调地址,IdentityServer会自动带上这2个参数跳转到这2个地址。

至于是从何处触发的IdentityServer回调跳转?当然是在客户端Web应用的控制器中触发,下面会慢慢讲到。

为了便于大家理解,这里我将登录页、登录页的视图模型类ViewModel也一并贴出来

    /// <summary>
    /// 登录页的视图模型
    /// </summary>
    public class LoginInputViewModel
    {
        [Required]
        public string Username { get; set; }
        [Required]
        public string Password { get; set; }
        public bool RememberLogin { get; set; }
        public string ReturnUrl { get; set; }
    }
            <div class="login_con">
                <h1>登录/LOGIN</h1>
                @using (Html.BeginForm("Login", "Account"))
                {
                    <div class="text_box">
                        <div>
                            <input type="hidden" name="ReturnUrl" value="@Model.ReturnUrl" />
                            <div><i><img src="/login/images/icon01.png"></i><input id="name" type="text" name="Username" placeholder="请输入注册邮箱"></div>
                            <div><i><img src="/login/images/icon02.png"></i><input id="pwd" type="password" name="Password" placeholder="请输入密码"></div>
                            <button type="submit">登 录</button>
                        </div>
                    </div>
                }

            </div>

 

2、Web应用客户端项目

修改StartUp类

在ConfigureServices方法中添加IdentityServer的依赖注入

//注入IdentityServer单点登录授权认证
            //DefaultChallengeScheme的名字要和下面AddOpenIdConnect方法第一个参数名字保持一致
            services.AddAuthentication(options =>
            {
                options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;//默认的身份验证方案名
                options.DefaultChallengeScheme = "oidc";//用来跳转到ids登录页的身份验证方案名
                //注意这俩配置与下面注册的身份验证方案的名字对应
            })
           .AddCookie(options =>
           {
               options.ExpireTimeSpan = TimeSpan.FromMinutes(60);
               options.Cookie.Name = CookieAuthenticationDefaults.AuthenticationScheme;//注册asp.net core 默认的基于cookie的身份验证方案
           })
           .AddOpenIdConnect("oidc", options =>//注册ids为我们提供的oidc身份验证方案
           {
               options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
               options.Authority = "https://www.aaa.vip:5100";
               options.RequireHttpsMetadata = false;

               //指定允许服务端返回的地址,默认是new PathString("/signin-oidc")
               //如果这里地址进行了自定义,那么服务端也要进行修改
               //options.CallbackPath = new PathString("/signin-oidc");

               //指定用户注销后,服务端可以调用客户端注销的地址,默认是new PathString("signout-callback-oidc")
               //options.SignedOutCallbackPath = new PathString("/signout-callback-oidc");

               options.ClientId = "hpm_mvc_imp";
               options.ClientSecret = "SSOSecret";
               //options.ResponseType = "code id_token";//授权模式
               options.SaveTokens = true;//是否将最后获取的idToken和accessToken存储到默认身份验证方案中

               //布尔值来设置处理程序是否应该转到用户信息端点检索。额外索赔或不在id_token创建一个身份收到令牌端点。默认为“false”
               //options.GetClaimsFromUserInfoEndpoint = true;

               //事件
               options.Events = new Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectEvents()
               {
                   //远程故障
                   OnRemoteFailure = context =>
                   {
                       context.Response.Redirect("/SSO/Error");
                       context.HandleResponse();
                       return Task.FromResult(0);
                   },
                   //访问拒绝
                   OnAccessDenied = context =>
                   {
                       //重定向到指定页面
                       context.Response.Redirect("/SSO/Denied");
                       //停止此请求的所有处理并返回给客户端
                       context.HandleResponse();
                       return Task.FromResult(0);
                   },
               };
           });

在Configure方法中启用认证授权中间件及Cookie策略中间件

            //使用Cookie
            app.UseCookiePolicy(new CookiePolicyOptions { MinimumSameSitePolicy = SameSiteMode.Lax });

            app.UseRouting();

            //身份认证中间件(身份验证必须在授权的前面)
            app.UseAuthentication();

            app.UseAuthorization();

接着,在任何需要登录验证的Action操作上,添加[Authorize]特性标识,则未登录状态下系统会触发认证,自动跳转到identityServer项目的登录页/Account/Login并带上相应ReturnUrl参数,如下

如果不想这样被动的触发登录跳转,想要实现主动点击【登录】按钮跳转到登录页,可以创建一个用户控制器,将登录和注销功能都写在里面,其中登录Action带上[Authorize]特性标识,这样就能巧妙实现触发登录页跳转。

    public class UserController : Controller
    {/// <summary>
        /// 登录
        /// </summary>
        /// <param name="pageUrl"></param>
        /// <returns></returns>
        [Authorize]
        public IActionResult Login(string pageUrl=null)
        {
            //在认证中心登录页登录后,回到此处再跳转到其他页面
            if(pageUrl == null)
            {
                return RedirectToAction("Index", "Home");
            }
            else
            {
                return Redirect(pageUrl);
            }
        }

        /// <summary>
        /// 注销登录
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public IActionResult Logout()
        {
            //this.HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
            //this.HttpContext.SignOutAsync("oidc");
            //return RedirectToAction("Index", "Home");

            //这里会触发identityServer对/Account/Logout的回调,并带上logoutId参数
            return SignOut("Cookies", "oidc");
        }

    }

客户端主动触发登录注销操作的位置

                @if (string.IsNullOrEmpty(Model.UserName))
                {
                    <div id="loginBox">
                        <a style="cursor: pointer;" href="/User/Login">登录</a><span> | </span><a style="cursor: pointer;" href="login/register.html">注册</a>
                    </div>
                }
                else
                {
                    <span>Hi @Model.UserName 欢迎回来~<br /><a style="cursor: pointer;" href="/User/Logout">退出登录</a></span>
                }

当在IdentityServer认证中心的登录页登录成功后,会自动跳转回Web客户端项目,这时客户端需要获取登录后的用户信息,获取方式如下:

            if(HttpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.NameIdentifier)!=null)
            {
                //Type:http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier Value:1
                viewModel.UserId = Convert.ToInt32(HttpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.NameIdentifier).Value);//获取用户ID
                //Type:name Value:一人之下
                viewModel.UserName = HttpContext.User.Claims.SingleOrDefault(s => s.Type == "name").Value;//获取用户姓名
            }     

直接在客户端的控制器中获取即可,这里由于我在登录时设定的IdentityServerUser参数Type是这2个,所以就用这2个Type来获取对应的信息,实际开发过程中大家可以根据自己的需要去设置,不一定要按照我的Type来取。

 

至此,费了我九牛二虎之力,苦心钻研一周的IdentityServer单点登录算是讲完了,最后还是要提醒大家一句,玩IdentityServer单点登录的前提是,你的站点必须是HTTPS!!!

本人虽然在钻研过程中参考了不少资料,但此文基本也算是原创,麻烦大家转载时注明出处,祝各位工作顺利,少死脑细胞。

 

标签:core,登录,+.,public,new,IdentityServer,net,options,客户端
来源: https://www.cnblogs.com/mooncher/p/16328987.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有