Browse Source

提交树形结构课纲保存

黄贺彬 6 years ago
parent
commit
0e38573701

+ 2 - 1
TEAMModelOS.Model/Common/Dtos/LoginResult.cs

@@ -1,12 +1,13 @@
 using System;
 using System.Collections.Generic;
 using System.Text;
+using TEAMModelOS.SDK.Extension.JwtAuth.Models;
 
 namespace TEAMModelOS.Model.Common.Dtos
 {
     public class LoginResult
     {
-        public string JwtToken { get; set; }
+        public JwtResponse JwtToken { get; set; }
         public bool CheckTicket { get; set; }
     }
 }

+ 14 - 0
TEAMModelOS.Model/Common/Models/JwtBlackRecord.cs

@@ -0,0 +1,14 @@
+using Microsoft.WindowsAzure.Storage.Table;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using TEAMModelOS.SDK.Context.Attributes.Table;
+
+namespace TEAMModelOS.Model.Common.Models
+{
+    [TableSpaceAttribute(Name = "Common")]
+    public class JwtBlackRecord :TableEntity
+    {
+        public string Jti { get; set; } 
+    }
+}

+ 7 - 0
TEAMModelOS.Model/Common/Models/LoginInfo.cs

@@ -2,12 +2,14 @@
 using System;
 using System.Collections.Generic;
 using System.Text;
+using TEAMModelOS.SDK.Context.Attributes.Table;
 
 namespace TEAMModelOS.Model.Common.Models
 {
     /// <summary>
     /// 登录信息
     /// </summary>
+    [TableSpaceAttribute(Name = "Common")]
     public class LoginInfo : TableEntity
     {
         public string TeamModelId { get; set; }
@@ -28,5 +30,10 @@ namespace TEAMModelOS.Model.Common.Models
         /// 到期时间
         /// </summary>
         public long Expires { get; set; }
+        /// <summary>
+        /// 作用域
+        /// </summary>
+        public string Scope { get; set; }
+        
     }
 }

+ 6 - 2
TEAMModelOS.Model/Common/Models/RoleUser.cs

@@ -1,10 +1,14 @@
-using System;
+using Microsoft.WindowsAzure.Storage.Table;
+using System;
 using System.Collections.Generic;
 using System.Text;
