zoukankan      html  css  js  c++  java
  • ASP.NET Core的身份认证框架IdentityServer4--(5)自定义用户登录(使用官网提供的UI)

    IdentityServer官方提供web页面,可以根据需求修改样式。具体UI下载跟配置参考官网文档。

    文档地址:https://identityserver4.readthedocs.io/en/release/quickstarts/3_interactive_login.html

    使用UI登录涉及的知识点参考园里大佬@solenovex的文章。这里不在重复说明,感兴趣的同学可以去看看。原文地址:https://www.cnblogs.com/cgzl/p/9253667.html

    我这里是根据官方提供的UI进行修改、自定义用户登录、访问API。

    源码地址:https://github.com/YANGKANG01/IdentityServer4-IdentityAuth

    一、配置IdentityServer

    1、引入官网包:IdentityServer4

    2、需要重新定义Web端信息,除了ClientId,AllowedGrantTypes,ClientSecrets,AllowedScopes等属性还需要配置登录成功或注销后的返回地址RedirectUrisPostLogoutRedirectUrisConfig文件配置如下:

    using IdentityServer4;
    using IdentityServer4.Models;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    
    namespace IdentityServer
    {
        /// <summary>
        /// IdentityServer配置
        /// </summary>
        public class Config
        {
            /// <summary>
            /// 添加对OpenID Connect的支持
            /// </summary>
            /// <returns></returns>
            public static IEnumerable<IdentityResource> GetIdentityResources()
            {
                return new List<IdentityResource>
                {
                    new IdentityResources.OpenId(), //必须要添加,否则报无效的scope错误
                    new IdentityResources.Profile()
                };
            }
            /// <summary>
            /// 定义系统中的API资源
            /// </summary>
            /// <returns></returns>
            public static IEnumerable<ApiResource> GetApiResources()
            {
                return new List<ApiResource>
                {
                    new ApiResource("api1", "My API")
                };
            }
    
            /// <summary>
            /// 客户端访问资源
            /// </summary>
            /// <returns></returns>
            public static IEnumerable<Client> GetClients()
            {
                // 客户端信息
                return new List<Client>
                {
                 //自定义接口登录的客户端
                 new Client
                    {
                        //客户端ID名称
                        ClientId = "client1",
                        //客户端访问方式:密码验证
                        AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
                        //用于认证的密码加密方式
                        ClientSecrets =
                        {
                            new Secret("secret".Sha256())
                        },
                        //客户端有权访问的范围
                        AllowedScopes = { "api1",
                        IdentityServerConstants.StandardScopes.OpenId, //必须要添加,否则报403 forbidden错误
                        IdentityServerConstants.StandardScopes.Profile
                     }
                    },
                    //定义mvc客户端
                    new Client
                    {
                        //客户端ID名称
                        ClientId = "mvc",
                        ClientName = "MVC Client",
                        //访问类型
                        AllowedGrantTypes = GrantTypes.Hybrid,
                        //关闭确认是否返回身份信息界面
                        RequireConsent=false,
                       // 登录成功后重定向地址
                        RedirectUris = { "http://localhost:5002/signin-oidc" },
                       //注销成功后的重定向地址
                        PostLogoutRedirectUris = { "http://localhost:5002/signout-callback-oidc" },
                         //用于认证的密码加密方式
                        ClientSecrets =
                        {
                            new Secret("secret".Sha256())
                        },
                         //客户端有权访问的范围
                        AllowedScopes = new List<string>
                        {
                            IdentityServerConstants.StandardScopes.OpenId,
                            IdentityServerConstants.StandardScopes.Profile,
                            "api1",//要访问的api名称
                        },
                    }
                };
            }
        }
    }

    3、Startup的配置跟前面自定义接口登录一样没什么变化,这里也贴下源码方便没看前篇的同学:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using IdentityServer.Service;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Http;
    using Microsoft.Extensions.DependencyInjection;
    
    namespace IdentityServer
    {
        public class Startup
        {
            // This method gets called by the runtime. Use this method to add services to the container.
            // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
            public void ConfigureServices(IServiceCollection services)
            {
                //配置身份服务器与内存中的存储,密钥,客户端和资源
                services.AddIdentityServer()
                    .AddDeveloperSigningCredential()
                    .AddInMemoryIdentityResources(Config.GetIdentityResources())//用户信息建模
                    .AddInMemoryApiResources(Config.GetApiResources())//添加api资源
                    .AddInMemoryClients(Config.GetClients())//添加客户端
                    .AddResourceOwnerValidator<LoginValidator>()//用户校验
                    .AddProfileService<ProfileService>();
                //注册mvc服务
                services.AddMvc();
            }
    
            // 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();
                }
                //添加到HTTP管道中。
                app.UseIdentityServer();
                //添加静态资源访问
                app.UseStaticFiles();
                //添加mvc到管道中
                app.UseMvcWithDefaultRoute();
    
            }
        }
    }

     4、添加官网UI后找到AccountController类,修改登录方法Login ,把下图中的代码替换成自己的查询数据库用户即可,这里官方使用的是TestUsers类中自定义的用户来登录。

    二、Web端配置获取登录后的用户信息

    1、引入官网包:IdentityModel

    2、Startup配置如下。ResponseType返回类型详情可参考@solenovex的文章,大佬在文章说的比较详细,这里不在重复说明,地址:https://www.cnblogs.com/cgzl/p/9253667.html

    using System;
    using System.Collections.Generic;
    using System.IdentityModel.Tokens.Jwt;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Authentication;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    
    namespace Web
    {
        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;
                });
    
                JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
    
                services.AddAuthentication(options =>
                {
                    options.DefaultScheme = "Cookies";
                    options.DefaultChallengeScheme = "oidc";
                })
                    .AddCookie("Cookies")
                    .AddOpenIdConnect("oidc", options =>
                    {
                        options.SignInScheme = "Cookies";
                        //授权端服务地址
                        options.Authority = "http://localhost:5000/";
                        //是否https请求
                        options.RequireHttpsMetadata = false;
                        //客户端ID名称
                        options.ClientId = "mvc";
                        options.ClientSecret = "secret";
                        //返回的类型
                        options.ResponseType = "code id_token";
                        //添加自定义用户信息
                        options.Scope.Clear();
                        options.Scope.Add("openid");
                        options.Scope.Add("profile");
                        //是否存储token
                        options.SaveTokens = true;
                        //用于设置在从令牌端点接收的id_token创建标识后,处理程序是否应转到用户信息端点
                        options.GetClaimsFromUserInfoEndpoint = true;
                        //访问名称api
                        options.Scope.Add("api1");
                        //避免claims被默认过滤掉,如果不想让中间件过滤掉nbf和amr, 把nbf和amr从被过滤掉集合里移除。可以使用下面这个方方式:
                        options.ClaimActions.Remove("nbf");
                        options.ClaimActions.Remove("amr");
                        //删除某些Claims
                        options.ClaimActions.DeleteClaim("sid");
                        options.ClaimActions.DeleteClaim("idp");
                    });
    
                services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
            }
    
            // 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");
                }
    
                app.UseStaticFiles();
                app.UseCookiePolicy();
                //添加用户验证中间件
                app.UseAuthentication();
                //
                app.UseMvc(routes =>
                {
                    routes.MapRoute(
                        name: "default",
                        template: "{controller=Home}/{action=Index}/{id?}");
                });
            }
        }
    }

     3、在需要登录的页面方法添加Authorize特性。

     启动web 会看到页面自动重定向到登录页面效果如图:

     4、获取用户信息可使用HttpContext.User.Identity来获取当前用户信息,代码如下:

     //获取用户信息
     var claimIdentity = (ClaimsIdentity)HttpContext.User.Identity;
     var claimsPrincipal = claimIdentity.Claims as List<Claim>;

    5、获取用户token,这里的token是服务端生成发送给客户端,用于身份校验,可使用token访问需要登录权限的API接口。代码如下:

    //获取用户token
    var token = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.AccessToken);

    Ps:注销登录默认跳转到退出信息提示页面,如不需要修改服务端的 AccountOptions类中的AutomaticRedirectAfterSignOut属性,默认为false,修改为true即可。

    三、API配置

    1、引入官网包:IdentityServer4.AccessTokenValidation

    2、Startup类配置如下:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Microsoft.AspNetCore.Builder;
    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.Extensions.Configuration;
    using Microsoft.Extensions.DependencyInjection;
    using Microsoft.Extensions.Logging;
    using Microsoft.Extensions.Options;
    
    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.AddMvcCore()
                        .AddAuthorization()//添加身份验证服务
                        .AddJsonFormatters();
                //AddAuthentication将身份验证服务添加到DI并配置"Bearer"为默认方案
                services.AddAuthentication("Bearer")
                        .AddIdentityServerAuthentication(options =>
                        {
                            options.Authority = "http://localhost:5000";//identifyServer服务地址
                            options.RequireHttpsMetadata = false;//是否使用https
    
                            options.ApiName = "api1";//进行身份验证的API资源的名称
                        });
            }
    
            // 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();
            }
        }
    }

    3、给对应的API接口添加Authorize特性,Web端登录通过token访问该接口。代码如下:

    //获取用户token
    var token = await HttpContext.GetTokenAsync(OpenIdConnectParameterNames.AccessToken);
    //实例化HttpClient
    var client = new HttpClient();
    client.SetBearerToken(token);
    //请求identity接口
    var response = await client.GetAsync("http://localhost:5001/identity");
    if (!response.IsSuccessStatusCode)
    {
         Console.WriteLine(response.StatusCode);
    }
  • 相关阅读:
    CSP 2020 提高组第一轮
    初赛胡扯
    Sublime安装SublimeServer插件开启本地服务器
    Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: No "exports" main defined in XXX ode_modules@babelhelper-compilation-targetspackage.json
    Vue解决less-loader报错 TypeError: this.getOptions is not a function
    Vue-cli项目关闭eslint检查
    Typora添加主题
    Oracle存储过程中EXECUTE IMMEDIATE 执行结果是空时怎么继续执行
    存储过程--异常捕获
    git和github的基本使用(2)
  • 原文地址:https://www.cnblogs.com/miskis/p/9480432.html
Copyright © 2011-2022 走看看