.Net6基于IdentityServer4搭建认证授权服务

编程入门 行业动态 更新时间:2024-10-27 11:25:46

.Net6基于IdentityServer4搭建认证授权服务

.Net6基于IdentityServer4搭建认证授权服务

新建一个名为Ids4.Server.Net6的空项目,引用包源IdentityServer4

添加Config配置类

using IdentityServer4.Models;
using static IdentityServer4.IdentityServerConstants;namespace Ids4.Server;public class Config
{public static IEnumerable<IdentityResource> IdentityResources =>new List<IdentityResource>{new IdentityResources.OpenId(),new IdentityResources.Profile()};public static IEnumerable<ApiScope> ApiScopes =>new ApiScope[]{new ApiScope("api2", "My Api2")};public static IEnumerable<Client> Clients =>new List<Client>{new Client{ClientId = "client_api2",// 要使用RefreshToken时,必须要把AllowedGrantTypes设置为授权代码、混合和资源所有者密码凭证流AllowedGrantTypes = GrantTypes.ResourceOwnerPassword, //GrantTypes.ClientCredentials,ClientSecrets ={new Secret("secret".Sha256()) //secret加密密钥 Sha256加密方式},AllowedScopes ={"api2",StandardScopes.OfflineAccess,},// 刷新Token时RefreshToken保持不变RefreshTokenUsage = TokenUsage.ReUse,RefreshTokenExpiration = TokenExpiration.Sliding,// RefreshToken过期时间SlidingRefreshTokenLifetime = 3600,// 明确授权请求刷新令牌AllowOfflineAccess = true,// TOken过期时间AccessTokenLifetime = 60,}};
}

添加UserInfoModel类,模拟数据库用户信息实体

namespace Ids4.Server;public class UserInfoModel
{public string Id { get; set; }public string Username { get; set; }public string Password { get; set; }public string Role { get; set; }
}

添加静态类UserData,模拟数据库数据

namespace Ids4.Server;public static class UserData
{/// <summary>/// 模拟数据库存储的用户信息/// </summary>/// <returns></returns>public static List<UserInfoModel> GetListUsers(){return new List<UserInfoModel>{new UserInfoModel{Id = "1",Username = "zhangsan",Password = "123456",Role = "admin"},new UserInfoModel{Id = "2",Username = "lisi",Password = "123456",Role = "Test1,Test2"},new UserInfoModel{Id = "2",Username = "lisi",Password = "123456",Role = "Test2"}};}
}

添加ResourceOwnerPasswordValidator类继承IResourceOwnerPasswordValidator实现ValidateAsync。该方法用于客户端请求获取Token时校验用户信息是否存在

using IdentityModel;
using IdentityServer4.Models;
using IdentityServer4.Validation;namespace Ids4.Server;public class ResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
{public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context){// 根据username和password查询用户是否存在var user = UserData.GetListUsers().FirstOrDefault(p => p.Username == context.UserName && p.Password == context.Password);if (user != null){// 返回Id,为下一步获取角色权限做准备context.Result = new GrantValidationResult(user.Id, OidcConstants.AuthenticationMethods.Password);}else{context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "Invalid credentials");}}
}

添加ProfileService类继承IProfileService实现GetProfileDataAsync。该方法用于将用户的角色信息添加到Token

using System.Security.Claims;
using IdentityModel;
using IdentityServer4.Extensions;
using IdentityServer4.Models;
using IdentityServer4.Services;namespace Ids4.Server;public class ProfileService : IProfileService
{/// <summary>/// 根据Id拿到用户所属角色,添加到Token中/// </summary>/// <param name="context"></param>public async Task GetProfileDataAsync(ProfileDataRequestContext context){var user = UserData.GetListUsers().FirstOrDefault(p => p.Id == context.Subject.GetSubjectId());// 存在多个权限时var roleArr = user.Role.Split(",");var claims = new List<Claim>();foreach (var item in roleArr){claims.Add(new Claim(JwtClaimTypes.Role, item));}context.IssuedClaims = claims;}public async Task IsActiveAsync(IsActiveContext context){context.IsActive = true;}
}

添加RefreshTokenService类继承IRefreshTokenService实现CreateRefreshTokenAsyncUpdateRefreshTokenAsyncValidateRefreshTokenAsync三个方法

using System.Security.Claims;
using IdentityServer4.Models;
using IdentityServer4.Services;
using IdentityServer4.Validation;namespace Ids4.Server;public class RefreshTokenService : IRefreshTokenService
{/// <summary>/// 模拟RefreshToken存在缓存中/// </summary>private readonly static Dictionary<string, RefreshToken> _refreshTokens = new Dictionary<string, RefreshToken>();/// <summary>/// 创建刷新token/// </summary>/// <param name="subject"></param>/// <param name="accessToken"></param>/// <param name="client"></param>/// <returns></returns>/// <exception cref="NotImplementedException"></exception>public async Task<string> CreateRefreshTokenAsync(ClaimsPrincipal subject, Token accessToken, Client client){var handle = Guid.NewGuid().ToString();var refreshToken = new RefreshToken{AccessToken = accessToken,CreationTime = DateTime.UtcNow,Lifetime = client.RefreshTokenExpiration == TokenExpiration.Sliding ? client.SlidingRefreshTokenLifetime : client.AbsoluteRefreshTokenLifetime,//Subject = subject,Version = 1};_refreshTokens[handle] = refreshToken;return await Task.FromResult(handle);}/// <summary>/// 修改刷新token/// </summary>/// <param name="handle"></param>/// <param name="refreshToken"></param>/// <param name="client"></param>/// <returns></returns>/// <exception cref="NotImplementedException"></exception>public async Task<string> UpdateRefreshTokenAsync(string handle, RefreshToken refreshToken, Client client){if (!_refreshTokens.ContainsKey(handle)){throw new ArgumentException("Invalid refresh token handle");}_refreshTokens[handle] = refreshToken;return await Task.FromResult(handle);}/// <summary>/// 验证刷新token/// </summary>/// <param name="token"></param>/// <param name="client"></param>/// <returns></returns>/// <exception cref="NotImplementedException"></exception>public async Task<TokenValidationResult> ValidateRefreshTokenAsync(string token, Client client){if (!_refreshTokens.TryGetValue(token, out var refreshToken)){return await Task.FromResult(new TokenValidationResult{IsError = true,Error = "Invalid refresh token"});}if (refreshToken.AccessToken.ClientId != client.ClientId){return await Task.FromResult(new TokenValidationResult{IsError = true,Error = "Refresh token does not belong to the client"});}if (DateTime.UtcNow > refreshToken.CreationTime.AddSeconds(refreshToken.Lifetime)){return await Task.FromResult(new TokenValidationResult{IsError = true,Error = "Refresh token has expired"});}return await Task.FromResult(new TokenValidationResult{IsError = false,RefreshToken = refreshToken});}
}

Program注入

builder.Services.AddTransient<IRefreshTokenService, RefreshTokenService>();
builder.Services.AddIdentityServer().AddDeveloperSigningCredential().AddInMemoryApiScopes(Config.ApiScopes).AddInMemoryClients(Config.Clients).AddInMemoryIdentityResources(Config.IdentityResources).AddProfileService<ProfileService>().AddResourceOwnerValidator<ResourceOwnerPasswordValidator>();app.UseIdentityServer();

项目结构

至此,基于IdentityServer4的认证授权服务就搭建完成了
使用postman请求获取AccessToken

使用RefreshToken刷新AccessToken

解析后的Token

源码地址:.git

更多推荐

.Net6基于IdentityServer4搭建认证授权服务

本文发布于:2024-03-09 13:32:48,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1725101.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!