添加项目文件。

This commit is contained in:
JianWeie
2021-12-20 21:27:32 +08:00
parent 747486f5cb
commit 82d825b7a5
3514 changed files with 887941 additions and 0 deletions

View File

@@ -0,0 +1,56 @@
/***********************************************************************
* Project: CoreCms
* ProjectName: 核心内容管理系统
* Web: https://www.corecms.net
* Author: 大灰灰
* Email: jianweie@163.com
* CreateTime: 2021/1/31 21:45:10
* Description: 暂无
***********************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
namespace CoreCms.Net.Auth.Policys
{
public class ApiResponse
{
public int Status { get; set; } = 404;
public object Value { get; set; } = "No Found";
public ApiResponse(StatusCode apiCode, object msg = null)
{
switch (apiCode)
{
case StatusCode.CODE401:
{
Status = 401;
Value = "很抱歉,您无权访问该接口,请确保已经登录!";
}
break;
case StatusCode.CODE403:
{
Status = 403;
Value = "很抱歉,您的访问权限等级不够,联系管理员!";
}
break;
case StatusCode.CODE500:
{
Status = 500;
Value = msg;
}
break;
}
}
}
public enum StatusCode
{
CODE401,
CODE403,
CODE404,
CODE500
}
}

View File

@@ -0,0 +1,62 @@
/***********************************************************************
* Project: CoreCms
* ProjectName: 核心内容管理系统
* Web: https://www.corecms.net
* Author: 大灰灰
* Email: jianweie@163.com
* CreateTime: 2021/1/31 21:45:10
* Description: 暂无
***********************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using CoreCms.Net.Model.ViewModels.UI;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
namespace CoreCms.Net.Auth.Policys
{
public class ApiResponseForAdminHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
public ApiResponseForAdminHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
{
}
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
throw new NotImplementedException();
}
protected override async Task HandleChallengeAsync(AuthenticationProperties properties)
{
Response.ContentType = "application/json";
//Response.StatusCode = StatusCodes.Status401Unauthorized;
//await Response.WriteAsync(JsonConvert.SerializeObject(new ApiResponse(StatusCode.CODE401)));
var jm = new AdminUiCallBack();
jm.code = 401;
jm.data = 401;
jm.msg = "很抱歉,您无权访问该接口,请确保已经登录!";
await Response.WriteAsync(JsonConvert.SerializeObject(jm));
}
protected override async Task HandleForbiddenAsync(AuthenticationProperties properties)
{
Response.ContentType = "application/json";
//Response.StatusCode = StatusCodes.Status403Forbidden;
//await Response.WriteAsync(JsonConvert.SerializeObject(new ApiResponse(StatusCode.CODE403)));
var jm = new AdminUiCallBack();
jm.code = 403;
jm.msg = "很抱歉,您的访问权限等级不够,联系管理员!!";
await Response.WriteAsync(JsonConvert.SerializeObject(jm));
}
}
}

View File

@@ -0,0 +1,65 @@
/***********************************************************************
* Project: CoreCms
* ProjectName: 核心内容管理系统
* Web: https://www.corecms.net
* Author: 大灰灰
* Email: jianweie@163.com
* CreateTime: 2021/1/31 21:45:10
* Description: 暂无
***********************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using CoreCms.Net.Model.ViewModels.UI;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
namespace CoreCms.Net.Auth.Policys
{
public class ApiResponseForClientHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
public ApiResponseForClientHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
{
}
protected override Task<AuthenticateResult> HandleAuthenticateAsync()
{
throw new NotImplementedException();
}
protected override async Task HandleChallengeAsync(AuthenticationProperties properties)
{
Response.ContentType = "application/json";
//Response.StatusCode = StatusCodes.Status401Unauthorized;
//await Response.WriteAsync(JsonConvert.SerializeObject(new ApiResponse(StatusCode.CODE401)));
var jm = new WebApiCallBack();
jm.status = false;
jm.code = 14007;
jm.data = 14007;
jm.msg = "很抱歉,授权失效,请重新登录!";
await Response.WriteAsync(JsonConvert.SerializeObject(jm));
}
protected override async Task HandleForbiddenAsync(AuthenticationProperties properties)
{
Response.ContentType = "application/json";
//Response.StatusCode = StatusCodes.Status403Forbidden;
//await Response.WriteAsync(JsonConvert.SerializeObject(new ApiResponse(StatusCode.CODE403)));
var jm = new WebApiCallBack();
jm.status = false;
jm.code = 14007;
jm.data = 14007;
jm.msg = "很抱歉,授权失效,请重新登录!";
await Response.WriteAsync(JsonConvert.SerializeObject(jm));
}
}
}

View File

@@ -0,0 +1,56 @@
/***********************************************************************
* Project: CoreCms
* ProjectName: 核心内容管理系统
* Web: https://www.corecms.net
* Author: 大灰灰
* Email: jianweie@163.com
* CreateTime: 2021/1/31 21:45:10
* Description: 暂无
***********************************************************************/
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
namespace CoreCms.Net.Auth.Policys
{
/// <summary>
/// JWTToken生成类
/// </summary>
public class JwtToken
{
/// <summary>
/// 获取基于JWT的Token
/// </summary>
/// <param name="claims">需要在登陆的时候配置</param>
/// <param name="permissionRequirement">在startup中定义的参数</param>
/// <returns></returns>
public static dynamic BuildJwtToken(Claim[] claims, PermissionRequirement permissionRequirement)
{
var now = DateTime.Now;
// 实例化JwtSecurityToken
var jwt = new JwtSecurityToken(
issuer: permissionRequirement.Issuer,
audience: permissionRequirement.Audience,
claims: claims,
notBefore: now,
expires: now.Add(permissionRequirement.Expiration),
signingCredentials: permissionRequirement.SigningCredentials
);
// 生成 Token
var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);
//打包返回前台
var responseJson = new
{
success = true,
token = encodedJwt,
expires_in = permissionRequirement.Expiration.TotalSeconds,
token_type = "Bearer"
};
return responseJson;
}
}
}

