OsharpNS轻量级.net core快速开发框架简明入门教程

教程目录

  1. 从零开始启动Osharp

    1.1. 使用OsharpNS项目模板创建项目

    1.2. 配置数据库连接串并启动项目

    1.3. OsharpNS.Swagger使用实例(登录和授权)

    1.4. Angular6的前端项目启动

  2. Osharp代码生成器的使用

    2.1 生成器的使用

    2.2 生成代码详解(如何自己实现业务功能)

  3. Osharp部分模块使用

    3.1 Osharp.Redis使用

    3.2 Osharp.Hangfire使用

    3.3 Osharp.Permissions使用

  4. Osharp深度学习和使用

    4.1 切换数据库(从SqlServer改为MySql)

    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使用

  1. 系统授权检查流程

    核心代码位于Osharp/Secutiry/FunctionAuthorizationBase

    检查过程如下:

    1. 检查function是否为null,为null反馈错误,否则继续检查

    2. 检查function是否被禁用,被禁用反馈错误,否则继续检查

    3. 检查功能是否任何人可用,如果是,直接返回成功,否则继续检查

    4. 检查用户是否登陆,未登录反馈错误,否则继续检查

    5. 用户已登陆,判断功能是否登陆即可使用,如果是,反馈成功,否则继续检查

    6. 获取用户的角色,判断角色是否有角色允许执行功能,如果是,反馈成功,否则继续检查

    7. 获取用户能执行的所有功能,判断是否包含功能,如果是,反馈成功;如果否,反馈失败(系统除了给定用户角色,还能根据用户单独给定功能授权,所以检查完角色之后不满足条件,还要检查用户私有的功能是否包含)

            /// <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);
    }
  2. 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. 不通过数据库强制给定用户角色的方法

    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使用的更多相关文章

  1. OsharpNS轻量级.net core快速开发框架简明入门教程-Osharp.Redis使用

    OsharpNS轻量级.net core快速开发框架简明入门教程 教程目录 从零开始启动Osharp 1.1. 使用OsharpNS项目模板创建项目 1.2. 配置数据库连接串并启动项目 1.3. O ...

  2. OsharpNS轻量级.net core快速开发框架简明入门教程-Osharp.Hangfire使用

    OsharpNS轻量级.net core快速开发框架简明入门教程 教程目录 从零开始启动Osharp 1.1. 使用OsharpNS项目模板创建项目 1.2. 配置数据库连接串并启动项目 1.3. O ...

  3. OsharpNS轻量级.net core快速开发框架简明入门教程-从零开始启动Osharp

    OsharpNS轻量级.net core快速开发框架简明入门教程 教程目录 从零开始启动Osharp 1.1. 使用OsharpNS项目模板创建项目 1.2. 配置数据库连接串并启动项目 1.3. O ...

  4. OsharpNS轻量级.net core快速开发框架简明入门教程-代码生成器的使用

    OsharpNS轻量级.net core快速开发框架简明入门教程 教程目录 从零开始启动Osharp 1.1. 使用OsharpNS项目模板创建项目 1.2. 配置数据库连接串并启动项目 1.3. O ...

  5. OsharpNS轻量级.net core快速开发框架简明入门教程-基于Osharp实现自己的业务功能

    OsharpNS轻量级.net core快速开发框架简明入门教程 教程目录 从零开始启动Osharp 1.1. 使用OsharpNS项目模板创建项目 1.2. 配置数据库连接串并启动项目 1.3. O ...

  6. OsharpNS轻量级.net core快速开发框架简明入门教程-切换数据库(从SqlServer改为MySql)

    OsharpNS轻量级.net core快速开发框架简明入门教程 教程目录 从零开始启动Osharp 1.1. 使用OsharpNS项目模板创建项目 1.2. 配置数据库连接串并启动项目 1.3. O ...

  7. OsharpNS轻量级.net core快速开发框架简明入门教程-多上下文配置(多个数据库的使用)

    OsharpNS轻量级.net core快速开发框架简明入门教程 教程目录 从零开始启动Osharp 1.1. 使用OsharpNS项目模板创建项目 1.2. 配置数据库连接串并启动项目 1.3. O ...

  8. 【开源】OSharpNS,轻量级.net core快速开发框架发布

    OSharpNS简介 OSharp Framework with .NetStandard2.0(OSharpNS)是OSharp的以.NetStandard2.0为目标框架,在AspNetCore的 ...

  9. [开源]OSharpNS - .net core 快速开发框架 - 快速开始

    什么是OSharp OSharpNS全称OSharp Framework with .NetStandard2.0,是一个基于.NetStandard2.0开发的一个.NetCore快速开发框架.这个 ...

随机推荐

  1. SQL Server 通过“with as”方法查询树型结构

    一.with as 公用表表达式 类似VIEW,但是不并没有创建对象,WITH  AS 公用表表达式不创建对象,只能被后随的SELECT语句,其作用: 1. 实现递归查询(树形结构) 2. 可以在一个 ...

  2. .net core EF Core 视图的应用

    由之前的一篇文章<.net core Entity Framework 与 EF Core>我们都已经知道 EF Core 增加了许多特性,并且性能上也有了很大的提升. 但是EF Core ...

  3. 基于kafka_2.11-2.1.0实现的生产者和消费者代码样例

    1.搭建部署好zookeeper集群和kafka集群,这里省略. 启动zk: bin/zkServer.sh start conf/zoo.cfg. 验证zk是否启动成功: bin/zkServer. ...

  4. 面试官都叫好的Synchronized底层实现,这工资开多少一个月?

    本文为死磕Synchronized底层实现第三篇文章,内容为重量级锁实现. 本系列文章将对HotSpot的synchronized锁实现进行全面分析,内容包括偏向锁.轻量级锁.重量级锁的加锁.解锁.锁 ...

  5. Python进阶(二)

    1.模块和包的概念 python的解决方案是把同名的模块放到不同的包中 1.1,导入模块 要使用一个模块,我们必须首先导入该模块.Python使用import语句导入一个模块.例如,导入系统自带的模块 ...

  6. 微信小程序 自定义头部导航栏和导航栏背景图片 navigationStyle

    ​ 这两天因为要做一个带背景的小程序头,哭了,小程序导航栏有背景也就算了,还得让导航栏上的背景顺下来,心态小崩.现在可以单独设置一个页面的小程序头了,但是前提是要微信7.0以上的版本,考虑到兼容性问题 ...

  7. 使用Javamail实现邮件发送功能

    目录 相关的包 编写工具类 环境说明 @(使用Javamail实现邮件发送功能) 相关的包 activation.jar javax.mail.jar mail包建议使用高版本写的包,否则可能会发空白 ...

  8. 个人项目:WC

    一.GitHub项目地址:https://github.com/lseap/myWC 二.PSP表格: PSP2.1 Personal Software Process Stages 预估耗时(分钟) ...

  9. SpringBoot的学习一:入门篇

    SpringBoot是什么: SpringBoot是Spring项目中的一个子工程,是一个轻量级框架. SpringBoot框架中有两个个非常重要的策略:开箱即用和约定优于配置 一.构建工程 1.开发 ...

  10. C语言的10大基础算法

    C语言的10大基础算法 算法是一个程序和软件的灵魂,作为一名优秀的程序员,只有对一些基础的算法有着全面的掌握,才会在设计程序和编写代码的过程中显得得心应手.本文包括了经典的Fibonacci数列.简易 ...