xf 1 ano atrás
pai
commit
4f7bcc45ba

+ 11 - 12
src/Hotline.Api/StartupExtensions.cs

@@ -4,7 +4,6 @@ using Hotline.Api.Realtimes;
 using Hotline.Application;
 using Hotline.Application.Contracts;
 using Hotline.CallCenter.Devices;
-using Hotline.Identity.Accounts;
 using Hotline.NewRock;
 using Hotline.Permissions;
 using Hotline.Repository.SqlSugar.Extensions;
@@ -37,7 +36,7 @@ internal static class StartupExtensions
 #if DEBUG
         builder.WebHost.UseUrls("http://*:50100");
 #endif
-
+        
         //services.Configure<DeviceConfigs>(d => configuration.GetSection(nameof(DeviceConfigs)).Bind(d));
         services.Configure<IdentityConfiguration>(d => configuration.GetSection(nameof(IdentityConfiguration)).Bind(d));
         services.Configure<CallCenterConfiguration>(d => configuration.GetSection(nameof(CallCenterConfiguration)).Bind(d));
@@ -53,6 +52,15 @@ internal static class StartupExtensions
             .AddScoped(typeof(IPasswordHasher<>), typeof(PasswordHasher<>))
             ;
 
+        //cache
+        services.AddCache(d =>
+        {
+            var cacheConfig = configuration.GetSection("Cache").Get<CacheOptions>();
+            cacheConfig.Adapt(d);
+            d.Prefix = "Hotline";
+            d.TopicName = "hotline-topic";
+        });
+
         //Authentication
         services.RegisterAuthentication(configuration);
 
@@ -110,15 +118,6 @@ internal static class StartupExtensions
         services.AddSqlSugar(configuration);
         //services.AddWexDb(configuration);
 
-        //cache
-        services.AddCache(d =>
-            {
-                var cacheConfig = configuration.GetSection("Cache").Get<CacheOptions>();
-                cacheConfig.Adapt(d);
-                d.Prefix = "Hotline";
-                d.TopicName = "hotline-topic";
-            });
-
         //validator
         services.AddFluentValidationAutoValidation(config =>
         {
@@ -150,7 +149,7 @@ internal static class StartupExtensions
                 //c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
             });
         }
-
+       
         app.UseCors(CorsOrigins);
 
         app.UseAuthentication();

+ 18 - 1
src/Hotline.Api/StartupHelper.cs

@@ -1,6 +1,8 @@
 using System.IdentityModel.Tokens.Jwt;
 using System.Reflection;
 using System.Text;
+using Hotline.Application.Orders;
+using Hotline.Identity;
 using Hotline.Repository.SqlSugar;
 using Hotline.Repository.SqlSugar.Ts;
 using Mapster;
@@ -8,6 +10,7 @@ using MapsterMapper;
 using Microsoft.AspNetCore.Authentication.JwtBearer;
 using Microsoft.IdentityModel.Tokens;
 using Microsoft.OpenApi.Models;
+using XF.Domain.Cache;
 using XF.Domain.Entities;
 using XF.Domain.Exceptions;
 using XF.Domain.Options;