View File

@@ -0,0 +1,210 @@
/***********************************************************************
* Project: CoreCms
* ProjectName: 核心内容管理系统
* Web: https://www.corecms.net
* Author: 大灰灰
* Email: jianweie@163.com
* CreateTime: 2021/1/31 21:45:10
* Description: 暂无
***********************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using CoreCms.Net.Configuration;
using CoreCms.Net.IServices;
using CoreCms.Net.Utility.Extensions;
using CoreCms.Net.Utility.Helper;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
namespace CoreCms.Net.Auth.Policys
{
/// <summary>
/// 权限授权处理器
/// </summary>
public class PermissionForAdminHandler : AuthorizationHandler<PermissionRequirement>
{
/// <summary>
/// 验证方案提供对象
/// </summary>
public IAuthenticationSchemeProvider Schemes { get; set; }
private readonly ISysRoleMenuServices _sysRoleMenuServices;
private readonly IHttpContextAccessor _accessor;
/// <summary>
/// 构造函数注入
/// </summary>
/// <param name="schemes"></param>
/// <param name="navigationRepository"></param>
/// <param name="accessor"></param>
public PermissionForAdminHandler(IAuthenticationSchemeProvider schemes
, ISysRoleMenuServices sysRoleMenuServices
, IHttpContextAccessor accessor)
{
_accessor = accessor;
Schemes = schemes;
_sysRoleMenuServices = sysRoleMenuServices;
}
// 重写异步处理程序
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement)
{
var httpContext = _accessor.HttpContext;
if (!requirement.Permissions.Any())
{
var data = await _sysRoleMenuServices.RoleModuleMaps();
var list = new List<PermissionItem>();
if (Permissions.IsUseIds4)
{
list = (from item in data
orderby item.id
select new PermissionItem
{
Url = item.menu?.component,
RouteUrl = item.menu?.path,
Authority = item.menu?.authority,
Role = item.role?.id.ObjectToString(),
}).ToList();
}
else
{
list = (from item in data
orderby item.id
select new PermissionItem
{
Url = item.menu?.component,
RouteUrl = item.menu?.path,
Authority = item.menu?.authority,
Role = item.role?.roleCode,
}).ToList();
}
requirement.Permissions = list;
}
//请求Url
if (httpContext != null)
{
//
var questUrl = httpContext.Request.Path.Value.ToLower();
//判断请求是否停止
var handlers = httpContext.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();
foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync())
{
if (await handlers.GetHandlerAsync(httpContext, scheme.Name) is IAuthenticationRequestHandler handler && await handler.HandleRequestAsync())
{
context.Fail();
return;
}
}
//判断请求是否拥有凭据,即有没有登录
var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync();
if (defaultAuthenticate != null)
{
var result = await httpContext.AuthenticateAsync(defaultAuthenticate.Name);
//result?.Principal不为空即登录成功
if (result?.Principal != null)
{
httpContext.User = result.Principal;
// 获取当前用户的角色信息
var currentUserRoles = new List<string>();
// ids4和jwt切换
// ids4
if (Permissions.IsUseIds4)
{
currentUserRoles = (from item in httpContext.User.Claims
where item.Type == "role"
select item.Value).ToList();
}
else
{
// jwt
currentUserRoles = (from item in httpContext.User.Claims
where item.Type == requirement.ClaimType
select item.Value).ToList();
}
var isMatchRole = false;
var permisssionRoles = requirement.Permissions.Where(w => currentUserRoles.Contains(w.Role));
foreach (var item in permisssionRoles)
{
try
{
//权限中是否存在请求的url
if (Regex.Match(questUrl, item.Url.ObjectToString().ToLower()).Value == questUrl)
{
isMatchRole = true;
break;
}
}
catch (Exception)
{
// ignored
}
}
//验证权限
if (currentUserRoles.Count <= 0 || !isMatchRole)
{
context.Fail();
return;
}
var isExp = false;
// ids4和jwt切换
// ids4
if (Permissions.IsUseIds4)
{
isExp = (httpContext.User.Claims.SingleOrDefault(s => s.Type == "exp")?.Value) != null && DateHelper.StampToDateTime(httpContext.User.Claims.SingleOrDefault(s => s.Type == "exp")?.Value) >= DateTime.Now;
}
else
{
// jwt
isExp = (httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration)?.Value) != null && DateTime.Parse(httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration)?.Value) >= DateTime.Now;
}
if (isExp)
{
context.Succeed(requirement);
}
else
{
context.Fail();
return;
}
return;
}
else
{
context.Fail();
return;
}
}
else
{
context.Fail();
return;
}
//判断没有登录时是否访问登录的url,并且是Post请求并且是form表单提交类型否则为失败
//if (!questUrl.Equals(requirement.LoginPath.ToLower(), StringComparison.Ordinal) && (!httpContext.Request.Method.Equals("POST") || !httpContext.Request.HasJsonContentType()))
//{
// context.Fail();
// return;
//}
}
context.Succeed(requirement);
}
}
}

View File

@@ -0,0 +1,182 @@
/***********************************************************************
* Project: CoreCms
* ProjectName: 核心内容管理系统
* Web: https://www.corecms.net
* Author: 大灰灰
* Email: jianweie@163.com
* CreateTime: 2021/1/31 21:45:10
* Description: 暂无
***********************************************************************/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using CoreCms.Net.Utility.Extensions;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
namespace CoreCms.Net.Auth.Policys
{
/// <summary>
/// 权限授权处理器
/// </summary>
public class PermissionForClientHandler : AuthorizationHandler<PermissionRequirement>
{
/// <summary>
/// 验证方案提供对象
/// </summary>
public IAuthenticationSchemeProvider Schemes { get; set; }
private readonly IHttpContextAccessor _accessor;
/// <summary>
/// 构造函数注入
/// </summary>
/// <param name="schemes"></param>
/// <param name="navigationRepository"></param>
/// <param name="accessor"></param>
public PermissionForClientHandler(IAuthenticationSchemeProvider schemes, IHttpContextAccessor accessor)
{
_accessor = accessor;
Schemes = schemes;
}
// 重写异步处理程序
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement)
{
var httpContext = _accessor.HttpContext;
if (!requirement.Permissions.Any())
{
//var data = await _navigationRepository.QueryAsync();
//var list = (from item in data
// where item.isLock == false
// orderby item.id
// select new PermissionItem
// {
// Url = item.linkUrl,
// Role = item.identificationCode,
// }).ToList();
//requirement.Permissions = list;
}
//请求Url
if (httpContext != null)
{
var questUrl = httpContext.Request.Path.Value.ToLower();
//判断请求是否停止
var handlers = httpContext.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();
foreach (var scheme in await Schemes.GetRequestHandlerSchemesAsync())
{
if (await handlers.GetHandlerAsync(httpContext, scheme.Name) is IAuthenticationRequestHandler handler && await handler.HandleRequestAsync())
{
context.Fail();
return;
}
}
//判断请求是否拥有凭据,即有没有登录
var defaultAuthenticate = await Schemes.GetDefaultAuthenticateSchemeAsync();
if (defaultAuthenticate != null)
{
var result = await httpContext.AuthenticateAsync(defaultAuthenticate.Name);
//result?.Principal不为空即登录成功
if (result?.Principal != null)
{
// 将最新的角色和接口列表更新
// 这里暂时把代码移动到了Login获取token的api里,这样就不用每次都请求数据库,造成压力.
// 但是这样有个问题,就是如果修改了某一个角色的菜单权限,不会立刻更新,
// 需要让用户退出重新登录,如果你想实时更新,请把下边的注释打开即可.
//var data = await _roleModulePermissionServices.RoleModuleMaps();
//var list = (from item in data
// where item.IsDeleted == false
// orderby item.Id
// select new PermissionItem
// {
// Url = item.Module?.LinkUrl,
// Role = item.Role?.Name,
// }).ToList();
//requirement.Permissions = list;
httpContext.User = result.Principal;
//权限中是否存在请求的url
//if (requirement.Permissions.GroupBy(g => g.Url).Where(w => w.Key?.ToLower() == questUrl).Count() > 0)
//if (isMatchUrl)
if (true)
{
// 获取当前用户的角色信息
var currentUserRoles = (from item in httpContext.User.Claims
where item.Type == requirement.ClaimType
select item.Value).ToList();
var isMatchRole = false;
var permisssionRoles = requirement.Permissions.Where(w => currentUserRoles.Contains(w.Role));
foreach (var item in permisssionRoles)
{
try
{
if (Regex.Match(questUrl, item.Url?.ObjectToString().ToLower())?.Value == questUrl)
{
isMatchRole = true;
break;
}
}
catch (Exception)
{
// ignored
}
}
//验证权限
//if (currentUserRoles.Count <= 0 || requirement.Permissions.Where(w => currentUserRoles.Contains(w.Role) && w.Url.ToLower() == questUrl).Count() <= 0)
if (currentUserRoles.Count <= 0 || !isMatchRole)
{
context.Fail();
return;
}
}
//判断过期时间这里仅仅是最坏验证原则你可以不要这个if else的判断因为我们使用的官方验证Token过期后上边的result?.Principal 就为 null 了,进不到这里了,因此这里其实可以不用验证过期时间,只是做最后严谨判断)
if ((httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration)?.Value) != null && DateTime.Parse(httpContext.User.Claims.SingleOrDefault(s => s.Type == ClaimTypes.Expiration)?.Value) >= DateTime.Now)
{
context.Succeed(requirement);
}
else
{
context.Fail();
return;
}
return;
}
else
{
context.Fail();
return;
}
}
else
{
context.Fail();
return;
}
//判断没有登录时是否访问登录的url,并且是Post请求并且是form表单提交类型否则为失败
//if (!questUrl.Equals(requirement.LoginPath.ToLower(), StringComparison.Ordinal) && (!httpContext.Request.Method.Equals("POST") || !httpContext.Request.HasJsonContentType()))
//{
// context.Fail();
// return;
//}
}
context.Succeed(requirement);
}
}
}

