Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
31df4a7593 | ||
|
|
dbc05c13ee | ||
|
|
e90cc2d86e | ||
|
|
3cbd8b7559 | ||
|
|
d54b71badb | ||
|
|
ddeb2948b7 | ||
|
|
fb1ce7d931 | ||
|
|
c117d9ef1f | ||
|
|
9b38ee9b39 | ||
|
|
116dd1a808 | ||
|
|
26753657b8 | ||
|
|
62ffe47d25 | ||
|
|
bb2f4641a3 | ||
|
|
aadc4128f0 | ||
|
|
a8ce74f35d | ||
|
|
44ed8dfd3c | ||
|
|
a7261fde58 | ||
|
|
453a15b9ad | ||
|
|
5a04f831a7 | ||
|
|
fdfde570c7 | ||
|
|
874f5b6cef | ||
|
|
86ec43f676 | ||
|
|
66334d6535 | ||
|
|
608fb26aa2 | ||
|
|
c4e852a0df | ||
|
|
d88ee5f50d | ||
|
|
ad53bb3530 |
@@ -0,0 +1,34 @@
|
|||||||
|
name: CI
|
||||||
|
|
||||||
|
on: [create]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build Project
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- name: Setup .NET Core
|
||||||
|
uses: actions/setup-dotnet@v1
|
||||||
|
with:
|
||||||
|
dotnet-version: '3.1.101'
|
||||||
|
- name: Build
|
||||||
|
run: dotnet build
|
||||||
|
|
||||||
|
publish:
|
||||||
|
needs: build
|
||||||
|
name: Publish Project to Nuget
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- name: Setup .NET Core
|
||||||
|
uses: actions/setup-dotnet@v1
|
||||||
|
with:
|
||||||
|
dotnet-version: '3.1.101'
|
||||||
|
- name: Publish
|
||||||
|
run: |
|
||||||
|
version=`git describe --tags`
|
||||||
|
dotnet pack --configuration release -p:PackageVersion=$version
|
||||||
|
dotnet nuget push bin/release/YY-Tech.YYApi.$version.nupkg -k ${APIKEY} -s https://www.nuget.org/api/v2/package
|
||||||
|
env:
|
||||||
|
APIKEY: ${{ secrets.APPKEY }}
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
name: PublishToNuget
|
|
||||||
|
|
||||||
on: [push]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
name: publish to nuget
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
with:
|
|
||||||
fetch-depth: 2
|
|
||||||
- name: Publish NuGet
|
|
||||||
uses: rohith/publish-nuget@v1.0.3
|
|
||||||
with:
|
|
||||||
nuget_key: ${{ secrets.NugetKey }}
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
# Created by .ignore support plugin (hsz.mobi)
|
# Created by .ignore support plugin (hsz.mobi)
|
||||||
### C template
|
### C template
|
||||||
# Prerequisites
|
# Prerequisites
|
||||||
|
*.sln:
|
||||||
*.d
|
*.d
|
||||||
|
|
||||||
# Object files
|
# Object files
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
using YYApi.Communications;
|
||||||
|
using YYApi.Exceptions;
|
||||||
|
|
||||||
|
namespace YYApi.Attributes
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 检测登录中间件
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
||||||
|
public class YYAuthAttribute : ActionFilterAttribute
|
||||||
|
{
|
||||||
|
private string[] Types { get; }
|
||||||
|
|
||||||
|
//默认是user登录类型
|
||||||
|
public YYAuthAttribute()
|
||||||
|
{
|
||||||
|
Types = new[] { "user" };
|
||||||
|
}
|
||||||
|
|
||||||
|
//只检测一种用户类型的快捷方式
|
||||||
|
public YYAuthAttribute(string type)
|
||||||
|
{
|
||||||
|
Types = new[] { type };
|
||||||
|
}
|
||||||
|
|
||||||
|
//设定特定类型的检测
|
||||||
|
public YYAuthAttribute(string[] types)
|
||||||
|
{
|
||||||
|
Types = types;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnActionExecuting(ActionExecutingContext context)
|
||||||
|
{
|
||||||
|
var loginInfo = (YYLoginItem)context.HttpContext.Items["LoginInfo"];
|
||||||
|
//检测是否登录
|
||||||
|
if (loginInfo == null)
|
||||||
|
{
|
||||||
|
throw new YYApiException(401);
|
||||||
|
}
|
||||||
|
//检测用户类型
|
||||||
|
if (Types.Intersect(loginInfo.Type).Count() == 0)
|
||||||
|
{
|
||||||
|
throw new YYApiException(403);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,20 +1,22 @@
|
|||||||
using Swashbuckle.AspNetCore.Annotations;
|
using System;
|
||||||
|
using Swashbuckle.AspNetCore.Annotations;
|
||||||
|
|
||||||
namespace YYApi.Helpers
|
namespace YYApi.Attributes
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 快捷自定义接口文档类
|
/// 快捷自定义接口文档类
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ApiDoc : SwaggerOperationAttribute
|
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
|
||||||
|
public class YYDocAttribute : SwaggerOperationAttribute
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 定义接口说明
|
/// 定义接口说明
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tag">接口分组</param>
|
/// <param name="tag">接口分组</param>
|
||||||
/// <param name="name">接口名称</param>
|
/// <param name="name">接口名称</param>
|
||||||
public ApiDoc(string tag, string name)
|
public YYDocAttribute(string tag, string name)
|
||||||
{
|
{
|
||||||
Tags = new[] {tag};
|
Tags = new[] { tag };
|
||||||
Summary = name;
|
Summary = name;
|
||||||
// Consumes = new[] {"application/json"};
|
// Consumes = new[] {"application/json"};
|
||||||
// Produces = new[] {"application/json"};
|
// Produces = new[] {"application/json"};
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
namespace YYApi.Communications
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 只有ID的请求
|
||||||
|
/// </summary>
|
||||||
|
public class YYIdOnlyRequest
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 基础分页请求
|
||||||
|
/// </summary>
|
||||||
|
public class YYBasePageRequest
|
||||||
|
{
|
||||||
|
public int Page { get; set; }
|
||||||
|
public int Count { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@ namespace YYApi.Communications
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 基础相应
|
/// 基础相应
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class BaseResponse
|
public class YYBaseResponse
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 错误代码
|
/// 错误代码
|
||||||
@@ -25,6 +25,7 @@ namespace YYApi.Communications
|
|||||||
private readonly Dictionary<int, string> MsgBox = new Dictionary<int, string>()
|
private readonly Dictionary<int, string> MsgBox = new Dictionary<int, string>()
|
||||||
{
|
{
|
||||||
{200, "成功"},
|
{200, "成功"},
|
||||||
|
{204, "没有数据"},
|
||||||
{400, "参数错误"},
|
{400, "参数错误"},
|
||||||
{401, "需要登录"},
|
{401, "需要登录"},
|
||||||
{403, "无权访问"},
|
{403, "无权访问"},
|
||||||
@@ -35,7 +36,7 @@ namespace YYApi.Communications
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 返回一个成功的空结果
|
/// 返回一个成功的空结果
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public BaseResponse()
|
public YYBaseResponse()
|
||||||
{
|
{
|
||||||
SetCode(200);
|
SetCode(200);
|
||||||
}
|
}
|
||||||
@@ -45,7 +46,7 @@ namespace YYApi.Communications
|
|||||||
/// 返回指定代码的描述
|
/// 返回指定代码的描述
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="code">错误代码</param>
|
/// <param name="code">错误代码</param>
|
||||||
public BaseResponse(int code)
|
public YYBaseResponse(int code)
|
||||||
{
|
{
|
||||||
SetCode(code);
|
SetCode(code);
|
||||||
}
|
}
|
||||||
@@ -55,7 +56,7 @@ namespace YYApi.Communications
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="code">错误代码</param>
|
/// <param name="code">错误代码</param>
|
||||||
/// <param name="message">错误信息</param>
|
/// <param name="message">错误信息</param>
|
||||||
public BaseResponse(int code, string message)
|
public YYBaseResponse(int code, string message)
|
||||||
{
|
{
|
||||||
SetCodeMsg(code, message);
|
SetCodeMsg(code, message);
|
||||||
}
|
}
|
||||||
@@ -94,19 +95,37 @@ namespace YYApi.Communications
|
|||||||
{
|
{
|
||||||
IgnoreReadOnlyProperties = true,
|
IgnoreReadOnlyProperties = true,
|
||||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||||
Converters = {new JsonStringEnumConverter()}
|
Converters = { new JsonStringEnumConverter() }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 动态内容
|
/// 动态内容分页
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T"></typeparam>
|
/// <typeparam name="T"></typeparam>
|
||||||
public class BaseResponse<T> : BaseResponse
|
public class YYBasePageResponse<T> : YYBaseResponse
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 动态内容
|
/// 动态内容列表
|
||||||
|
/// </summary>
|
||||||
|
public T List { get; set; }
|
||||||
|
//当前页码
|
||||||
|
public int Page { get; set; }
|
||||||
|
//每页条数
|
||||||
|
public int Count { get; set; }
|
||||||
|
//总计条数
|
||||||
|
public int Total { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 动态Data返回
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
public class YYBaseResponse<T> : YYBaseResponse
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 动态内容列表
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public T Data { get; set; }
|
public T Data { get; set; }
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
namespace YYApi.Communications
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 登录信息中间件
|
||||||
|
/// </summary>
|
||||||
|
public class YYLoginItem
|
||||||
|
{
|
||||||
|
//登录用户的ID
|
||||||
|
public int Id { get; set; }
|
||||||
|
//登录用户来源
|
||||||
|
public string[] Type { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
using YYApi.Communications;
|
using YYApi.Communications;
|
||||||
using YYApi.Helpers;
|
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using YYApi.Exceptions;
|
||||||
|
using YYApi.Attributes;
|
||||||
|
|
||||||
namespace YYApi.Controllers
|
namespace YYApi.Controllers
|
||||||
{
|
{
|
||||||
@@ -13,12 +14,12 @@ namespace YYApi.Controllers
|
|||||||
/// 2. 报错返回
|
/// 2. 报错返回
|
||||||
/// 3. 错误回馈页面
|
/// 3. 错误回馈页面
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class BaseController : Controller
|
public class YYBaseController : Controller
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 当前登录用户的ID
|
/// 当前登录用户的ID
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected LoginInfoItem LoginInfo => (LoginInfoItem)HttpContext.Items["LoginInfo"];
|
protected YYLoginItem LoginInfo => (YYLoginItem)HttpContext.Items["LoginInfo"];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 验证请求参数
|
/// 验证请求参数
|
||||||
@@ -46,9 +47,9 @@ namespace YYApi.Controllers
|
|||||||
/// <param name="code">错误代码</param>
|
/// <param name="code">错误代码</param>
|
||||||
/// <param name="message">错误描述(若是常规错误,代码可自动带取描述)</param>
|
/// <param name="message">错误描述(若是常规错误,代码可自动带取描述)</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
protected static void Error(int code, string message = null)
|
protected static void Error(int code = 500, string message = "")
|
||||||
{
|
{
|
||||||
throw new ApiException(code, message);
|
throw new YYApiException(code, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -57,7 +58,7 @@ namespace YYApi.Controllers
|
|||||||
/// <param name="condition">检测条件</param>
|
/// <param name="condition">检测条件</param>
|
||||||
/// <param name="code">错误代码</param>
|
/// <param name="code">错误代码</param>
|
||||||
/// <param name="message">错误描述</param>
|
/// <param name="message">错误描述</param>
|
||||||
protected static void ErrorWhen(bool condition, int code, string message = null)
|
protected static void ErrorWhen(bool condition, int code = 500, string message = "")
|
||||||
{
|
{
|
||||||
if (condition)
|
if (condition)
|
||||||
{
|
{
|
||||||
@@ -66,17 +67,25 @@ namespace YYApi.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 错误回馈页面
|
/// 检测给定的变量是否为NUll
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="condition">检测条件</param>
|
||||||
/// <param name="code">错误代码</param>
|
/// <param name="code">错误代码</param>
|
||||||
/// <returns></returns>
|
/// <param name="message">错误描述</param>
|
||||||
[HttpGet("exception/{code:int}")]
|
protected static void ErrorWhenNull(object condition, int code = 404, string message = "请求的资源不存在")
|
||||||
[ApiExplorerSettings(IgnoreApi = true)]
|
|
||||||
public BaseResponse ExceptionHandler(int code)
|
|
||||||
{
|
{
|
||||||
var response = new BaseResponse();
|
ErrorWhen(condition == null, code, message);
|
||||||
response.SetCode(code);
|
|
||||||
return response;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 上传文件
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
protected YYBaseResponse<string> UploadFile()
|
||||||
|
{
|
||||||
|
return new YYBaseResponse<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using YYApi.Attributes;
|
||||||
|
using YYApi.Communications;
|
||||||
|
using YYApi.Helpers;
|
||||||
|
|
||||||
|
namespace YYApi.Controllers
|
||||||
|
{
|
||||||
|
public class YYCommonController : YYBaseController
|
||||||
|
{
|
||||||
|
private YYAuth Auth { get; }
|
||||||
|
|
||||||
|
public YYCommonController(YYAuth auth)
|
||||||
|
{
|
||||||
|
Auth = auth;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 错误回馈页面
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="code">错误代码</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet("exception/{code:int}")]
|
||||||
|
[ApiExplorerSettings(IgnoreApi = true)]
|
||||||
|
public YYBaseResponse ExceptionHandler(int code)
|
||||||
|
{
|
||||||
|
var response = new YYBaseResponse();
|
||||||
|
response.SetCode(code);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检测用户登陆的控制器
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost("/auth/check"), YYDoc("认证", "检测登陆")]
|
||||||
|
public YYBaseResponse<int> CheckLogin()
|
||||||
|
{
|
||||||
|
ErrorWhenNull(LoginInfo, 401);
|
||||||
|
return new YYBaseResponse<int> { Data = LoginInfo.Id };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 退出登陆
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost("/auth/logout"), YYDoc("认证", "退出登陆")]
|
||||||
|
public YYBaseResponse Logout()
|
||||||
|
{
|
||||||
|
string token = null;
|
||||||
|
|
||||||
|
if (Request.Headers.ContainsKey("Token"))
|
||||||
|
{
|
||||||
|
token = Request.Headers["Token"];
|
||||||
|
}
|
||||||
|
Auth.Logout(token);
|
||||||
|
return new YYBaseResponse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
namespace YYApi.Exceptions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Api错误捕获异常
|
||||||
|
/// </summary>
|
||||||
|
public class YYApiException : Exception
|
||||||
|
{
|
||||||
|
public int Code { get; }
|
||||||
|
|
||||||
|
public YYApiException(int code, string message = "") : base(message)
|
||||||
|
{
|
||||||
|
Code = code;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+67
-33
@@ -4,6 +4,7 @@ using Microsoft.AspNetCore.Builder;
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.OpenApi.Models;
|
using Microsoft.OpenApi.Models;
|
||||||
using Swashbuckle.AspNetCore.SwaggerUI;
|
using Swashbuckle.AspNetCore.SwaggerUI;
|
||||||
|
using YYApi.Middlewares;
|
||||||
|
|
||||||
namespace YYApi
|
namespace YYApi
|
||||||
{
|
{
|
||||||
@@ -12,18 +13,10 @@ namespace YYApi
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class Extensions
|
public static class Extensions
|
||||||
{
|
{
|
||||||
/// <summary>
|
//**********快捷添加**************
|
||||||
/// 添加自定义授权认证中间价
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="builder"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static IServiceCollection AddAuth(this IServiceCollection builder)
|
|
||||||
{
|
|
||||||
return builder.AddScoped<Auth>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 添加整个YYAPI
|
/// 添加整个YYAPI,同时增加CORS规则
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="builder"></param>
|
/// <param name="builder"></param>
|
||||||
/// <param name="title"></param>
|
/// <param name="title"></param>
|
||||||
@@ -32,7 +25,44 @@ namespace YYApi
|
|||||||
public static IServiceCollection AddYYApi(this IServiceCollection builder, string title,
|
public static IServiceCollection AddYYApi(this IServiceCollection builder, string title,
|
||||||
string description = null)
|
string description = null)
|
||||||
{
|
{
|
||||||
return builder.AddAuth().AddApiDoc(title, description);
|
return builder.AddYYAuth().AddYYDoc(title, description).AddCors().AddYYUpload();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 使用所有YYApi自定义中间件
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder"></param>
|
||||||
|
/// <param name="title"></param>
|
||||||
|
/// <param name="staticFileroot"></param>
|
||||||
|
/// <param name="submitMethods"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IApplicationBuilder UseYYApi(this IApplicationBuilder builder, string title = "API文档", params SubmitMethod[] submitMethods)
|
||||||
|
{
|
||||||
|
return builder.UseYYException().UseYYDoc(title, submitMethods).UseMiddleware<YYAuthMiddleware>().UseCors(x => x.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin()).UseYYUpload();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//*********组件快捷方式*************
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 添加自定义授权认证中间价
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IServiceCollection AddYYAuth(this IServiceCollection builder)
|
||||||
|
{
|
||||||
|
return builder.AddScoped<YYAuth>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 添加Base64上传组件
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IServiceCollection AddYYUpload(this IServiceCollection builder)
|
||||||
|
{
|
||||||
|
return builder.AddSingleton<YYUpload>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -42,12 +72,12 @@ namespace YYApi
|
|||||||
/// <param name="title">文档标题</param>
|
/// <param name="title">文档标题</param>
|
||||||
/// <param name="description">文档描述</param>
|
/// <param name="description">文档描述</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IServiceCollection AddApiDoc(this IServiceCollection builder, string title,
|
public static IServiceCollection AddYYDoc(this IServiceCollection builder, string title,
|
||||||
string description = null)
|
string description = null)
|
||||||
{
|
{
|
||||||
return builder.AddSwaggerGen(x =>
|
return builder.AddSwaggerGen(x =>
|
||||||
{
|
{
|
||||||
x.SwaggerDoc("api", new OpenApiInfo {Title = title, Description = description});
|
x.SwaggerDoc("api", new OpenApiInfo { Title = title, Description = description });
|
||||||
x.EnableAnnotations();
|
x.EnableAnnotations();
|
||||||
x.AddSecurityRequirement(new OpenApiSecurityRequirement
|
x.AddSecurityRequirement(new OpenApiSecurityRequirement
|
||||||
{
|
{
|
||||||
@@ -60,18 +90,33 @@ namespace YYApi
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
x.AddSecurityDefinition("HeaderToken",
|
x.AddSecurityDefinition("HeaderToken",
|
||||||
new OpenApiSecurityScheme {Name = "Token", In = ParameterLocation.Header});
|
new OpenApiSecurityScheme { Name = "Token", In = ParameterLocation.Header });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 使用异常中间价扩展
|
/// 使用异常中间价扩展
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="builder"></param>
|
/// <param name="builder"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IApplicationBuilder UseExceptionMiddleware(this IApplicationBuilder builder)
|
public static IApplicationBuilder UseYYException(this IApplicationBuilder builder)
|
||||||
{
|
{
|
||||||
return builder.UseMiddleware<ExceptionMiddleware>();
|
return builder.UseMiddleware<YYExceptionMiddleware>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 配置上传组件必须
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IApplicationBuilder UseYYUpload(this IApplicationBuilder builder)
|
||||||
|
{
|
||||||
|
return builder.UseStaticFiles(new StaticFileOptions
|
||||||
|
{
|
||||||
|
DefaultContentType = "application/x-msdownload",
|
||||||
|
ServeUnknownFileTypes = true
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -81,7 +126,7 @@ namespace YYApi
|
|||||||
/// <param name="title">文档标题</param>
|
/// <param name="title">文档标题</param>
|
||||||
/// <param name="submitMethods">文档支持的提交方式(如果不指定,默认使用POST)</param>
|
/// <param name="submitMethods">文档支持的提交方式(如果不指定,默认使用POST)</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IApplicationBuilder UseApiDoc(this IApplicationBuilder builder, string title,
|
public static IApplicationBuilder UseYYDoc(this IApplicationBuilder builder, string title,
|
||||||
params SubmitMethod[] submitMethods)
|
params SubmitMethod[] submitMethods)
|
||||||
{
|
{
|
||||||
return builder.UseSwagger(x => x.RouteTemplate = "docs/{documentName}.json").UseSwaggerUI(x =>
|
return builder.UseSwagger(x => x.RouteTemplate = "docs/{documentName}.json").UseSwaggerUI(x =>
|
||||||
@@ -111,10 +156,10 @@ namespace YYApi
|
|||||||
/// <param name="title">文档标题</param>
|
/// <param name="title">文档标题</param>
|
||||||
/// <param name="submitMethods">API提交方式定义</param>
|
/// <param name="submitMethods">API提交方式定义</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IApplicationBuilder UseDocAndException(this IApplicationBuilder builder, string title = "API文档",
|
public static IApplicationBuilder UseYYDocEx(this IApplicationBuilder builder, string title = "API文档",
|
||||||
params SubmitMethod[] submitMethods)
|
params SubmitMethod[] submitMethods)
|
||||||
{
|
{
|
||||||
return builder.UseExceptionMiddleware().UseApiDoc(title, submitMethods);
|
return builder.UseYYException().UseYYDoc(title, submitMethods);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -122,22 +167,11 @@ namespace YYApi
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="builder"></param>
|
/// <param name="builder"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static IApplicationBuilder UseAuthMiddleware(this IApplicationBuilder builder)
|
public static IApplicationBuilder UseYYAuth(this IApplicationBuilder builder)
|
||||||
{
|
{
|
||||||
return builder.UseMiddleware<AuthMiddleware>();
|
return builder.UseMiddleware<YYAuthMiddleware>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 使用所有YYApi自定义中间件
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="builder"></param>
|
|
||||||
/// <param name="title"></param>
|
|
||||||
/// <param name="submitMethods"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public static IApplicationBuilder UseYYApiMiddleware(this IApplicationBuilder builder, string title = "API文档",
|
|
||||||
params SubmitMethod[] submitMethods)
|
|
||||||
{
|
|
||||||
return builder.UseExceptionMiddleware().UseApiDoc(title, submitMethods).UseMiddleware<AuthMiddleware>();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Text.Json;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Filters;
|
|
||||||
using Microsoft.Extensions.Caching.Distributed;
|
|
||||||
|
|
||||||
namespace YYApi.Helpers
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// 认证信息获取中间件
|
|
||||||
/// </summary>
|
|
||||||
public class AuthMiddleware
|
|
||||||
{
|
|
||||||
private RequestDelegate Next { get; }
|
|
||||||
|
|
||||||
public AuthMiddleware(RequestDelegate next)
|
|
||||||
{
|
|
||||||
Next = next;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task Invoke(HttpContext httpContext, IDistributedCache cache)
|
|
||||||
{
|
|
||||||
string token = null;
|
|
||||||
if (httpContext.Request.Headers.ContainsKey("Token"))
|
|
||||||
{
|
|
||||||
token = httpContext.Request.Headers["Token"];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(token))
|
|
||||||
{
|
|
||||||
var login = cache.GetString(token);
|
|
||||||
if (login != null)
|
|
||||||
{
|
|
||||||
httpContext.Items.Add("LoginInfo", JsonSerializer.Deserialize<LoginInfoItem>(login));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Next(httpContext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 登录信息中间件
|
|
||||||
/// </summary>
|
|
||||||
public class LoginInfoItem
|
|
||||||
{
|
|
||||||
//登录用户的ID
|
|
||||||
public int Id { get; set; }
|
|
||||||
//登录用户来源
|
|
||||||
public string Type { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 检测登录中间件
|
|
||||||
/// </summary>
|
|
||||||
public class CheckAuthAttribute : ActionFilterAttribute
|
|
||||||
{
|
|
||||||
public override void OnActionExecuting(ActionExecutingContext context)
|
|
||||||
{
|
|
||||||
if (context.HttpContext.Items["LoginId"] == null)
|
|
||||||
{
|
|
||||||
throw new ApiException(401);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 认证助手
|
|
||||||
/// </summary>
|
|
||||||
public class Auth
|
|
||||||
{
|
|
||||||
private IDistributedCache Cache { get; }
|
|
||||||
|
|
||||||
public Auth(IDistributedCache cache)
|
|
||||||
{
|
|
||||||
Cache = cache;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 产生一个Token记录并返回Token
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="id"></param>
|
|
||||||
/// <returns></returns>
|
|
||||||
public string SetId(int id, string type = "user")
|
|
||||||
{
|
|
||||||
var uuid = GetUUID();
|
|
||||||
var loginItem = new LoginInfoItem
|
|
||||||
{
|
|
||||||
Id = id,
|
|
||||||
Type = type
|
|
||||||
};
|
|
||||||
Cache.SetString(uuid, JsonSerializer.Serialize(loginItem));
|
|
||||||
return uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
private string GetUUID()
|
|
||||||
{
|
|
||||||
return Guid.NewGuid().ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
using System;
|
||||||
|
using System.Text.Json;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.Caching.Distributed;
|
||||||
|
using YYApi.Communications;
|
||||||
|
|
||||||
|
namespace YYApi.Helpers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 认证助手
|
||||||
|
/// </summary>
|
||||||
|
public class YYAuth
|
||||||
|
{
|
||||||
|
private IDistributedCache Cache { get; }
|
||||||
|
|
||||||
|
public YYAuth(IDistributedCache cache)
|
||||||
|
{
|
||||||
|
Cache = cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 产生一个Token记录并返回Token
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public string Login(int id, string type = "user", string token = null)
|
||||||
|
{
|
||||||
|
return Login(id, new[] { type }, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 产生一个Token并记录用户ID角色[多角色]
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public string Login(int id, string[] type, string uuid = null)
|
||||||
|
{
|
||||||
|
if (uuid == null)
|
||||||
|
{
|
||||||
|
uuid = Guid.NewGuid().ToString();
|
||||||
|
}
|
||||||
|
var loginItem = new YYLoginItem
|
||||||
|
{
|
||||||
|
Id = id,
|
||||||
|
Type = type
|
||||||
|
};
|
||||||
|
Cache.SetString(uuid, JsonSerializer.Serialize(loginItem));
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 退出登陆
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uuid">登陆标识</param>
|
||||||
|
public void Logout(string uuid)
|
||||||
|
{
|
||||||
|
Cache.Remove(uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
|
||||||
|
namespace YYApi.Helpers
|
||||||
|
{
|
||||||
|
public class YYUpload
|
||||||
|
{
|
||||||
|
private string FilePathFolder = "/uploads/";
|
||||||
|
public string FilePath
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (!value.StartsWith("/"))
|
||||||
|
{
|
||||||
|
FilePathFolder = $"/{value}";
|
||||||
|
}
|
||||||
|
if (!FilePathFolder.EndsWith("/"))
|
||||||
|
{
|
||||||
|
FilePathFolder += "/";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return FilePathFolder;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IWebHostEnvironment Env { get; }
|
||||||
|
|
||||||
|
public YYUpload(IWebHostEnvironment env)
|
||||||
|
{
|
||||||
|
Env = env;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class YYUploadInfo
|
||||||
|
{
|
||||||
|
public string Path { get; set; }
|
||||||
|
public int Size { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 保存base64文件,如果有标头按照标头自动识别
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="base64"></param>
|
||||||
|
/// <param name="ext">扩展名</param>
|
||||||
|
/// <param name="path">存放路径</param>
|
||||||
|
/// <param name="fileName">文件名</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public YYUploadInfo SaveFile(string base64, string ext = null, string path = null, string fileName = null)
|
||||||
|
{
|
||||||
|
byte[] bt;
|
||||||
|
var filePath = FilePath + path;
|
||||||
|
if (fileName == null)
|
||||||
|
{
|
||||||
|
fileName = Guid.NewGuid().ToString();
|
||||||
|
}
|
||||||
|
var baseArr = base64.Split(";");
|
||||||
|
if (baseArr.Length == 2)
|
||||||
|
{
|
||||||
|
var info = baseArr[0].Split(":")[1].Split("/");
|
||||||
|
if (path == null)
|
||||||
|
{
|
||||||
|
filePath += $"{info[0]}/";
|
||||||
|
}
|
||||||
|
if (ext == null)
|
||||||
|
{
|
||||||
|
ext = info[1];
|
||||||
|
}
|
||||||
|
var data = baseArr[1].Split(",");
|
||||||
|
bt = Convert.FromBase64String(data[1]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bt = Convert.FromBase64String(base64);
|
||||||
|
}
|
||||||
|
var fn = fileName + (string.IsNullOrEmpty(ext) ? string.Empty : $".{ext}");
|
||||||
|
return WriteFile(filePath, fn, bt);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 把数据写入文件
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filePath"></param>
|
||||||
|
/// <param name="fileName"></param>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public YYUploadInfo WriteFile(string filePath, string fileName, byte[] data)
|
||||||
|
{
|
||||||
|
var realPath = Directory.GetCurrentDirectory() + "/wwwroot" + filePath;
|
||||||
|
if (!Directory.Exists(realPath))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(realPath);
|
||||||
|
}
|
||||||
|
File.WriteAllBytes(realPath + fileName, data);
|
||||||
|
return new YYUploadInfo
|
||||||
|
{
|
||||||
|
Path = filePath + fileName,
|
||||||
|
Size = data.Length
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ using System.Text.RegularExpressions;
|
|||||||
|
|
||||||
namespace YYApi.Helpers
|
namespace YYApi.Helpers
|
||||||
{
|
{
|
||||||
public static class Util
|
public static class YYUtil
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 检测手机号是否正确
|
/// 检测手机号是否正确
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
using System;
|
||||||
|
using Hangfire.Dashboard;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using StackExchange.Redis;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
|
namespace YYApi.JobService
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Redis缓存Key定义
|
||||||
|
/// </summary>
|
||||||
|
public struct CacheKey
|
||||||
|
{
|
||||||
|
public const string HangfireDashboardAuthPrefix = "{hangfire}:dashboard:auth:";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// HangFire Dashboard Digest认证.
|
||||||
|
/// </summary>
|
||||||
|
public class YYHFDashboardAuth : IDashboardAuthorizationFilter
|
||||||
|
{
|
||||||
|
private IConfiguration _config { get; }
|
||||||
|
private IDatabase _redis { get; }
|
||||||
|
public YYHFDashboardAuth(IConfiguration config, IDatabase redis)
|
||||||
|
{
|
||||||
|
_redis = redis;
|
||||||
|
_config = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Authorize(DashboardContext context)
|
||||||
|
{
|
||||||
|
var http = context.GetHttpContext();
|
||||||
|
if (http.Request.Headers.ContainsKey("Authorization"))
|
||||||
|
{
|
||||||
|
var authObj = _processAuthHeader(http.Request.Headers["Authorization"].ToString());
|
||||||
|
if (http.Request.QueryString.ToString().Contains("logout"))
|
||||||
|
{
|
||||||
|
_redis.KeyDelete(CacheKey.HangfireDashboardAuthPrefix + authObj["opaque"]);
|
||||||
|
_redirect(http);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (authObj["username"] == _config["Hangfire:User"])
|
||||||
|
{
|
||||||
|
var a1 = _md5(string.Format("{0}:Need Login:{1}", authObj["username"], _config["Hangfire:Pass"]));
|
||||||
|
var a2 = _md5(string.Format("{0}:{1}", http.Request.Method, authObj["uri"]));
|
||||||
|
var nonce = _redis.StringGet(CacheKey.HangfireDashboardAuthPrefix + authObj["opaque"]);
|
||||||
|
var validCode = _md5(string.Format("{0}:{1}:{2}:{3}:{4}:{5}", a1, nonce, authObj["nc"], authObj["cnonce"], authObj["qop"], a2));
|
||||||
|
if (authObj["response"] == validCode)
|
||||||
|
{
|
||||||
|
_redis.StringSet(CacheKey.HangfireDashboardAuthPrefix + authObj["opaque"], nonce, new TimeSpan(0, 5, 0));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_challenge(http);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生成401认证header
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The challenge.</returns>
|
||||||
|
private void _challenge(HttpContext http)
|
||||||
|
{
|
||||||
|
var response = http.Response;
|
||||||
|
var guid = Guid.NewGuid().ToString();
|
||||||
|
var opaque = _md5(guid);
|
||||||
|
_redis.StringSet(CacheKey.HangfireDashboardAuthPrefix + opaque, guid, new TimeSpan(0, 0, 30));
|
||||||
|
response.StatusCode = 401;
|
||||||
|
response.Headers.Add("WWW-Authenticate", string.Format("Digest realm=\"Need Login\",qop=\"auth\",nonce=\"{0}\",opaque=\"{1}\"", guid, opaque));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 跳转到页面不附加参数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="http">Http.</param>
|
||||||
|
private void _redirect(HttpContext http)
|
||||||
|
{
|
||||||
|
var response = http.Response;
|
||||||
|
response.StatusCode = 302;
|
||||||
|
response.Headers.Add("Location", (http.Request.PathBase + http.Request.Path).ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 处理DigestHeader中的参数为字典
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The auth header.</returns>
|
||||||
|
/// <param name="authData">Auth data.</param>
|
||||||
|
private Dictionary<string, string> _processAuthHeader(string authData)
|
||||||
|
{
|
||||||
|
var authDataArray = authData.Replace("Digest ", string.Empty).Replace("\"", string.Empty).Split(", ");
|
||||||
|
var authDic = new Dictionary<string, string>();
|
||||||
|
foreach (var item in authDataArray)
|
||||||
|
{
|
||||||
|
var tmp = item.Split("=", 2);
|
||||||
|
authDic.Add(tmp[0], tmp[1]);
|
||||||
|
}
|
||||||
|
return authDic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 计算字符串32位MD5
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The md5.</returns>
|
||||||
|
/// <param name="source">Source.</param>
|
||||||
|
private string _md5(string source)
|
||||||
|
{
|
||||||
|
byte[] sor = Encoding.UTF8.GetBytes(source);
|
||||||
|
var md5 = MD5.Create();
|
||||||
|
byte[] result = md5.ComputeHash(sor);
|
||||||
|
StringBuilder strbul = new StringBuilder(40);
|
||||||
|
for (int i = 0; i < result.Length; i++)
|
||||||
|
{
|
||||||
|
strbul.Append(result[i].ToString("x2"));//加密结果"x2"结果为32位,"x3"结果为48位,"x4"结果为64位
|
||||||
|
|
||||||
|
}
|
||||||
|
return strbul.ToString();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using System;
|
||||||
|
namespace YYApi.JobService
|
||||||
|
{
|
||||||
|
public class JobDashboardConfig
|
||||||
|
{
|
||||||
|
public string Path { get; set; }
|
||||||
|
public string Username { get; set; }
|
||||||
|
public string Password { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using System;
|
||||||
|
namespace YYApi.JobService
|
||||||
|
{
|
||||||
|
public class JobStorage
|
||||||
|
{
|
||||||
|
public JobStorage()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
using System.Text.Json;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.Caching.Distributed;
|
||||||
|
using YYApi.Communications;
|
||||||
|
|
||||||
|
namespace YYApi.Middlewares
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 认证信息获取中间件
|
||||||
|
/// </summary>
|
||||||
|
public class YYAuthMiddleware
|
||||||
|
{
|
||||||
|
private RequestDelegate Next { get; }
|
||||||
|
|
||||||
|
public YYAuthMiddleware(RequestDelegate next)
|
||||||
|
{
|
||||||
|
Next = next;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task Invoke(HttpContext httpContext, IDistributedCache cache)
|
||||||
|
{
|
||||||
|
string token = null;
|
||||||
|
if (httpContext.Request.Headers.ContainsKey("Token"))
|
||||||
|
{
|
||||||
|
token = httpContext.Request.Headers["Token"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(token))
|
||||||
|
{
|
||||||
|
var login = cache.GetString(token);
|
||||||
|
if (login != null)
|
||||||
|
{
|
||||||
|
httpContext.Items.Add("LoginInfo", JsonSerializer.Deserialize<YYLoginItem>(login));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Next(httpContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,20 +2,20 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using YYApi.Communications;
|
using YYApi.Communications;
|
||||||
using Microsoft.AspNetCore.Builder;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using YYApi.Exceptions;
|
||||||
|
|
||||||
namespace YYApi.Helpers
|
namespace YYApi.Middlewares
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 异常处理中间件
|
/// 异常处理中间件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class ExceptionMiddleware
|
public class YYExceptionMiddleware
|
||||||
{
|
{
|
||||||
private RequestDelegate Next { get; }
|
private RequestDelegate Next { get; }
|
||||||
private ILogger<ExceptionMiddleware> Log { get; }
|
private ILogger<YYExceptionMiddleware> Log { get; }
|
||||||
|
|
||||||
public ExceptionMiddleware(RequestDelegate next, ILogger<ExceptionMiddleware> log)
|
public YYExceptionMiddleware(RequestDelegate next, ILogger<YYExceptionMiddleware> log)
|
||||||
{
|
{
|
||||||
Log = log;
|
Log = log;
|
||||||
Next = next;
|
Next = next;
|
||||||
@@ -23,12 +23,12 @@ namespace YYApi.Helpers
|
|||||||
|
|
||||||
public async Task InvokeAsync(HttpContext context)
|
public async Task InvokeAsync(HttpContext context)
|
||||||
{
|
{
|
||||||
var response = new BaseResponse();
|
var response = new YYBaseResponse();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await Next(context);
|
await Next(context);
|
||||||
}
|
}
|
||||||
catch (ApiException ex)
|
catch (YYApiException ex)
|
||||||
{
|
{
|
||||||
response.SetCodeMsg(ex.Code, ex.Message);
|
response.SetCodeMsg(ex.Code, ex.Message);
|
||||||
ErrorResponse(context, response);
|
ErrorResponse(context, response);
|
||||||
@@ -47,25 +47,11 @@ namespace YYApi.Helpers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="context"></param>
|
/// <param name="context"></param>
|
||||||
/// <param name="response"></param>
|
/// <param name="response"></param>
|
||||||
private void ErrorResponse(HttpContext context, BaseResponse response)
|
private void ErrorResponse(HttpContext context, YYBaseResponse response)
|
||||||
{
|
{
|
||||||
context.Response.StatusCode = 200;
|
context.Response.StatusCode = 200;
|
||||||
context.Response.Headers.Add("Content-Type", "application/json");
|
context.Response.Headers.Add("Content-Type", "application/json");
|
||||||
context.Response.WriteAsync(response.ToString());
|
context.Response.WriteAsync(response.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Api错误捕获异常
|
|
||||||
/// </summary>
|
|
||||||
public class ApiException : Exception
|
|
||||||
{
|
|
||||||
public int Code { get; }
|
|
||||||
|
|
||||||
public ApiException(int code, string message = "") : base(message)
|
|
||||||
{
|
|
||||||
Code = code;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
# YYApi 基于Asp.net Core 3的一个基础辅助包
|
# YYApi 基于Asp.net Core 3的一个基础辅助包
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
### 包含了以下组件:
|
### 包含了以下组件:
|
||||||
|
|
||||||
1. 统一的参数检测,基础认证服务
|
1. 统一的参数检测,基础认证服务
|
||||||
@@ -15,7 +17,7 @@ namespace Controllers
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取登录用户信息
|
/// 获取登录用户信息
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected User LoginInfo => (User) HttpContext.Items["LoginInfo"];
|
protected LoginInfoItem LoginInfo => (LoginInfoItem) HttpContext.Items["LoginInfo"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
@@ -25,28 +27,28 @@ namespace Controllers
|
|||||||
```C#
|
```C#
|
||||||
#Startup.cs
|
#Startup.cs
|
||||||
|
|
||||||
services.AddApiDoc("文档名称", "文档描述");
|
services.AddYYDoc("文档名称", "文档描述");
|
||||||
|
|
||||||
app.UseApiDoc("名称",SubmitMethod[])
|
app.UseYYDoc("名称",SubmitMethod[])
|
||||||
|
|
||||||
#控制器中可以直接使用特性
|
#控制器中可以直接使用特性
|
||||||
|
|
||||||
[ApiDoc("分组","名称")]
|
[YYDoc("分组","名称")]
|
||||||
```
|
```
|
||||||
|
|
||||||
3. 简单的基于Redis的登录TOKEN服务
|
3. 简单的基于Redis的登录TOKEN服务
|
||||||
|
|
||||||
```C#
|
```C#
|
||||||
#Startup.cs
|
#Startup.cs
|
||||||
service.AddAuth();
|
service.AddYYAuth();
|
||||||
```
|
```
|
||||||
添加时候, 可以从DI中获取 Auth 类,调用 Auth.SetId(int) 将用户ID和生成的Token绑定,本方法返回缓存中的Key名称
|
添加时候, 可以从DI中获取 Auth 类,调用 Auth.Set(int,string) 将用户ID/类型和生成的Token绑定,本方法返回缓存中的Key名称
|
||||||
|
|
||||||
```C#
|
```C#
|
||||||
#Startup.cs
|
#Startup.cs
|
||||||
app.UseAuthMiddleware();
|
app.UseYYAuth();
|
||||||
```
|
```
|
||||||
调用本中间件,然后再需要登录认证的地方,使用 [CheckAuth] 特性,即可完成检测登录相关的操作,
|
调用本中间件,然后再需要登录认证的地方,使用 [YYAuth] 特性,即可完成检测登录相关的操作,
|
||||||
如果需要获取用户的ID, 只需要 直接使用 LoginId 属性即可获取
|
如果需要获取用户的ID, 只需要 直接使用 LoginId 属性即可获取
|
||||||
|
|
||||||
4. 统一返回
|
4. 统一返回
|
||||||
@@ -58,5 +60,9 @@ app.UseAuthMiddleware();
|
|||||||
|
|
||||||
```C#
|
```C#
|
||||||
#Startup.cs
|
#Startup.cs
|
||||||
app.UseExceptionMiddleware();
|
app.UseYYException();
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### TODO:
|
||||||
|
1. 增加HANGFIRE 支持redis和sqlite 存储, 支持 基于其他系统的TOKEN认证和独立账号密码认证
|
||||||
|
|||||||
+11
-6
@@ -4,7 +4,7 @@
|
|||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
<OutputType>Library</OutputType>
|
<OutputType>Library</OutputType>
|
||||||
<PackOnBuild>true</PackOnBuild>
|
<PackOnBuild>true</PackOnBuild>
|
||||||
<Version>0.1.3</Version>
|
<Version>0.2.3</Version>
|
||||||
<Authors>xRain@YYTech</Authors>
|
<Authors>xRain@YYTech</Authors>
|
||||||
<Description>AspNetCore一个方便的API文档,捕获异常,统一输入输出的API类库</Description>
|
<Description>AspNetCore一个方便的API文档,捕获异常,统一输入输出的API类库</Description>
|
||||||
<PackageId>YY-Tech.YYApi</PackageId>
|
<PackageId>YY-Tech.YYApi</PackageId>
|
||||||
@@ -17,13 +17,18 @@
|
|||||||
<Folder Include="Helpers\" />
|
<Folder Include="Helpers\" />
|
||||||
<Folder Include="Communications\" />
|
<Folder Include="Communications\" />
|
||||||
<Folder Include="Controllers\" />
|
<Folder Include="Controllers\" />
|
||||||
|
<Folder Include="JobService\" />
|
||||||
|
<Folder Include="Middlewares\" />
|
||||||
|
<Folder Include="Attributes\" />
|
||||||
|
<Folder Include="Exceptions\" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Remove="Properties\launchSettings.json" />
|
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="5.5.1" />
|
||||||
</ItemGroup>
|
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="5.5.1" />
|
||||||
<ItemGroup>
|
<PackageReference Include="HangFire.Core" Version="1.7.11" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="5.0.0-rc5" />
|
<PackageReference Include="Hangfire.AspNetCore" Version="1.7.11" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="5.0.0-rc5" />
|
<PackageReference Include="Hangfire.Console" Version="1.4.2" />
|
||||||
|
<PackageReference Include="Hangfire.Redis.StackExchange" Version="1.8.4" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ProjectExtensions>
|
<ProjectExtensions>
|
||||||
<MonoDevelop>
|
<MonoDevelop>
|
||||||
|
|||||||
Reference in New Issue
Block a user