+using TEAMModelOS.SDK.Context.Attributes.Table;
 
 namespace TEAMModelOS.Model.Common.Models
 {
-    public class RoleUser
+
+    [TableSpaceAttribute(Name = "Common")]
+    public class RoleUser : TableEntity
     {
         public string Name { get; set; }
         public string Phone { get; set; }

+ 57 - 0
TEAMModelOS.Model/Common/Models/TeamModelUser.cs

@@ -0,0 +1,57 @@
+using Microsoft.WindowsAzure.Storage.Table;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using TEAMModelOS.SDK.Context.Attributes.Table;
+
+namespace TEAMModelOS.Model.Common.Models
+{
+    [TableSpaceAttribute(Name = "Common")]
+    public class TeamModelUser : TableEntity
+    {
+        /// <summary>
+        /// 真实姓名
+        /// </summary>
+        public string FullName { get; set; }
+        /// <summary>
+        /// 昵称
+        /// </summary>
+        public string NickName { get; set; }
+        /// <summary>
+        /// 性别
+        /// </summary>
+        public string Sex { get; set; }
+        /// <summary>
+        /// 手机号
+        /// </summary>
+        public string Cellphone { get; set; }
+        /// <summary>
+        /// 邮箱
+        /// </summary>
+        public string Email { get; set; }
+        /// <summary>
+        /// 醍摩豆ID
+        /// </summary>
+        public string TeamModelId { get; set; }
+        /// <summary>
+        /// 头像
+        /// </summary>
+        public string Header { get; set; }
+        /// <summary>
+        /// 城市
+        /// </summary>
+        public string City { get; set; }
+        /// <summary>
+        /// 城市编码
+        /// </summary>
+        public string CityCode { get; set; }
+        /// <summary>
+        /// 注册时间
+        /// </summary>
+        public long RegisterTime { get; set; }
+        /// <summary>
+        /// 国家或地区编码
+        /// </summary>
+        public string CountryCode { get; set; }
+    }
+}

+ 11 - 4
TEAMModelOS.Model/Syllabus/Dtos/SyllabusTree.cs

@@ -2,6 +2,7 @@
 using Microsoft.WindowsAzure.Storage.Table;
 using System;
 using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
 using System.Text;
 
 namespace TEAMModelOS.Model.Syllabus.Dtos
@@ -15,6 +16,7 @@ namespace TEAMModelOS.Model.Syllabus.Dtos
         /// <summary>
         /// 标题
         /// </summary>
+        [Required(ErrorMessage = "{0} 必须填写")]
         public string Title { get; set; }
         /// <summary>
         /// 是否展开
@@ -23,10 +25,12 @@ namespace TEAMModelOS.Model.Syllabus.Dtos
         /// <summary>
         /// 排序
         /// </summary>
+        [Required(ErrorMessage = "{0} 必须填写")]
         public int Order { get; set; }
         /// <summary>
         /// 类型
         /// </summary>
+        [Required(ErrorMessage = "{0} 必须填写")]
         public int Type { get; set; }
         /// <summary>
         /// 备注
@@ -35,14 +39,17 @@ namespace TEAMModelOS.Model.Syllabus.Dtos
         /// <summary>
         /// 节点Key
         /// </summary>
+        [Required(ErrorMessage = "{0} 必须填写")]
         public string NodeKey { get; set; }
-        /// <summary>
-        ///主键
-        /// </summary>
-        public string Id { get; set; }
+        ///// <summary>
+        /////主键
+        ///// </summary>
+        //[Required(ErrorMessage = "{0} 必须填写")]
+        //public string Id { get; set; }
         /// <summary>
         /// 父级
         /// </summary>
+        [Required(ErrorMessage = "{0} 必须填写")]
         public string Pid { get; set; }
         public SyllabusTree() 
         {

+ 5 - 5
TEAMModelOS.Model/Syllabus/Models/SyllabusNode.cs

@@ -42,11 +42,11 @@ namespace TEAMModelOS.Model.Syllabus.Models
         /// </summary>
         [Required(ErrorMessage = "{0} 必须填写")]
         public string NodeKey { get; set; }
-        /// <summary>
-        ///主键
-        /// </summary>
-        [Required(ErrorMessage = "{0} 必须填写")]
-        public string Id { get; set; }
+        ///// <summary>
+        /////主键
+        ///// </summary>
+        //[Required(ErrorMessage = "{0} 必须填写")]
+        //public string Id { get; set; }
         /// <summary>
         /// 父级
         /// </summary>

+ 5 - 2
TEAMModelOS.SDK/Extension/JwtAuth/JwtAuthExtension.cs

@@ -6,10 +6,10 @@ using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.IdentityModel.Tokens;
 using System;
-using System.Text;
 using System.Threading.Tasks;
-using TEAMModelOS.SDK.Extension.JwtAuth.JwtHelper;
 using TEAMModelOS.SDK.Context.Configuration;
+using TEAMModelOS.SDK.Helper.Security.RSACrypt;
+using TEAMModelOS.SDK.Extension.JwtAuth.Requirements;
 
 namespace TEAMModelOS.SDK.Extension.JwtAuth
 {
@@ -81,8 +81,11 @@ namespace TEAMModelOS.SDK.Extension.JwtAuth
                 auth.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
                     .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
                     .RequireAuthenticatedUser()
+                    .AddRequirements(new ValidJtiRequirement()) // 添加上面的验证要求
                     .Build());
             });
+            // 注册验证要求的处理器,可通过这种方式对同一种要求添加多种验证
+            services.AddSingleton<IAuthorizationHandler, ValidJtiHandler>();
         }
         
     }

+ 4 - 2
TEAMModelOS.SDK/Extension/JwtAuth/JwtHelper/JwtHelper.cs

@@ -10,6 +10,7 @@ using System.Text;
 using TEAMModelOS.SDK.Helper.Common.DateTimeHelper;
 using TEAMModelOS.SDK.Context.Configuration;
 using System.Security.Cryptography;