View File

@@ -0,0 +1,40 @@
/***********************************************************************
* Project: CoreCms
* ProjectName: 核心内容管理系统
* Web: https://www.corecms.net
* Author: 大灰灰
* Email: jianweie@163.com
* CreateTime: 2021/1/31 21:45:10
* Description: 暂无
***********************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
namespace CoreCms.Net.Auth.Policys
{
/// <summary>
/// 用户或角色或其他凭据实体
/// </summary>
public class PermissionItem
{
/// <summary>
/// 用户或角色或其他凭据名称
/// </summary>
public virtual string Role { get; set; }
/// <summary>
/// 请求Url
/// </summary>
public virtual string Url { get; set; }
/// <summary>
/// 权限标识
/// </summary>
public virtual string Authority { get; set; }
/// <summary>
/// 路由标识Url
/// </summary>
public virtual string RouteUrl { get; set; }
}
}

View File

@@ -0,0 +1,83 @@
/***********************************************************************
* Project: CoreCms
* ProjectName: 核心内容管理系统
* Web: https://www.corecms.net
* Author: 大灰灰
* Email: jianweie@163.com
* CreateTime: 2021/1/31 21:45:10
* Description: 暂无
***********************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.AspNetCore.Authorization;
using Microsoft.IdentityModel.Tokens;
namespace CoreCms.Net.Auth.Policys
{
/// <summary>
/// 必要参数类
/// 继承 IAuthorizationRequirement用于设计自定义权限处理器PermissionHandler
/// 因为AuthorizationHandler 中的泛型参数 TRequirement 必须继承 IAuthorizationRequirement
/// </summary>
public class PermissionRequirement : IAuthorizationRequirement
{
/// <summary>
/// 用户权限集合,一个订单包含了很多详情,
/// 同理,一个网站的认证发行中,也有很多权限详情(这里是Role和URL的关系)
/// </summary>
public List<PermissionItem> Permissions { get; set; }
/// <summary>
/// 无权限action
/// </summary>
public string DeniedAction { get; set; }
/// <summary>
/// 认证授权类型
/// </summary>
public string ClaimType { internal get; set; }
/// <summary>
/// 请求路径
/// </summary>
public string LoginPath { get; set; } = "/Api/Login";
/// <summary>
/// 发行人
/// </summary>
public string Issuer { get; set; }
/// <summary>
/// 订阅人
/// </summary>
public string Audience { get; set; }
/// <summary>
/// 过期时间
/// </summary>
public TimeSpan Expiration { get; set; }
/// <summary>
/// 签名验证
/// </summary>
public SigningCredentials SigningCredentials { get; set; }
/// <summary>
/// 构造
/// </summary>
/// <param name="deniedAction">拒约请求的url</param>
/// <param name="permissions">权限集合</param>
/// <param name="claimType">声明类型</param>
/// <param name="issuer">发行人</param>
/// <param name="audience">订阅人</param>
/// <param name="signingCredentials">签名验证实体</param>
/// <param name="expiration">过期时间</param>
public PermissionRequirement(string deniedAction, List<PermissionItem> permissions, string claimType, string issuer, string audience, SigningCredentials signingCredentials, TimeSpan expiration)
{
ClaimType = claimType;
DeniedAction = deniedAction;
Permissions = permissions;
Issuer = issuer;
Audience = audience;
Expiration = expiration;
SigningCredentials = signingCredentials;
}
}
}