IdentityServer4 实现单点登录

服务端

    public class Config
    {

        /// <summary>
        /// IDS资源
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<IdentityResource> GetIds()
        {
            return new List<IdentityResource>
            {
                new IdentityResources.OpenId(),
                new IdentityResources.Profile(),
            };
        }

        public static IEnumerable<ApiResource> GetApiResources()
        {
            return new List<ApiResource>
            {
                new ApiResource("UserCenter", "UserCenter API")
            };
        }

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

        /// <summary>
        /// 可以使用ID4 Server 客户端资源
        /// </summary>
        /// <returns></returns>
        public static IEnumerable<Client> GetClients()
        {
            List<Client> clients = new List<Client>() {
                ////授权码模式
                //new Client
                //{
                //    ClientId = "client1",
                //    ClientSecrets = { new Secret("123456".Sha256()) },
                //    //授权码模式
                //    AllowedGrantTypes = GrantTypes.Code,
                //    //需要确认授权
                //    RequireConsent = true,
                //    RequirePkce = true,
                //    //允许token通过浏览器
                //    AllowAccessTokensViaBrowser=true,               
                //    // where to redirect to after login(登录)
                //    RedirectUris = { "https://localhost:7072/signin-oidc" },
                //    // where to redirect to after logout(退出)
                //    PostLogoutRedirectUris = { "https://localhost:7072/signout-callback-oidc" },
                //    //允许的范围
                //    AllowedScopes = new List<string>
                //    {
                //        IdentityServerConstants.StandardScopes.OpenId,
                //        IdentityServerConstants.StandardScopes.Profile,
                //        "UserCenter"
                //    },
                //    AlwaysIncludeUserClaimsInIdToken=true
                //},
                new Client
                {
                    ClientId = "client2",
                    ClientSecrets = { new Secret("123456".Sha256()) },
                    //混合与客户端模式
                    AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
                    //需要确认授权
                    RequireConsent = true,
                    RequirePkce = false,
                    //允许token通过浏览器
                    AllowAccessTokensViaBrowser=true,               
                    // where to redirect to after login(登录)
                    RedirectUris = { "https://localhost:7072/signin-oidc" },
                    // where to redirect to after logout(退出)
                    PostLogoutRedirectUris = { "https://localhost:7072/signout-callback-oidc" },
                    AccessTokenLifetime = 3600,//Token 过期时间
                    //AccessTokenType= AccessTokenType.Jwt,
                    AlwaysIncludeUserClaimsInIdToken = true,//将用户所有的claims包含在IdToken内
                    //AbsoluteRefreshTokenLifetime = 2592000,//RefreshToken的最长生命周期,默认30天
                    //RefreshTokenExpiration = TokenExpiration.Sliding,//刷新令牌时,将刷新RefreshToken的生命周期。RefreshToken的总生命周期不会超过AbsoluteRefreshTokenLifetime。
                    //SlidingRefreshTokenLifetime = 3600,//以秒为单位滑动刷新令牌的生命周期。
                    AllowOfflineAccess = true,//如果要获取refresh_tokens ,必须把AllowOfflineAccess设置为true  
                    //允许的范围
                    AllowedScopes = new List<string>
                    {
                        //"UserCenter",
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile
                        
                    },
                }
            };
            return clients;
        }

        /// <summary>
        /// 定义可以使用ID4的用户资源
        /// </summary>
        /// <returns></returns>
        public static List<TestUser> GetUsers()
        {
            return new List<TestUser>()
            {
                new TestUser
                {
                        SubjectId = "001",
                        Username = "ypf1",    //账号
                        Password = "1",  //密码
                        Claims =
                        {
                            new Claim(JwtClaimTypes.Name, "Alice Smith"),
                            new Claim(JwtClaimTypes.Email, "AliceSmith@email.com"),
                        }
                 },
                 new TestUser
                 {
                        SubjectId = "002",
                        Username = "ypf2",
                        Password = "1",
                        Claims =
                        {
                            new Claim(JwtClaimTypes.Name, "Bob Smith"),
                            new Claim(JwtClaimTypes.Email, "BobSmith@email.com"),
                        }
                  }
            };
        }
    }

  Startup 代码

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();

            //注册IDS4信息(授权码模式)
            services.AddIdentityServer(options=> {
                options.Authentication.CookieAuthenticationScheme = CookieAuthenticationDefaults.AuthenticationScheme;            
            })
            .AddDeveloperSigningCredential()
            .AddInMemoryIdentityResources(Config.GetIds())
            .AddInMemoryClients(Config.GetClients())
            .AddInMemoryApiResources(Config.GetApiResources())
            .AddInMemoryApiScopes(Config.GetApiScopes())
            .AddTestUsers(Config.GetUsers());

            services
                .AddAuthentication(options=> {
//默认为Cookie 同时支持Jwt options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme) .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => { // IdentityServer4 地址 options.Authority = "http://localhost:7071"; options.RequireHttpsMetadata = false; options.TokenValidationParameters = new TokenValidationParameters() { ValidateIssuer = false,//是否验证Issuer ValidateAudience = false,//是否验证Audience ValidateLifetime = true,//是否验证失效时间 ValidateIssuerSigningKey = false,//是否验证SecurityKey //ValidAudience = "UserCenter",//Audience //ValidIssuer = "yourdomain.com",//Issuer,这两项和前面签发jwt的设置一致 //ValidAudiences = new List<string>() { "client2" }//, "api1" }; }); } // 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(); } 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.UseRouting(); //启用IDS4 app.UseIdentityServer(); app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); }); }

 api 使用jwt验证

    [Route("api/[controller]/[action]")]
    [ApiController]
    [Authorize(AuthenticationSchemes=JwtBearerDefaults.AuthenticationScheme)]//(JwtBearerDefaults.AuthenticationScheme)
    public class DemoController : ControllerBase
    {
        [Authorize]
        public JsonResult Index()
        {
            //string str = OpenIdConnectParameterNames.RefreshToken;

            string accessToken = HttpContext.GetTokenAsync("access_token").Result;
            string idToken = HttpContext.GetTokenAsync("id_token").Result;
            var refreshToken = HttpContext.GetTokenAsync("refresh_token").Result;

            var claimsList = from c in User.Claims select new { c.Type, c.Value };


            return new JsonResult(new
            {
                data = new
                {
                    accessToken,
                    idToken,
                    refreshToken,
                    claimsList
                }
            });
        }
    }

 同时服务端需要下载IdentityServer4.Quickstart.UI 代码 (github上有)

以下3个文件复制到你的服务端项目中

 

 

客户端

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.AddControllersWithViews();

            JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
            //添加Cookie认证
            services.AddAuthentication(options =>
            {
                options.DefaultScheme = "Cookies";
                options.DefaultChallengeScheme = "oidc";
            })
            .AddCookie("Cookies")
            //通过OIDC协议远程请求认证
            .AddOpenIdConnect("oidc", options =>
            {
                options.Authority = "http://localhost:7071";   //认证授权服务器地址

                #region 授权码模式
                //options.RequireHttpsMetadata = false;
                //options.ClientId = "client1";    //客户端ID
                //options.ClientSecret = "123456"; //客户端秘钥
                ////授权码模式
                //options.ResponseType = OpenIdConnectResponseType.Code;
                //options.ResponseMode = OpenIdConnectResponseMode.Query;
                //options.SaveTokens = true; 
                #endregion

                #region 混合客户端模式
                options.RequireHttpsMetadata = false;
                options.ClientId = "client2";    //客户端ID
                options.ClientSecret = "123456"; //客户端秘钥
                //混合客户端模式
                options.ResponseType = OpenIdConnectResponseType.CodeIdTokenToken;
                //options.ResponseMode = OpenIdConnectResponseMode.Query;
                options.SaveTokens = true;
                #endregion
            });
        }

        // 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();
            }
            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.UseRouting();

            //开启认证
            app.UseAuthentication();
            //开启授权
            app.UseAuthorization();

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

  客户端api增加授权控制,在没有授权的情况下访问,客户端会跳转到服务端登录进行认证,认证通过会转回到客户端

 

这里服务端认证中心可以提供获取用户信息接口,客户端可以使用拿到的token请求认证中心的用户信息接口

posted @ 2021-01-06 15:48  在路上的白羊  阅读(517)  评论(0编辑  收藏  举报