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 的值。
通过调用上面两个接口,完成登录授权。
效果图: