OsharpNS輕量級.net core快速開發框架簡明入門教程-Osharp.Permissions使用

OsharpNS輕量級.net core快速開發框架簡明入門教程

教程目錄html

  1. 從零開始啓動Osharp前端

    1.1. 使用OsharpNS項目模板建立項目git

    1.2. 配置數據庫鏈接串並啓動項目github

    1.3. OsharpNS.Swagger使用實例(登陸和受權)數據庫

    1.4. Angular6的前端項目啓動緩存

  2. Osharp代碼生成器的使用框架

    2.1 生成器的使用async

    2.2 生成代碼詳解(如何本身實現業務功能)ide

  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;
            }
相關文章
相關標籤/搜索