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);
}

 

posted @ 2018-08-15 15:49  ice.ko  阅读(6441)  评论(0编辑  收藏  举报