+using TEAMModelOS.SDK.Helper.Security.RSACrypt;
 
 namespace TEAMModelOS.SDK.Extension.JwtAuth.JwtHelper
 {
@@ -41,6 +42,7 @@ namespace TEAMModelOS.SDK.Extension.JwtAuth.JwtHelper
             claims.Add(new Claim(JwtClaimTypes.Audience, setting.Audience));
             claims.Add(new Claim(JwtClaimTypes.Issuer, setting.Issuer));
             claims.Add(new Claim(JwtClaimTypes.Scope, claimModel.Scope));
+            claims.Add(new Claim(JwtClaimTypes.JwtId, Guid.NewGuid().ToString()));
             claims.AddRange(claimModel.Roles.ToArray().Select(s=>new Claim(JwtClaimTypes.Role,s)));
             string path = BaseConfigModel.ContentRootPath;
             RSACryptoServiceProvider provider = RsaHelper.LoadCertificateFile(path + "/private.pem");
@@ -53,8 +55,8 @@ namespace TEAMModelOS.SDK.Extension.JwtAuth.JwtHelper
                 );
             var jwtHandler = new JwtSecurityTokenHandler();
             return new JwtResponse {
-                access_token = jwtHandler.WriteToken(jwt),
-                scope = claimModel.Scope
+                Access_token = jwtHandler.WriteToken(jwt),
+                Scope = claimModel.Scope
             };
         }
         /// <summary>

+ 14 - 0
TEAMModelOS.SDK/Extension/JwtAuth/Models/JwtBlackRecord.cs

@@ -0,0 +1,14 @@
+using Microsoft.WindowsAzure.Storage.Table;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using TEAMModelOS.SDK.Context.Attributes.Table;
+
+namespace TEAMModelOS.SDK.Extension.JwtAuth.Models
+{
+    [TableSpaceAttribute(Name = "Common")]
+    public class JwtBlackRecord :TableEntity
+    {
+        public string Jti { get; set; } 
+    }
+}

+ 5 - 3
TEAMModelOS.SDK/Extension/JwtAuth/Models/JwtResponse.cs

@@ -1,13 +1,15 @@
 using System;
 using System.Collections.Generic;
 using System.Text;
+using TEAMModelOS.SDK.Context.Constant.Common;
 
 namespace TEAMModelOS.SDK.Extension.JwtAuth.Models
 {
     public class JwtResponse
     {
-        public string access_token { get; set; }
-        public string token_type { get; set; } = "Bearer";
-        public string scope { get; set; }
+        public string Access_token { get; set; }
+        public string Token_type { get; set; } = "Bearer";
+        public string Token_key { get; set; } =Constants.AUTHORIZATION;
+        public string Scope { get; set; }
     }
 }

+ 44 - 0
TEAMModelOS.SDK/Extension/JwtAuth/Requirements/ValidJtiHandler.cs

@@ -0,0 +1,44 @@
+using Microsoft.AspNetCore.Authorization;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using TEAMModelOS.SDK.Extension.JwtAuth.Models;
+using TEAMModelOS.SDK.Module.AzureTable.Interfaces;
+
+namespace TEAMModelOS.SDK.Extension.JwtAuth.Requirements
+{
+    public class ValidJtiHandler : AuthorizationHandler<ValidJtiRequirement>
+    {
+        private IAzureTableDBRepository _azureTableDBRepository;
+
+        public ValidJtiHandler(IAzureTableDBRepository azureTableDBRepository)
+        {
+            _azureTableDBRepository = azureTableDBRepository;
+        }
+        protected override  Task HandleRequirementAsync(AuthorizationHandlerContext context, ValidJtiRequirement requirement)
+        {
+            // 检查 Jti 是否存在
+            var jti = context.User.FindFirst("jti")?.Value;
+            if (jti == null)
+            {
+                context.Fail(); // 显式的声明验证失败
+                return Task.CompletedTask;
+            }
+
+            // 检查 jti 是否在黑名单
+            // 使用Redis  对于连续访问的token 进行限制
+            JwtBlackRecord record =  _azureTableDBRepository.FindOneByKey<JwtBlackRecord>("Jti",jti).Result;
+            if (record != null  && !string.IsNullOrEmpty(record.RowKey))
+            {
+                context.Fail();
+            }
+            else
+            {
+                context.Succeed(requirement); // 显式的声明验证成功
+            }
+            return Task.CompletedTask;
+
+        }
+    }
+}

+ 9 - 0
TEAMModelOS.SDK/Extension/JwtAuth/Requirements/ValidJtiRequirement.cs

@@ -0,0 +1,9 @@
+using Microsoft.AspNetCore.Authorization;
+
+namespace TEAMModelOS.SDK.Extension.JwtAuth.Requirements
+{
+    public class ValidJtiRequirement : IAuthorizationRequirement
+    {
+        
+    }
+}

+ 6 - 6
TEAMModelOS.SDK/Extension/JwtAuth/JwtHelper/RsaHelper.cs

@@ -1,12 +1,11 @@
-using Newtonsoft.Json;
-using System;
+using System;
 using System.Collections.Generic;
 using System.IO;
 using System.Security.Cryptography;
 using System.Text;
 using TEAMModelOS.SDK.Helper.Common.JsonHelper;
 
-namespace TEAMModelOS.SDK.Extension.JwtAuth.JwtHelper
+namespace TEAMModelOS.SDK.Helper.Security.RSACrypt
 {
     public static class RsaHelper
     {
@@ -17,7 +16,7 @@ namespace TEAMModelOS.SDK.Extension.JwtAuth.JwtHelper
             byte[] signatureBytes = rsaCsp.SignData(dataBytes, "SHA1");
             return Convert.ToBase64String(signatureBytes);
         }
-       
+
         private static byte[] GetPem(string type, byte[] data)
         {
             string pem = Encoding.UTF8.GetString(data);
@@ -28,7 +27,8 @@ namespace TEAMModelOS.SDK.Extension.JwtAuth.JwtHelper
             string base64 = pem.Substring(start, (end - start));
             return Convert.FromBase64String(base64);
         }
-        public static string  LoadCertificateFileToSting (string filename) {
+        public static string LoadCertificateFileToSting(string filename)
+        {
             FileStream fs = System.IO.File.OpenRead(filename);
             byte[] data = new byte[fs.Length];
             byte[] res = null;
@@ -128,7 +128,7 @@ namespace TEAMModelOS.SDK.Extension.JwtAuth.JwtHelper
             }
             catch (Exception ex)
             {
-                throw new Exception("",ex);
+                throw new Exception("", ex);
             }
             finally
             {

+ 24 - 16
TEAMModelOS.Service/Common/Implements/LoginInfoService.cs

@@ -52,9 +52,9 @@ namespace TEAMModelOS.Service.Common.Implements
                 if (login != null && !string.IsNullOrEmpty(login.Token))
                 {
                     result.CheckTicket = true;
-                    string token = CreateJwtToken(login);
+                    JwtResponse token = CreateJwtToken(login);
                     result.JwtToken = token;
-                    login.Token = token;
+                    login.Token = token.Access_token;
                     await _repository.Update<LoginInfo>(login);
                     return result;
                 }
@@ -78,8 +78,6 @@ namespace TEAMModelOS.Service.Common.Implements
                     JosnRPCResponse<TeamModelIdInfo> response = MessagePackHelper.JsonToObject<JosnRPCResponse<TeamModelIdInfo>>(jsonStr);
                     if (response.error == null && response != null)
                     {
-
-
                         result.CheckTicket = true;
                         LoginInfo loginInfo = new LoginInfo
                         {
@@ -91,10 +89,23 @@ namespace TEAMModelOS.Service.Common.Implements
                             Ticket = ticketInfo.Ticket,
                             CountryCode = response.result.countryCode
                         };
-                        string jwtToken = CreateJwtToken(loginInfo);
-                        loginInfo.Token = jwtToken;
+                        TeamModelUser user= await _repository.FindOneByKey<TeamModelUser>("TeamModelId", response.result.id);
+                        if (user == null || string.IsNullOrEmpty(user.RowKey))
+                        {
+                            user = new TeamModelUser { RowKey = Guid.NewGuid().ToString(), PartitionKey = loginInfo.CountryCode ,RegisterTime=DateTimeHelper.ConvertToTimeStamp13(DateTime.Now) };
+                        }
+                        user.Cellphone = response.result.cellphone;
+                        user.NickName = response.result.name;
+                        if (string.IsNullOrEmpty(user.FullName)) {
+                            user.FullName = response.result.name;
+                        }
+                        user.TeamModelId = response.result.id;
+                        user.CountryCode = response.result.countryCode;
+                        JwtResponse jwtToken = CreateJwtToken(loginInfo);
+                        loginInfo.Token = jwtToken.Access_token;
                         result.JwtToken = jwtToken;
-                        SaveLoginInfoAsync(loginInfo);
+                        await _repository.Save<LoginInfo>(loginInfo);
+                        await _repository.SaveOrUpdate<TeamModelUser>(user);
                         return result;
                     }
                     else
@@ -125,14 +136,14 @@ namespace TEAMModelOS.Service.Common.Implements
                         }
                     }
                 }
-                Dictionary<string, Object> msp = new Dictionary<string, object>
+                Dictionary<string, object> msp = new Dictionary<string, object>
                 {
                     { "Token", ticketInfo.Token }
                 };
                 LoginInfo loginInfo = _repository.FindOneByDict<LoginInfo>(msp).Result;
                 if (loginInfo != null && !string.IsNullOrEmpty(loginInfo.Token))
                 {
-                    return new LoginResult { JwtToken = loginInfo.Token, CheckTicket = true };
+                    return new LoginResult { JwtToken = new JwtResponse { Access_token=loginInfo.Token ,Scope=loginInfo.Scope}, CheckTicket = true };
                 }
                 else
                 {
@@ -140,11 +151,8 @@ namespace TEAMModelOS.Service.Common.Implements
                 }
             }
         }
-        public string CreateJwtToken(LoginInfo loginInfo)
+        public JwtResponse CreateJwtToken(LoginInfo loginInfo)
         {
-            //List<ContestRoleUser> roots = BaseConfigModel.GetAppSettings<List<ContestRoleUser>>("RoleUser:Root");
-            //List<ContestRoleUser> admins = BaseConfigModel.GetAppSettings<List<ContestRoleUser>>("RoleUser:Admin");
-
             List<RoleUser> roots = BaseConfigModel.Configuration.GetSection("RoleUser:Root").Get<List<RoleUser>>();
             List<RoleUser> admins = BaseConfigModel.Configuration.GetSection("RoleUser:Admin").Get<List<RoleUser>>();
             string role = "";
@@ -174,12 +182,12 @@ namespace TEAMModelOS.Service.Common.Implements
             model.Claims.Add(new Claim(JwtClaimTypes.PhoneNumber, loginInfo.Phone));
             model.Roles.Add(role);
             JwtResponse jwtResponse = JwtHelper.IssueJWT(model, _options.Value);
-            return jwtResponse.access_token;
+            return jwtResponse;
         }
 
-        public LoginInfo SaveLoginInfoAsync(LoginInfo loginInfo)
+        public Task<LoginInfo> SaveLoginInfoAsync(LoginInfo loginInfo)
         {
-            return _repository.Save<LoginInfo>(loginInfo).Result;
+            return _repository.Save<LoginInfo>(loginInfo);
         }
     }
 }

+ 6 - 6
TEAMModelOS.Service/Syllabus/Implements/SyllabusService.cs

@@ -24,11 +24,11 @@ namespace TEAMModelOS.Service.Syllabus.Implements
             List<SyllabusTree> nodes = new List<SyllabusTree>();
             TreeToList(trees, nodes);
             List<SyllabusNode> nods = MessagePackHelper.JsonToObject<List<SyllabusNode>>(MessagePackHelper.ObjectToJson(nodes));
-            string pk = Guid.NewGuid().ToString();
-            foreach (SyllabusNode node in nods) {
-                node.RowKey = node.Id;
-                node.PartitionKey = pk;
-            }
+            //string pk = Guid.NewGuid().ToString();
+            //foreach (SyllabusNode node in nods) {
+            //    //node.RowKey = node.Id;
+            //    node.PartitionKey = pk;
+            //}
              await _azureTableDBRepository.SaveOrUpdateAll<SyllabusNode>(nods);
             List<SyllabusTree> treess = ListToTree(nods);
             return treess;
@@ -52,7 +52,7 @@ namespace TEAMModelOS.Service.Syllabus.Implements
         {
             List<SyllabusTree> list = MessagePackHelper.JsonToObject<List<SyllabusTree>>(MessagePackHelper.ObjectToJson(noes));
  
-            var lookup = list.ToDictionary(n => n.Id, n => n);
+            var lookup = list.ToDictionary(n => n.RowKey, n => n);
             return GetChild(list, lookup);
         }
 

+ 3 - 3
TEAMModelOS/Controllers/Common/LoginController.cs

@@ -92,10 +92,10 @@ namespace TEAMModelOS.Controllers.Common
         /// </summary>
         /// <returns></returns>
         [HttpPost("authentication")]
-        [Authorize]
-        public Object Authentication()
+        [Authorize("Bearer")]
+        public object Authentication()
         {
-            return "";
+            return "aaa";
         }
         [AllowAnonymous]
        

+ 1 - 1
TEAMModelOS/appsettings.Development.json

@@ -74,7 +74,7 @@
   "JwtSetting": {
     "SecurityKey": "JwtBearerSample_11231~#$%#%^2235",
     "Issuer": "HaBook", //签发者
-    "Audience": "Habook.TeamModel.Contest",
+    "Audience": "TEAMModelOS",
     "JwtClient": [
       {
         "Name": "WebApp",