diff --git "a/\346\242\201\345\220\257\351\221\253/2022-0629 \347\254\254\345\215\201\345\233\233\346\254\241\347\254\224\350\256\260.md" "b/\346\242\201\345\220\257\351\221\253/2022-0629 \347\254\254\345\215\201\345\233\233\346\254\241\347\254\224\350\256\260.md"
new file mode 100644
index 0000000000000000000000000000000000000000..4f214fc33cf6a934a5deb761b2874ae753934481
--- /dev/null
+++ "b/\346\242\201\345\220\257\351\221\253/2022-0629 \347\254\254\345\215\201\345\233\233\346\254\241\347\254\224\350\256\260.md"
@@ -0,0 +1,66 @@
+# .NET 6 新特性 —— Random.Shared Intro
+```
+最近微软发了一篇 .NET 6 性能提升的博客文章,里面提到了很多有趣的东西,其中有一个是 Random.Shared
+
+这是一个只读的静态属性,并且是一个线程安全的对象,这个东西可以帮助我们简化 Random 对象的使用
+
+Before
+
+首先我们需要知道 Random 不是线程安全的,所以我们如果要在多线程下用 Random 的话,通常需要考虑线程安全问题
+
+既然不是线程安全的,那我们用的时候创建一个就好了,每次都 new 一个,但是这样的话一来代码不够简洁,二来可能会创建比较多的 Random 对象,那么不使用的时候每次 new 要怎么做呢?
+
+比较简单的做法就是加一个锁,如下所示:
+
+publicstaticclassRandomGen1
+
+{
+
+privatestaticRandom _inst = newRandom;
+
+publicstaticintNext( )
+
+{
+
+lock(_inst) return_inst.Next;
+
+}
+
+}
+
+但是这样的话会导致获取锁的效率相对来说会比较低,每次还需要去先拿到锁,所以也有别的解法:
+
+publicstaticclassRandomGen2
+
+{
+
+privatestaticRandom _global = newRandom;
+
+[ ThreadStatic]
+
+privatestaticRandom _local;
+
+publicstaticintNext( )
+
+{
+
+Random inst = _local;
+
+if(inst == null)
+
+{
+
+intseed;
+
+lock(_global) seed = _global.Next;
+
+_local = inst = newRandom(seed);
+
+}
+
+returninst.Next;
+
+}
+
+}
+```
\ No newline at end of file
diff --git "a/\346\242\201\345\220\257\351\221\253/2022-0701 \347\254\254\345\215\201\344\272\224\346\254\241\347\254\224\350\256\260.md" "b/\346\242\201\345\220\257\351\221\253/2022-0701 \347\254\254\345\215\201\344\272\224\346\254\241\347\254\224\350\256\260.md"
new file mode 100644
index 0000000000000000000000000000000000000000..817e8cd15d1e81ebd18c09cb870206f96050251a
--- /dev/null
+++ "b/\346\242\201\345\220\257\351\221\253/2022-0701 \347\254\254\345\215\201\344\272\224\346\254\241\347\254\224\350\256\260.md"
@@ -0,0 +1,166 @@
+# 定义审计日志
+```js
+using AuditLogDemo.Models;
+using AuditLogDemo.Services;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.Controllers;
+using Microsoft.AspNetCore.Mvc.Filters;
+using Microsoft.Extensions.Logging;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Reflection;
+using System.Threading.Tasks;
+
+namespace AuditLogDemo.Fliters
+{
+ public class AuditLogActionFilter : IAsyncActionFilter
+ {
+ ///
+ /// 审计日志服务对象
+ ///
+ private readonly IAuditLogService _auditLogService;
+ ///
+ /// 登录用户
+ ///
+ private readonly ISession _Session;
+ ///
+ /// 日志记录
+ ///
+ private readonly ILogger _logger;
+
+ public AuditLogActionFilter(
+ IAuditLogService auditLogService,
+ ISession Session,
+ ILogger logger
+ )
+ {
+ _Session = Session;
+ _logger = logger;
+ _auditLogService = auditLogService;
+ }
+
+ public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
+ {
+ // 判断是否写日志
+ if (!ShouldSaveAudit(context))
+ {
+ await next();
+ return;
+ }
+ //接口Type
+ var type = (context.ActionDescriptor as ControllerActionDescriptor).ControllerTypeInfo.AsType();
+ //方法信息
+ var method = (context.ActionDescriptor as ControllerActionDescriptor).MethodInfo;
+ //方法参数
+ var arguments = context.ActionArguments;
+ //开始计时
+ var stopwatch = Stopwatch.StartNew();
+ var auditInfo = new AuditInfo
+ {
+ UserInfo = _Session?.Id,
+ ServiceName = type != null ? type.FullName.TruncateWithPostfix(EntityDefault.FieldsLength250) : "",
+ MethodName = method.Name.TruncateWithPostfix(EntityDefault.FieldsLength250),
+ ////请求参数转Json
+ Parameters = JsonConvert.SerializeObject(arguments),
+ ExecutionTime = DateTime.Now,
+ BrowserInfo = context.HttpContext.Request.Headers["User-Agent"].ToString().TruncateWithPostfix(EntityDefault.FieldsLength250),
+ ClientIpAddress = context.HttpContext.Connection.RemoteIpAddress.ToString().TruncateWithPostfix(EntityDefault.FieldsLength50),
+ //ClientName = _clientInfoProvider.ComputerName.TruncateWithPostfix(EntityDefault.FieldsLength100),
+ Id = Guid.NewGuid().ToString()
+ };
+
+ ActionExecutedContext result = null;
+ try
+ {
+ result = await next();
+ if (result.Exception != null && !result.ExceptionHandled)
+ {
+ auditInfo.Exception = result.Exception;
+ }
+ }
+ catch (Exception ex)
+ {
+ auditInfo.Exception = ex;
+ throw;
+ }
+ finally
+ {
+ stopwatch.Stop();
+ auditInfo.ExecutionDuration = Convert.ToInt32(stopwatch.Elapsed.TotalMilliseconds);
+
+ if (result != null)
+ {
+ switch (result.Result)
+ {
+ case ObjectResult objectResult:
+ auditInfo.ReturnValue = JsonConvert.SerializeObject(objectResult.Value);
+ break;
+
+ case JsonResult jsonResult:
+ auditInfo.ReturnValue = JsonConvert.SerializeObject(jsonResult.Value);
+ break;
+
+ case ContentResult contentResult:
+ auditInfo.ReturnValue = contentResult.Content;
+ break;
+ }
+ }
+ Console.WriteLine(auditInfo.ToString());
+ //保存审计日志
+ await _auditLogService.SaveAsync(auditInfo);
+ }
+ }
+
+ ///
+ /// 是否需要记录审计
+ ///
+ ///
+ ///
+ private bool ShouldSaveAudit(ActionExecutingContext context)
+ {
+ if (!(context.ActionDescriptor is ControllerActionDescriptor))
+ return false;
+ var methodInfo = (context.ActionDescriptor as ControllerActionDescriptor).MethodInfo;
+
+ if (methodInfo == null)
+ {
+ return false;
+ }
+
+ if (!methodInfo.IsPublic)
+ {
+ return false;
+ }
+
+ if (methodInfo.GetCustomAttribute() != null)
+ {
+ return true;
+ }
+
+ if (methodInfo.GetCustomAttribute() != null)
+ {
+ return false;
+ }
+
+ var classType = methodInfo.DeclaringType;
+ if (classType != null)
+ {
+ if (classType.GetTypeInfo().GetCustomAttribute() != null)
+ {
+ return true;
+ }
+
+ if (classType.GetTypeInfo().GetCustomAttribute() != null)
+ {
+ return false;
+ }
+ }
+ return false;
+ }
+ }
+}
+```
\ No newline at end of file
diff --git "a/\346\242\201\345\220\257\351\221\253/2022-0702 \347\254\254\345\215\201\345\205\255\346\254\241\347\254\224\350\256\260.md" "b/\346\242\201\345\220\257\351\221\253/2022-0702 \347\254\254\345\215\201\345\205\255\346\254\241\347\254\224\350\256\260.md"
new file mode 100644
index 0000000000000000000000000000000000000000..fc4f3f2c5703e0315199514990e1524b2fb61272
--- /dev/null
+++ "b/\346\242\201\345\220\257\351\221\253/2022-0702 \347\254\254\345\215\201\345\205\255\346\254\241\347\254\224\350\256\260.md"
@@ -0,0 +1,114 @@
+# 一、验证Token
+```js
+#region 验证token
+
+if (!string.IsNullOrEmpty(Token))
+
+{
+
+int m = new Bll.Api.Common().PUB_VerificationToken(Token);
+
+if (m <= 0)
+
+{
+
+ReturnStr = "{\"result\":\"" + (int)KeyEnum.AppReturn.失败 + "\",\"msg\":\"登录失效\",\"data\":\"\"}";
+
+result = new HttpResponseMessage { Content = new StringContent(ReturnStr, Encoding.GetEncoding("UTF-8"), "application/json") };
+
+return result;
+
+}
+
+}
+
+else
+
+{
+
+ReturnStr = "{\"result\":\"" + (int)KeyEnum.AppReturn.失败 + "\",\"msg\":\"token不能为空\",\"data\":\"\"}";
+
+result = new HttpResponseMessage { Content = new StringContent(ReturnStr, Encoding.GetEncoding("UTF-8"), "application/json") };
+
+return result;
+
+}
+
+#endregion 验证token
+```
+# 二、调用验证方法
+```js
+public int PUB_VerificationToken(string token)
+
+{
+
+int result = 0;
+
+return 1;
+
+string secretKey = ConfigurationManager.AppSettings["token_secretKey"].ToString();//加密秘钥
+
+if (!string.IsNullOrEmpty(token))
+
+{
+
+try
+
+{
+
+byte[] key = Encoding.UTF8.GetBytes(secretKey);
+
+IJsonSerializer serializer = new JsonNetSerializer();
+
+IDateTimeProvider provider = new UtcDateTimeProvider();
+
+IJwtValidator validator = new JwtValidator(serializer, provider);
+
+IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
+
+IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder);
+
+//解密
+
+var json = decoder.DecodeToObject(token, key, verify: true);
+
+if (json != null)
+
+{
+
+//判断口令过期时间
+
+if (json.ExpiryDateTime < DateTime.Now)
+
+{
+
+result = -1;
+
+}
+
+else
+
+{
+
+result = 1;
+
+}
+
+}
+
+}
+
+catch (Exception ex)
+
+{
+
+result = 0;
+
+}
+
+}
+
+return result;
+
+}
+```
\ No newline at end of file