ASP.NET Core的身份认证框架IdentityServer4--(5)自定义用户登录(通过接口登录,无UI版本)

官网接口详解文档地址文档地址 (PS:可通过接口名称搜索相应接口信息。)

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

 一、修改服务端

1、修改Startup文件源码如下:

namespace Server
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            //配置身份服务器与内存中的存储,密钥,客户端和资源
            services.AddIdentityServer()
                .AddDeveloperSigningCredential()
                .AddInMemoryIdentityResources(Config.GetIdentityResources());//添加对OpenID Connect的支持
                .AddInMemoryApiResources(Config.GetApiResources())//添加api资源
                .AddInMemoryClients(Config.GetClients())//添加客户端
                .AddResourceOwnerValidator<LoginValidator>()//用户校验
                .AddProfileService<ProfileService>();
        }
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            //添加到HTTP管道中。
            app.UseIdentityServer();
        }
    }
}

 2、修改config文件

namespace Server
{
    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
                {
                    //客户端名称
                    ClientId = "client1",
                    //客户端访问方式:密码验证
                    AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
                    //用于认证的密码加密方式
                    ClientSecrets =
                    {
                        new Secret("secret".Sha256())
                    },
                    //客户端有权访问的范围
                    AllowedScopes = { "api1",IdentityServerConstants.StandardScopes.OpenId, //必须要添加,否则报403 forbidden错误
                  IdentityServerConstants.StandardScopes.Profile }
                }
            };
        }
    }
}

3、新建LoginValidator类,用于用户校验

namespace Server
{
    /// <summary>
    /// 自定义用户登录校验
    /// </summary>
    public class LoginValidator : IResourceOwnerPasswordValidator
    {
        public LoginValidator()
        {

        }
        /// <summary>
        /// 登录用户校验
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
        {
            //根据context.UserName和context.Password与数据库的数据做校验,判断是否合法
            if (context.UserName == "test" && context.Password == "123")
            {
                context.Result = new GrantValidationResult(
                 subject: context.UserName,
                 authenticationMethod: "custom",
                 claims: GetUserClaims());
            }
            else
            {
                //验证失败
                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "账号密码错误");
            }
        }
        /// <summary>
        /// 可以根据需要设置相应的Claim
        /// </summary>
        /// <returns></returns>
        private Claim[] GetUserClaims()
        {
            return new Claim[]
            {
            new Claim("UserId", 1.ToString()),
            new Claim(JwtClaimTypes.Name,"test"),
            new Claim(JwtClaimTypes.GivenName, "jaycewu"),
            new Claim(JwtClaimTypes.FamilyName, "yyy"),
            new Claim(JwtClaimTypes.Email, "test@qq.com"),
            new Claim(JwtClaimTypes.Role,"admin")
            };
        }
    }
}

4、新建ProfileService类,用于返回用户自定义信息

namespace Server
{
    /// <summary>
    /// 获取用户信息并返回给客户端
    /// </summary>
    public class ProfileService : IProfileService
    {
        /// <summary>
        /// 获取用户信息
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task GetProfileDataAsync(ProfileDataRequestContext context)
        {
            try
            {
                //用户信息
                var claims = context.Subject.Claims.ToList();

                //获取用户信息
                context.IssuedClaims = claims.ToList();
            }
            catch (Exception ex)
            {
                //log your error
            }
        }
        /// <summary>
        /// 获取或设置一个值,该值指示主题是否处于活动状态并且可以接收令牌。
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task IsActiveAsync(IsActiveContext context)
        {
            context.IsActive = true;
        }
    }
}

5、通过接口获取用户信息

5.1、用户登录接口:http://localhost:5000/connect/token

参数名 说明 是否必填 示例
username 用户名 Y test
password 密码 Y 123
grant_type 加密类型 Y password
client_id 客户端名称 Y client1
client_secret 客户端加密类型 Y secret

 

 

 

 

 

效果图:

注意最新版content-Type必须是application/x-www-form-urlencoded,不然会报无效请求错误

5.2、获取用户信息接口:http://localhost:5000/connect/userinfo

参数 是否必填 说明 
Authorization Y 值的格式:key空格value

 

 

 

PS:key 的值为上面接口返回的 token_type 的值,value 为 access_token 的值。

通过调用上面两个接口,完成登录授权。

效果图:

 

 

posted @ 2018-08-08 14:43  ice.ko  阅读(1750)  评论(2编辑  收藏  举报