@@ -25,6 +28,12 @@ namespace Hotline.Api
         /// <returns></returns>
         public static IServiceCollection RegisterAuthentication(this IServiceCollection services, ConfigurationManager configuration)
         {
+            //using var serviceProvider = services.BuildServiceProvider();
+            //var cacheAudience = serviceProvider.GetService<ITypedCache<AudienceTicket>>();
+            var jwtOptions = configuration.GetSection("IdentityConfiguration").Get<IdentityConfiguration>().Jwt;
+
+            #region remote ids
+
             //JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
             //services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
             //    .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, d =>
@@ -56,10 +65,10 @@ namespace Hotline.Api
             //        };
             //    });
 
+            #endregion
             services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                 .AddJwtBearer(d =>
                 {
-                    var jwtOptions = configuration.GetSection("IdentityConfiguration").Get<IdentityConfiguration>().Jwt;
                     byte[] bytes = Encoding.UTF8.GetBytes(jwtOptions.SecretKey);
                     var secKey = new SymmetricSecurityKey(bytes);
                     d.TokenValidationParameters = new()
@@ -69,6 +78,14 @@ namespace Hotline.Api
                         ValidateLifetime = true,
                         ValidateIssuerSigningKey = true,
                         IssuerSigningKey = secKey,
+                        //AudienceValidator = (audiences, token, parameters) =>
+                        //{
+                        //    using var serviceProvider = services.BuildServiceProvider();
+                        //    var a = serviceProvider.GetService<IOrderApplication>();
+                        //    var cacheAudience = serviceProvider.GetService<ITypedCache<AudienceTicket>>();
+                        //    var audience = cacheAudience.Get(token.Id);
+                        //    return audiences != null && audiences.Any(a => a == audience?.Ticket);
+                        //}
                     };
 
                     //d.Audience = "hotline_api";

+ 12 - 4
src/Hotline.Application/Identity/IdentityAppService.cs

@@ -1,4 +1,5 @@
 using System.Security.Claims;
+using Hotline.Identity;
 using Hotline.Identity.Accounts;
 using Hotline.Push;
 using Hotline.Settings;
@@ -9,6 +10,7 @@ using IdentityModel;
 using Microsoft.AspNetCore.Identity;
 using Microsoft.Extensions.Options;
 using XF.Domain.Authentications;
+using XF.Domain.Cache;
 using XF.Domain.Dependency;
 using XF.Domain.Exceptions;
 using XF.Domain.Options;
@@ -23,6 +25,7 @@ public class IdentityAppService : IIdentityAppService, IScopeDependency
     private readonly IRepository<User> _userRepository;
     private readonly IJwtSecurity _jwtSecurity;
     private readonly IOptionsSnapshot<IdentityConfiguration> _identityOptionsAccessor;
+    private readonly ITypedCache<AudienceTicket> _cacheAudience;
     private readonly IMessageCodeDomainService _messageCodeDomainService;
 
     public IdentityAppService(
@@ -31,6 +34,7 @@ public class IdentityAppService : IIdentityAppService, IScopeDependency
         IRepository<User> userRepository,
         IJwtSecurity jwtSecurity,
         IOptionsSnapshot<IdentityConfiguration> identityOptionsAccessor,
+        ITypedCache<AudienceTicket> cacheAudience,
         IMessageCodeDomainService messageCodeDomainService)
     {
         _accountRepository = accountRepository;
@@ -38,6 +42,7 @@ public class IdentityAppService : IIdentityAppService, IScopeDependency
         _userRepository = userRepository;
         _jwtSecurity = jwtSecurity;
         _identityOptionsAccessor = identityOptionsAccessor;
+        _cacheAudience = cacheAudience;
         _messageCodeDomainService = messageCodeDomainService;
     }
 
@@ -50,7 +55,7 @@ public class IdentityAppService : IIdentityAppService, IScopeDependency
             throw UserFriendlyException.SameMessage("用户名或密码错误!");
 
         //校验验证码
-        await _messageCodeDomainService.CheckdCode(account.UserName, account.PhoneNo, dto.MsgCode, cancellationToken);
+        //await _messageCodeDomainService.CheckdCode(account.UserName, account.PhoneNo, dto.MsgCode, cancellationToken);
 
         if (account.Status != EAccountStatus.Normal)
             throw UserFriendlyException.SameMessage("用户名或密码错误!");
@@ -68,7 +73,7 @@ public class IdentityAppService : IIdentityAppService, IScopeDependency
             await _accountRepository.UpdateAsync(account, cancellationToken);
             throw UserFriendlyException.SameMessage("账号名或密码错误!");
         }
-        
+
         //限制系统类型账户频繁获取token的行为
         //todo
 
@@ -88,7 +93,7 @@ public class IdentityAppService : IIdentityAppService, IScopeDependency
         var jwtOptions = _identityOptionsAccessor.Value.Jwt;
         var claims = new List<Claim>
         {
-            //new(JwtClaimTypes.Id, account.Id),
+            new(JwtClaimTypes.Id, account.Id),
             new(JwtClaimTypes.Subject, account.Id),
             new(JwtClaimTypes.PhoneNumber, account.PhoneNo ?? string.Empty),
             new(AppClaimTypes.UserDisplayName, account.Name),
@@ -112,7 +117,10 @@ public class IdentityAppService : IIdentityAppService, IScopeDependency
             );
         }
         claims.AddRange(account.Roles.Select(d => new Claim(JwtClaimTypes.Role, d.Name)));
