OsharpNS轻量级.net core快速开发框架简明入门教程-Osharp.Permissions使用
OsharpNS轻量级.net core快速开发框架简明入门教程
教程目录
从零开始启动Osharp
1.1. 使用OsharpNS项目模板创建项目
1.2. 配置数据库连接串并启动项目
1.3. OsharpNS.Swagger使用实例(登录和授权)
1.4. Angular6的前端项目启动
Osharp代码生成器的使用
2.1 生成器的使用
Osharp部分模块使用
3.1 Osharp.Redis使用
Osharp深度学习和使用
4.2 多上下文配置(多个数据库的使用)
4.3. 自定义模块的定义(Senparc.Weixin的使用)
4.4. 继续学习中....
OsharpNS官方资源
项目地址:https://github.com/i66soft/osharp-ns20
演示地址:https://www.osharp.org 直接使用QQ登录可以查看效果
文档地址:https://docs.osharp.org 正在完善中....
发布博客:https://www.cnblogs.com/guomingfeng/p/osharpns-publish.html 大神看这个文档应该就能跑起来,从零开始启动Osharp基于此文档完成
VS生成器插件:https://marketplace.visualstudio.com/items?itemName=LiuliuSoft.osharp
官方交流QQ群:85895249
Osharp.Permissions使用
系统授权检查流程
核心代码位于
Osharp/Secutiry/FunctionAuthorizationBase检查过程如下:
检查function是否为null,为null反馈错误,否则继续检查
检查function是否被禁用,被禁用反馈错误,否则继续检查
检查功能是否任何人可用,如果是,直接返回成功,否则继续检查
检查用户是否登陆,未登录反馈错误,否则继续检查
用户已登陆,判断功能是否登陆即可使用,如果是,反馈成功,否则继续检查
获取用户的角色,判断角色是否有角色允许执行功能,如果是,反馈成功,否则继续检查
获取用户能执行的所有功能,判断是否包含功能,如果是,反馈成功;如果否,反馈失败(系统除了给定用户角色,还能根据用户单独给定功能授权,所以检查完角色之后不满足条件,还要检查用户私有的功能是否包含)
/// <summary>
/// 重写以实现权限检查核心验证操作
/// </summary>
/// <param name="function">要验证的功能信息</param>
/// <param name="principal">当前用户在线信息</param>
/// <returns>功能权限验证结果</returns>
protected virtual AuthorizationResult AuthorizeCore(IFunction function, IPrincipal principal)
{
if (function == null)
{
return new AuthorizationResult(AuthorizationStatus.NoFound);
}
if (function.IsLocked)
{
return new AuthorizationResult(AuthorizationStatus.Locked, $"功能“{function.Name}”已被禁用,无法执行");
}
if (function.AccessType == FunctionAccessType.Anonymouse)
{
return AuthorizationResult.OK;
}
//未登录
if (principal == null || !principal.Identity.IsAuthenticated)
{
return new AuthorizationResult(AuthorizationStatus.Unauthorized);
}
//已登录,无角色限制
if (function.AccessType == FunctionAccessType.Logined)
{
return AuthorizationResult.OK;
}
return AuthorizeRoleLimit(function, principal);
} /// <summary>
/// 重写以实现 角色限制 的功能的功能权限检查
/// </summary>
/// <param name="function">要验证的功能信息</param>
/// <param name="principal">用户在线信息</param>
/// <returns>功能权限验证结果</returns>
protected virtual AuthorizationResult AuthorizeRoleLimit(IFunction function, IPrincipal principal)
{
//角色限制
if (!(principal.Identity is ClaimsIdentity identity))
{
return new AuthorizationResult(AuthorizationStatus.Error, "当前用户标识IIdentity格式不正确,仅支持ClaimsIdentity类型的用户标识");
}
//检查角色-功能的权限
string[] userRoleNames = identity.GetRoles().ToArray();
AuthorizationResult result = AuthorizeRoleNames(function, userRoleNames);
if (result.IsOk)
{
return result;
}
result = AuthorizeUserName(function, principal.Identity.GetUserName());
return result;
} /// <summary>
/// 重写以实现指定角色是否有执行指定功能的权限
/// </summary>
/// <param name="function">功能信息</param>
/// <param name="roleNames">角色名称</param>
/// <returns>功能权限检查结果</returns>
protected virtual AuthorizationResult AuthorizeRoleNames(IFunction function, params string[] roleNames)
{
Check.NotNull(roleNames, nameof(roleNames)); if (roleNames.Length == 0)
{
return new AuthorizationResult(AuthorizationStatus.Forbidden);
}
if (function.AccessType != FunctionAccessType.RoleLimit || roleNames.Contains(SuperRoleName))
{
return AuthorizationResult.OK;
}
string[] functionRoleNames = FunctionAuthCache.GetFunctionRoles(function.Id);
if (roleNames.Intersect(functionRoleNames).Any())
{
return AuthorizationResult.OK;
}
return new AuthorizationResult(AuthorizationStatus.Forbidden);
} /// <summary>
/// 重写以实现指定用户是否有执行指定功能的权限
/// </summary>
/// <param name="function">功能信息</param>
/// <param name="userName">用户名</param>
/// <returns>功能权限检查结果</returns>
protected virtual AuthorizationResult AuthorizeUserName(IFunction function, string userName)
{
if (function.AccessType != FunctionAccessType.RoleLimit)
{
return AuthorizationResult.OK;
} Guid[] functionIds = FunctionAuthCache.GetUserFunctions(userName);
if (functionIds.Contains(function.Id))
{
return AuthorizationResult.OK;
}
return new AuthorizationResult(AuthorizationStatus.Forbidden);
}
Controller里面对是否检查权限的控制
文件路径为
CanDoo.Test.Web.Areas.Admin.Controllers,注意看文件中的[RoleLimit],带了这个就要做检查// -----------------------------------------------------------------------
// <copyright file="AdminApiController.cs" company="OSharp开源团队">
// Copyright (c) 2014-2018 OSharp. All rights reserved.
// </copyright>
// <site>http://www.osharp.org</site>
// <last-editor>郭明锋</last-editor>
// <last-date>2018-06-27 4:50</last-date>
// ----------------------------------------------------------------------- using Microsoft.AspNetCore.Mvc; using OSharp.AspNetCore.Mvc;
using OSharp.Core; namespace CanDoo.Test.Web.Areas.Admin.Controllers
{
[Area("Admin")]
[RoleLimit]
public abstract class AdminApiController : AreaApiController
{ }
}
不通过数据库强制给定用户角色的方法
3.1 通过Claim实现
在`IdentityController.cs`中,用户登陆后,生成Claim时,将角色给定
private async Task<string> CreateJwtToken(User user)
{
//在线用户缓存
IOnlineUserCache onlineUserCache = HttpContext.RequestServices.GetService<IOnlineUserCache>();
if (onlineUserCache != null)
{
await onlineUserCache.GetOrRefreshAsync(user.UserName);
} //生成Token,这里只包含最基本信息,其他信息从在线用户缓存中获取
Claim[] claims =
{
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()),
new Claim(ClaimTypes.Name, user.UserName),
new Claim("ExtendRoles", "学生") //这行是新增的,强制给定学生角色,用户角色表中不存在 用户和学生 角色的关联
};
OsharpOptions options = HttpContext.RequestServices.GetService<IOptions<OsharpOptions>>().Value;
string token = JwtHelper.CreateToken(claims, options);
return token;
}
在`CanDoo.Test.Core`中新建类`OnlineUserJwtSecurityTokenHandler.cs`
// -----------------------------------------------------------------------
// <copyright file="OnlineUserJwtSecurityTokenHandler.cs" company="OSharp开源团队">
// Copyright (c) 2014-2018 OSharp. All rights reserved.
// </copyright>
// <site>http://www.osharp.org</site>
// <last-editor>郭明锋</last-editor>
// <last-date>2018-07-09 15:01</last-date>
// ----------------------------------------------------------------------- using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims; using Microsoft.IdentityModel.Tokens; using OSharp.Collections;
using OSharp.Dependency;
using OSharp.Identity;
using OSharp.Secutiry.Claims; namespace CanDoo.Test.Identity
{
/// <summary>
/// 使用在线用户信息和JwtToken生成在线ClaimsIdentity
/// </summary>
public class OnlineUserJwtSecurityTokenHandler : JwtSecurityTokenHandler
{
/// <summary>
/// Creates a <see cref="T:System.Security.Claims.ClaimsIdentity" /> from a <see cref="T:System.IdentityModel.Tokens.Jwt.JwtSecurityToken" />.
/// </summary>
/// <param name="jwtToken">The <see cref="T:System.IdentityModel.Tokens.Jwt.JwtSecurityToken" /> to use as a <see cref="T:System.Security.Claims.Claim" /> source.</param>
/// <param name="issuer">The value to set <see cref="P:System.Security.Claims.Claim.Issuer" /></param>
/// <param name="validationParameters"> Contains parameters for validating the token.</param>
/// <returns>A <see cref="T:System.Security.Claims.ClaimsIdentity" /> containing the <see cref="P:System.IdentityModel.Tokens.Jwt.JwtSecurityToken.Claims" />.</returns>
protected override ClaimsIdentity CreateClaimsIdentity(JwtSecurityToken jwtToken,
string issuer,
TokenValidationParameters validationParameters)
{
ClaimsIdentity identity = base.CreateClaimsIdentity(jwtToken, issuer, validationParameters);
var extendRoles = identity.GetClaimValueFirstOrDefault("ExtendRoles");//从Claim中获取强制给定的角色 if (identity.IsAuthenticated)
{
//由在线缓存获取用户信息赋给IIdentity
IOnlineUserCache onlineUserCache = ServiceLocator.Instance.GetService<IOnlineUserCache>();
OnlineUser user = onlineUserCache.GetOrRefresh(identity.Name);
if (user == null)
{
return null;
} if (!string.IsNullOrEmpty(user.NickName))
{
identity.AddClaim(new Claim(ClaimTypes.GivenName, user.NickName));
}
if (!string.IsNullOrEmpty(user.Email))
{
identity.AddClaim(new Claim(ClaimTypes.Email, user.Email));
}
//这部分将从Claim中获取的角色进行赋值
string roles = "";
if (user.Roles.Length > 0)
roles = user.Roles.ExpandAndToString() + "," + extendRoles;
else
roles = extendRoles; if (roles != "")
identity.AddClaim(new Claim(ClaimTypes.Role, user.Roles.ExpandAndToString()));
} ScopedDictionary dict = ServiceLocator.Instance.GetService<ScopedDictionary>();
dict.Identity = identity;
return identity;
}
}
}
对`CanDoo.Test.Core`中`IdentityPack`中的代码进行调整
jwt.SecurityTokenValidators.Clear();
jwt.SecurityTokenValidators.Add(new OnlineUserJwtSecurityTokenHandler());//这里要使用本文中创建的OnlineUserJwtSecurityTokenHandler jwt.Events = new JwtBearerEvents()
{
// 生成SignalR的用户信息
OnMessageReceived = context =>
{
string token = context.Request.Query["access_token"];
string path = context.HttpContext.Request.Path;
if (!string.IsNullOrEmpty(token) && path.Contains("hub"))
{
context.Token = token;
} return Task.CompletedTask;
}
};
3.2 通过替换现有OnlineUserProvider缓存方法实现
在`CanDoo.Test.Core`中新建`MyOnlineUserProvider`
// -----------------------------------------------------------------------
// <copyright file="OnlineUserProvider.cs" company="OSharp开源团队">
// Copyright (c) 2014-2018 OSharp. All rights reserved.
// </copyright>
// <site>http://www.osharp.org</site>
// <last-editor>郭明锋</last-editor>
// <last-date>2018-08-17 22:36</last-date>
// ----------------------------------------------------------------------- using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.DependencyInjection;
using OSharp.Identity; namespace CanDoo.Test.Identity
{
/// <summary>
/// 在线用户信息提供者
/// </summary>
public class MyOnlineUserProvider<TUser, TUserKey, TRole, TRoleKey> : IOnlineUserProvider
where TUser : UserBase<TUserKey>
where TUserKey : IEquatable<TUserKey>
where TRole : RoleBase<TRoleKey>
where TRoleKey : IEquatable<TRoleKey>
{
/// <summary>
/// 创建在线用户信息
/// </summary>
/// <param name="provider">服务提供器</param>
/// <param name="userName">用户名</param>
/// <returns>在线用户信息</returns>
public virtual async Task<OnlineUser> Create(IServiceProvider provider, string userName)
{
UserManager<TUser> userManager = provider.GetService<UserManager<TUser>>();
TUser user = await userManager.FindByNameAsync(userName);
if (user == null)
{
return null;
}
IList<string> roles = await userManager.GetRolesAsync(user); roles.Add("学生");//这样就强制给用户赋值了,当然可以对其他东西也做手脚 RoleManager<TRole> roleManager = provider.GetService<RoleManager<TRole>>();
bool isAdmin = roleManager.Roles.Any(m => roles.Contains(m.Name) && m.IsAdmin);
return new OnlineUser()
{
Id = user.Id.ToString(),
UserName = user.UserName,
NickName = user.NickName,
Email = user.Email,
HeadImg = user.HeadImg,
IsAdmin = isAdmin,
Roles = roles.ToArray()
};
}
}
}
对`CanDoo.Test.Core`中的`IdentityPack`修改代码,将原有的`OnlineUserProvider`换为`MyOnlineUserProvider`
/// <summary>
/// 将模块服务添加到依赖注入服务容器中
/// </summary>
/// <param name="services">依赖注入服务容器</param>
/// <returns></returns>
public override IServiceCollection AddServices(IServiceCollection services)
{
services.AddScoped<IIdentityContract, IdentityService>();
base.AddServices(services);
services.Replace(new ServiceDescriptor(typeof(IOnlineUserProvider), typeof(MyOnlineUserProvider<User, int, Role, int>), ServiceLifetime.Scoped));
return services;
}
OsharpNS轻量级.net core快速开发框架简明入门教程-Osharp.Permissions使用的更多相关文章
- OsharpNS轻量级.net core快速开发框架简明入门教程-Osharp.Redis使用
OsharpNS轻量级.net core快速开发框架简明入门教程 教程目录 从零开始启动Osharp 1.1. 使用OsharpNS项目模板创建项目 1.2. 配置数据库连接串并启动项目 1.3. O ...
- OsharpNS轻量级.net core快速开发框架简明入门教程-Osharp.Hangfire使用
OsharpNS轻量级.net core快速开发框架简明入门教程 教程目录 从零开始启动Osharp 1.1. 使用OsharpNS项目模板创建项目 1.2. 配置数据库连接串并启动项目 1.3. O ...
- OsharpNS轻量级.net core快速开发框架简明入门教程-从零开始启动Osharp
OsharpNS轻量级.net core快速开发框架简明入门教程 教程目录 从零开始启动Osharp 1.1. 使用OsharpNS项目模板创建项目 1.2. 配置数据库连接串并启动项目 1.3. O ...
- OsharpNS轻量级.net core快速开发框架简明入门教程-代码生成器的使用
OsharpNS轻量级.net core快速开发框架简明入门教程 教程目录 从零开始启动Osharp 1.1. 使用OsharpNS项目模板创建项目 1.2. 配置数据库连接串并启动项目 1.3. O ...
- OsharpNS轻量级.net core快速开发框架简明入门教程-基于Osharp实现自己的业务功能
OsharpNS轻量级.net core快速开发框架简明入门教程 教程目录 从零开始启动Osharp 1.1. 使用OsharpNS项目模板创建项目 1.2. 配置数据库连接串并启动项目 1.3. O ...
- OsharpNS轻量级.net core快速开发框架简明入门教程-切换数据库(从SqlServer改为MySql)
OsharpNS轻量级.net core快速开发框架简明入门教程 教程目录 从零开始启动Osharp 1.1. 使用OsharpNS项目模板创建项目 1.2. 配置数据库连接串并启动项目 1.3. O ...
- OsharpNS轻量级.net core快速开发框架简明入门教程-多上下文配置(多个数据库的使用)
OsharpNS轻量级.net core快速开发框架简明入门教程 教程目录 从零开始启动Osharp 1.1. 使用OsharpNS项目模板创建项目 1.2. 配置数据库连接串并启动项目 1.3. O ...
- 【开源】OSharpNS,轻量级.net core快速开发框架发布
OSharpNS简介 OSharp Framework with .NetStandard2.0(OSharpNS)是OSharp的以.NetStandard2.0为目标框架,在AspNetCore的 ...
- [开源]OSharpNS - .net core 快速开发框架 - 快速开始
什么是OSharp OSharpNS全称OSharp Framework with .NetStandard2.0,是一个基于.NetStandard2.0开发的一个.NetCore快速开发框架.这个 ...
随机推荐
- jdk-8u151-nb-8_2-windows-x64软件安装教程及环境配置
1.双击jdk-8u151-windows-x64.exe文件 2.进入安装向导 3.配置环境变量 (1)计算机→属性→高级系统设置→高级→环境变量 (2)系统变量→新建 JAVA_HOME 变量 . ...
- (译)Kubernetes中的多容器Pod和Pod内容器间通信
原文:https://www.mirantis.com/blog/multi-container-pods-and-container-communication-in-kubernetes/Pave ...
- Java学习——包装类
Java学习——包装类 摘要:本文主要介绍了Java中常用的包装类和基本类型之间的转换,包装类或基本类型和String之间的转换. 部分内容来自以下博客: https://www.cnblogs.co ...
- FCC-学习笔记 Boo who
FCC-学习笔记 Boo who 1>最近在学习和练习FCC的题目.这个真的比较的好,推荐给大家. 2>中文版的地址:https://www.freecodecamp.cn/;英文版的地 ...
- <转>WPF 中的绑定
在WPF应用的开发过程中Binding是一个非常重要的部分. 在实际开发过程中Binding的不同种写法达到的效果相同但事实是存在很大区别的. 这里将实际中碰到过的问题做下汇总记录和理解. 1. so ...
- maven 学习---Maven快照
大型软件应用程序通常由多个模块组成,这是多个团队工作于同一应用程序的不同模块的常见场景.例如一个团队工作负责应用程序的前端应用用户接口工程(app-ui.jar:1.0)),同时他们使用数据服务工程( ...
- 处理 JS中 undefined 的 7 个技巧
摘要: JS的大部分报错都是undefined... 作者:前端小智 原文:处理 JS中 undefined 的 7 个技巧 Fundebug经授权转载,版权归原作者所有. 大约8年前,当原作者开始学 ...
- 4、Work-Queue
Work Queues using the Java Client In the first tutorial we wrote programs to send and receive messag ...
- C# 在不同编译下的不同表现
这是我在2018年的时候发在Unity Forums上的帖子, 至今无人回复, 之前是想用TypedReference做DataTable的相关功能的, 可是结果不正确. tiancaiwrk, Oc ...
- JS高阶---原型链
[大纲] [主体] 1.创建函数 注意:Object内置原生对象原来就有 2.添加实例方法 3.根据构造函数创建实例对象 原型链寻找 1.本身有在本身找 2.本身没有往摸着隐式原型链往里找 或者再上层 ...