-        var token = _jwtSecurity.EncodeJwtToken(claims);
+        var audience = new AudienceTicket(account.Id);
+        var expiredSeconds = jwtOptions.Expired <= 0 ? 3600 : jwtOptions.Expired;
+        await _cacheAudience.SetAsync(audience.Id, audience, TimeSpan.FromSeconds(expiredSeconds), cancellationToken);
+        var token = _jwtSecurity.EncodeJwtToken(claims, audience.Ticket);
         return token;
     }
 }

+ 3 - 5
src/Hotline.Application/Subscribers/DatasharingSubscriber.cs

@@ -289,8 +289,6 @@ namespace Hotline.Application.Subscribers
             }
         }
 
-
-
         /// <summary>
         /// 工单回访
         /// </summary>
@@ -409,9 +407,6 @@ namespace Hotline.Application.Subscribers
             }
         }
 
-        
-
-
         /// <summary>
         /// 订阅省工单延期消息
         /// </summary>
@@ -468,6 +463,9 @@ namespace Hotline.Application.Subscribers
         [CapSubscribe(EventNames.SharingOrderExtends)]
         public async Task RecOrderExtensionAsync(OrderExtensionDto dto, CancellationToken cancellationToken)
         {
+            var order = await _orderRepository.Queryable()
+                .FirstAsync(d => d.ProvinceNo == dto.ProvinceNo, cancellationToken);
+
             var orderExtension =
                 await _orderExtensionRepository.GetAsync(d => d.ProvinceNo == dto.ProvinceNo, cancellationToken);
             if (orderExtension is null)

+ 20 - 0
src/Hotline/Identity/AudienceTicket.cs

@@ -0,0 +1,20 @@
+namespace Hotline.Identity
+{
+    public class AudienceTicket
+    {
+        public AudienceTicket()
+        {
+
+        }
+
+        public AudienceTicket(string id)
+        {
+            Id = id;
+            Ticket = $"{id}/{DateTime.Now}";
+        }
+
+        public string Id { get; set; }
+
+        public string Ticket { get; set; }
+    }
+}

+ 4 - 3
src/XF.Domain/Authentications/IJwtSecurity.cs

@@ -18,7 +18,7 @@ namespace XF.Domain.Authentications
 {
     public interface IJwtSecurity
     {
-        string EncodeJwtToken(ICollection<Claim> claims);
+        string EncodeJwtToken(ICollection<Claim> claims, string? audience = null);
         void DecodeJwtToken(string jwt);
     }
 
@@ -33,7 +33,7 @@ namespace XF.Domain.Authentications
             _contextAccessor = contextAccessor;
         }
 
-        public string EncodeJwtToken(ICollection<Claim> claims)
+        public string EncodeJwtToken(ICollection<Claim> claims, string? audience = null)
         {
             var jwtOptions = _jwtConfigOptionAccessor.Value.Jwt;
             if (jwtOptions == null)
@@ -44,7 +44,8 @@ namespace XF.Domain.Authentications
             var signingCredentials =
                 new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);
             var expired = DateTime.Now.AddMinutes(jwtOptions.Expired);
-            var jwtSecurityToken = new JwtSecurityToken(jwtOptions.Issuer, jwtOptions.Audience, claims, DateTime.Now, expired,
+            audience ??= jwtOptions.Audience;
+            var jwtSecurityToken = new JwtSecurityToken(jwtOptions.Issuer, audience, claims, DateTime.Now, expired,
                 signingCredentials);
             var tokenHandler = new JwtSecurityTokenHandler();
             var token = tokenHandler.WriteToken(jwtSecurityToken);

+ 4 - 0
src/XF.Domain/Options/IdentityConfiguration.cs

@@ -24,6 +24,10 @@ namespace XF.Domain.Options
         public string Issuer { get; set; }
         public string Audience { get; set; }
         public string Scope { get; set; }
+
+        /// <summary>
+        /// 单位:秒
+        /// </summary>
         public int Expired { get; set; }
     }
 }