.net core webapi + vue 實現RBAC 基本的許可權管理

来源:https://www.cnblogs.com/zyb-wzy/archive/2022/05/30/ZYB_RBAC.html
-Advertisement-
Play Games

RBAC實現最基礎的許可權管理webapi+vue 一、確定關係表 //許可權管理表 這個表可以實現左側菜單的顯示 [Table("Permission")] public class Permission { [Key] public int Id { get; set; } public strin ...


RBAC實現最基礎的許可權管理webapi+vue

一、確定關係表

//許可權管理表    這個表可以實現左側菜單的顯示

    [Table("Permission")]
  public class Permission
  {
      [Key]
      public int Id { get; set; }
      public string PermissionCode { get; set; }
      public string PermissionName { get; set; }
      public string PermissionIco { get; set; }
      public string PermissionUrl { get; set; }
      public bool Enable { get; set; } = true;
      public string ParentCode { get; set; }
  }
   
  //角色表
    [Table("Role")]
  public class Role
  {
      [Key]
      public int Id { get; set; }
      [Required,StringLength(50)]
      public string RoleName { get; set; }
      public string Desc { get; set; }
      public string PermissionName { get; set; }
      public string Users { get; set; }

  }
   
  //用戶表
    /// <summary>
  /// 用戶表
  /// </summary>
  [Table("User")]
  public class User
  {
      [Key]
      public int Id { get; set; }
      public int DeptId { get; set; }
      [Required,StringLength(20)]
      public string UserName { get; set; }    
      [Required, StringLength(40)]
      public string Password { get; set; }
      public SexType SexType { get; set; }  
      [StringLength(100)]
      public string Email { get; set; }
      public string RoleIds { get; set; }  
      public string DepaCodes { get; set; }
  }

  public enum SexType
  {
      男,
      女,
      保密
  }
   
  //這張表用來關聯角色和許可權
    /// <summary>
  /// 角色許可權
  /// </summary>
  [Table("Role_Permission")]
  public class Role_Permission
  {
      [Key]
      public int Id { get; set; }
      public int RoleId { get; set; }
      public int PermissionId { get; set; }
  }
   
  //用戶和角色表 用來關聯用戶和角色
    [Table("User_Role")]
  public class User_Role
  {
      [Key]
      public int Id { get; set; }
      public int UserId { get; set; }
      public int RoleId { get; set; }
  }
   
   
   
   

二、寫介面

根據用戶id顯示許可權的介面

//這個是許可權管理的介面和實現    使用的是依賴註入的方式
public interface IPermissionRespository
  {
  //這裡的dto是實現左側菜單的遞歸實現
      List<MenoDto> GetPermissions(int userId);
  }
   
    public class PermissionRespository : IPermissionRespository
  {
      private readonly AppDbContext appDbContext;
      public PermissionRespository(AppDbContext appDbContext)
      {
          this.appDbContext = appDbContext;
      }

//根據用戶id查詢許可權顯示左側列表
      public List<MenoDto> GetPermissions(int userId)
      {
      //先查詢最高級的數據 然後一次查詢子集
          //if(userId == 1) return GetMenus(this.appDbContext.permissions.ToList(), "M");
          //使用ling語句實現三表聯查 最後顯示許可權信息
                    var menus = (from a in this.appDbContext.user_roles
                        join b in this.appDbContext.role_Permissions
                        on a.RoleId equals b.RoleId
                        join c in this.appDbContext.permissions
                      on b.PermissionId equals c.Id
                      where a.UserId == userId
                      select new Permission
                      {
                          Id = c.Id,
                          Enable = c.Enable,
                          ParentCode = c.ParentCode,
                          PermissionName = c.PermissionName,
                          PermissionCode = c.PermissionCode,
                          PermissionIco = c.PermissionIco
                      }).ToList();
          var list = GetMenus(menus, "M");
          return list;

      }

//使用遞歸查詢左側菜單
      public List<MenoDto> GetMenus(List<Permission> list,string permissionCode)
      {
            List<MenoDto> menus = new List<MenoDto>();
          foreach (var item in list.Where(u=>u.PermissionCode == permissionCode))
          {
              var menu = new MenoDto();
              menu.Id = item.Id;
              menu.PermissionName = item.PermissionName;
              menu.PermissionCode =item.PermissionCode;
              menu.PermissionUrl = item.PermissionUrl;
              menu.PermissionIco = item.PermissionIco;
              menu.Enable = item.Enable;
              menu.ParentCode = item.ParentCode;
              menu.menoDtos = GetMenus(list, item.ParentCode);
              menus.Add(menu);
          }
          return menus;
      }
  }
   
   

角色介面及實現

//角色介面
public interface IRoleRespository
  {
     
      ApiResultData GetRole(); //顯示角色全部信息 返回的是自己封裝的api規範
      int AddRole(Role role);
      /// <summary>
      /// 添加角色和許可權關係表
      /// </summary>
      /// <param name="roleId"></param>
      /// <param name=""></param>
      /// <returns></returns>
      int AddRole_Permission(int? roleId,string permissionIds);
      ApiResultData GetRole_Permission(int roleId);
      Role GetRole(int id);
  }
   
   
  //介面實現
  public class RoleRespository : IRoleRespository
  {
      private readonly AppDbContext appDbContext;
      public RoleRespository(AppDbContext appDbContext)
      {
          this.appDbContext = appDbContext;
      }
//添加角色信息
      public int AddRole(Role role)
      {
          this.appDbContext.roles.Add(role);
          return this.appDbContext.SaveChanges();
      }

//添加角色的許可權 實現一對多   一個角色可以有多個許可權
      public int AddRole_Permission(int? roleId, string permissionIds)
      {
          try
          {
          //判斷角色id是否為空
              if (roleId == null||string.IsNullOrEmpty(permissionIds)) return 0;
              //如果不為空刪除角色全部許可權  
              appDbContext.role_Permissions.RemoveRange(appDbContext.role_Permissions.Where(u=>u.RoleId == roleId));
              //這裡從新添加角色許可權  
              foreach (var item in permissionIds.Split(','))
              {
                  Role_Permission role_Permission = new Role_Permission();
                  role_Permission.RoleId = (int)roleId;
                  role_Permission.PermissionId = Convert.ToInt32(item);
                  appDbContext.role_Permissions.Add(role_Permission);
              }
              return this.appDbContext.SaveChanges();
          }
          catch (Exception)
          {

              throw;
          }
           
      }

//獲取角色全部信息
      public ApiResultData GetRole()
      {

          return new ApiResultData { Data = this.appDbContext.roles.ToList()};
      }

//查詢角色單個實體
      public Role GetRole(int id)
      {
          var role = this.appDbContext.roles.Find(id);
          return role;
      }

//通過角色id 查找對應的許可權id
      public ApiResultData GetRole_Permission(int roleId)
      {
          return new ApiResultData
          {
              Data = appDbContext.role_Permissions.Where(u => u.RoleId == roleId
          ).Select(u => u.PermissionId)
          };
      }
  }

用戶信息的介面及實現

 public interface IUserRespository
  {
      bool AddUser(User user); //添加用戶信息
      ApiResultData GetUserAll(); //獲取所有用戶信息
      ApiResult Login(User user); //登陸
  }
   
  //實現介面
  public class UserRespository : IUserRespository
  {
      private readonly AppDbContext appDbContext;
      public UserRespository(AppDbContext appDbContext)
      {
          this.appDbContext = appDbContext;
      }
      //添加角色信息
      public bool AddUser(User user)
      {
      //這裡開啟事務 因為需要操作兩張表添加數據
          using var begin = this.appDbContext.Database.BeginTransaction();
          try
          {
          //這裡添加用戶信息 密碼採用MD5加密方式 底下有代碼
              user.Password = Md5Helper.encrypt(user.Password);
              this.appDbContext.users.Add(user);
              this.appDbContext.SaveChanges();

//添加角色和用戶關聯的表
              foreach (var item in user.RoleIds.Split(',')) //這裡需要分割角色id 因為是多個id
              {
                  User_Role user_Role = new User_Role();
                  user_Role.UserId = user.Id;
                  user_Role.RoleId = Convert.ToInt32(item); //這裡需要把字元串id 轉為數字類型
                  this.appDbContext.user_roles.Add(user_Role);
              }
              this.appDbContext.SaveChanges();
              begin.Commit(); //關閉事務
              return true;
          }
          catch (Exception)
          {
              begin.Rollback(); //回滾 如果有一張表操作失敗 兩個添加都不會執行
              return false;
          }
      }

//獲取用戶的全部信息
      public ApiResultData GetUserAll()
      {
          return new ApiResultData { Data = this.appDbContext.users.ToList()};
      }

//實現登陸信息
      public ApiResult Login(User user)
      {
      //通過 MD5對要登錄的密碼加密 然後從資料庫查詢賬號密碼
          user.Password = Md5Helper.encrypt(user.Password);
          User userInfor = this.appDbContext.users.FirstOrDefault(u=>u.UserName==user.UserName&&u.Password == user.Password);
          if (userInfor == null) return new ApiResult { Code =ResponseCode.Fail , Data = userInfor, Message =GetEnumDescription.GetDescription(ResponseCode.Fail) };   //這裡使用的返回類型是封裝好的apiresult
          return new ApiResult { Code = ResponseCode.Success, Data = userInfor,Message= GetEnumDescription.GetDescription(ResponseCode.Success) };
      }
  }

返回的apiresult MD5加密方式 還有DTO

 //MD5加密方式
public static class Md5Helper
  {
      /// <summary>
      /// MD5加密(32位)
      /// </summary>
      /// <param name="str">加密字元</param>
      /// <returns></returns>
      public static string encrypt(string str)
      {
          string cl = str;
          string pwd = "";
          MD5 md5 = MD5.Create();
          byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(cl));
          for (int i = 0; i < s.Length; i++)
          {
              pwd = pwd + s[i].ToString("X");
          }
          return pwd;
      }
  }
  //apiresult 介面返回的規範
    public class ApiResult
  {
      public ResponseCode Code { get; set; } //狀態碼   類型是枚舉
      public string Message { get; set; } =string.Empty;
      public dynamic Data { get; set; }
      public bool Success =>Code== ResponseCode.Success;   //這裡是返回成功的狀態
  }
  //左側菜單返回的dto
  public class MenoDto
  {
      public int Id { get; set; }
      public string PermissionCode { get; set; }
      public string PermissionName { get; set; }
      public string PermissionIco { get; set; }
      public string PermissionUrl { get; set; }
      public bool Enable { get; set; } = true;
      public string ParentCode { get; set; }
      public List<MenoDto> menoDtos { get; set; }
  }
  //枚舉類型 返回的狀態碼
    // <summary>
  /// 響應code枚舉
  /// </summary>
  public enum ResponseCode
  {
      [Description("通用錯誤碼")]
      Fail = -1,
      [Description("登錄成功")]
      Success = 200,
      [Description("登錄失敗")]
      LoginFail = 201,// 登錄失敗
      /// <summary>
      /// 未授權,需要重新登錄
      /// </summary>
      [Description("未授權")]
      Unauthorized = 401,
      /// <summary>
      /// 未授權,不需要重新登錄,無許可權操作
      /// </summary>
      [Description("未授權")]
      Unauthorized1 = 1000, //未授權
      [Description("未知異常")]
      UnknownEx = 500, //未知異常標識
      [Description("資料庫異常")]
      DbEx = 999, //資料庫操作異常
      [Description("數據為空")]
      DataIsNull = 1002, //數據為空
      [Description("數據格式錯誤")]
      DataFormatError = 1003, //數據格式錯誤
      [Description("數據錯誤")]
      DataTypeError = 1004, //數據類型錯誤
      [Description("數據驗證失敗")]
      RequestDataVerifyFail = 1005, //請求數據驗證失敗
      [Description("數據錯誤")]
      UnityDataError = 1006, //統一數據處理錯誤碼
  }
  //這個類是返回apiresult的時候 獲取枚舉的值  
    public static class GetEnumDescription
  {
      /// <summary>
      /// 獲取枚舉的描述
      /// </summary>
      /// <param name="en"></param>
      /// <returns></returns>
      public static string GetDescription(Enum en)
      {
          //反射 獲取枚舉的類型
          Type type = en.GetType();
          //獲取所有的成員  
          var members = type.GetMember(en.ToString());
          if (members!=null && members.Length>0)
          {
              var desc = members[0].GetCustomAttributes(typeof(DescriptionAttribute),false);
              if (desc!=null&&desc.Length>0)
              {
                  return (desc[0] as DescriptionAttribute).Description;
              }
          }
          return type.ToString();
      }
  }

控制器實現角色api 用戶api 許可權api

//許可權api
[Route("api/[controller]/[action]")]
  [ApiController]
  [Authorize]   //這裡使用了JWT
  public class PermissionController : ControllerBase
  {
  //依賴註入 使用許可權的介面 還有redis的介面
      private readonly IPermissionRespository permissionRespository;
      private readonly IDistributedCache distributedCache;
      public PermissionController(IPermissionRespository permissionRespository,
          IDistributedCache distributedCache
          )
      {
          this.permissionRespository = permissionRespository;
          this.distributedCache = distributedCache;
      }

//通過角色id獲取許可權
      [HttpGet]
      public IActionResult GetPermission(int userId)
      {
      //這裡的key是角色的id
          var key = $"userId_{userId}_menu";
          //查詢redis是否存入信息
          var value = this.distributedCache.GetString(key);
          if (string.IsNullOrEmpty(value))
          {
              //訪問資料庫
              var list = this.permissionRespository.GetPermissions(userId);
              this.distributedCache.SetString(key,
                  JsonConvert.SerializeObject(list), new
                  DistributedCacheEntryOptions().SetSlidingExpiration(System.TimeSpan.FromSeconds(6))
                  ); //寫入redis資料庫   這裡需要序列化為字元串
          }
          //從redis裡面取的數據需要反序列化為list集合
          var result = JsonConvert.DeserializeObject<dynamic>(this.distributedCache.GetString(key));
          return Ok(result);
      }
  }
   
   
  //用戶api
    [Route("api/[controller]/[action]")]
  [ApiController]
  public class UserController : ControllerBase
  {
  //依賴註入 角色介面 還有jwt鑒權 登陸成功返回token碼 然後通過token碼訪問api介面
      private readonly IUserRespository userRespository;
      private readonly JwtToken jwtToken;
      public UserController(IUserRespository userRespository, JwtToken jwtToken = null)
      {
          this.userRespository = userRespository;
          this.jwtToken = jwtToken;
      }

      [HttpPost]
      public IActionResult AddUser(User user)
      {
          return Ok(this.userRespository.AddUser(user));
      }

      [HttpGet]
      public IActionResult GetUser()
      {
          return Ok(this.userRespository.GetUserAll());
      }

      [HttpPost]
      [AllowAnonymous]
      public IActionResult Login(User user)
      {
          var userInfor = this.userRespository.Login(user);
          if (userInfor.Success) //判斷是否登陸成功
          {
              User entity = userInfor.Data as User;
              var token = jwtToken.GenerateToken(entity.UserName);
              //JWT驗證碼存入響應頭 前端登陸需要從頭部獲取token碼
              HttpContext.Response.Headers["token"] = token;
              HttpContext.Response.Headers["Access-Control-Expose-Headers"] = "token";
              return Ok(userInfor);
          }
          return BadRequest(userInfor); //狀態碼400
      }
  }
   
  //角色api
   
  [Route("api/[controller]/[action]")]
  [ApiController]
  public class RoleController : ControllerBase
  {
      private readonly IRoleRespository roleRespository;
      public RoleController(IRoleRespository roleRespository)
      {
          this.roleRespository = roleRespository;
      }

      [HttpGet]
      public IActionResult GetRole(int id)
      {
          var role = this.roleRespository.GetRole(id);
          return Ok(role);
      }

      [HttpGet]
      public IActionResult GetRoleList([FromServices] IMapper mapper)
      {
          var role = this.roleRespository.GetRole();
          return Ok(role);
      }


      [HttpPost]
      public IActionResult AddRole(Role role)
      {
          return Ok(this.roleRespository.AddRole(role));
      }

      [HttpPost]
      public IActionResult AddRolePermission(int roleId,string permissionIds)
      {
          return Ok(roleRespository.AddRole_Permission(roleId,permissionIds));
      }

      [HttpGet]
      public IActionResult GetRoleIdByPermissoins(int roleId)
      {
          var role = roleRespository.GetRole_Permission(roleId);
          return Ok(role);
      }

  }

三、鑒權授權 ---JWT

授權的功能類 -----登陸功能用的這個 可以看用戶api

 public class JwtToken
  {
      public IConfiguration Configuration { get; }
      public JwtToken(IConfiguration configuration)
      {
          this.Configuration = configuration;
      }
      /// <summary>
      /// 生產令牌
      /// </summary>
      /// <param name="userName">用戶名</param>
      /// <param name="expireMinutes">過期時間</param>
      /// <returns></returns>
      public string GenerateToken(string userName,int expireMinutes=30)
      {
     
          //獲取發生人
          var issuer = Configuration.GetSection("JwtSettings:Issuer").Value;
          //獲取的是密鑰
          var signKey = Configuration.GetSection("JwtSettings:SignKey").Value;
//上邊兩條數據從配置文件讀取 在下麵
          var claims = new List<Claim>();
          //添加主題
          claims.Add(new Claim(JwtRegisteredClaimNames.Sub, issuer));
          claims.Add(new Claim(JwtRegisteredClaimNames.Jti, userName));

          //添加角色信息
          claims.Add(new Claim("Role", "User"));
          claims.Add(new Claim("userId", "Admin"));

          var userClaimsIdentity = new ClaimsIdentity(claims);
          //根據signKey 得到加密之後的key
          var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(signKey));
          //加密方式
          var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);

          // 建立 SecurityTokenDescriptor
          var tokenDescriptor = new SecurityTokenDescriptor
          {
              Issuer = issuer,
              //Audience = issuer, // 由於你的 API 受眾通常沒有區分特別對象,因此通常不太需要設定,也不太需要驗證
              //NotBefore = DateTime.Now, // 預設值就是 DateTime.Now
              //IssuedAt = DateTime.Now, // 預設值就是 DateTime.Now
              Subject = userClaimsIdentity,
              Expires = DateTime.Now.AddMinutes(expireMinutes),
              SigningCredentials = signingCredentials
          };

          // 產出所需要的 JWT securityToken 物件,並取得序列化後的 Token 結果(字串格式)
          var tokenHandler = new JwtSecurityTokenHandler();
          var securityToken = tokenHandler.CreateToken(tokenDescriptor);
          var serializeToken = tokenHandler.WriteToken(securityToken);

          return serializeToken;


      }
  }
   
  //配置文件
  "RedisConnectionStrings": "127.0.0.1:6379,password=,defaultDatabase=0,connectTimeout=5000,syncTimeout=1000", //這裡是連接redis的字元串
"JwtSettings": {
  "Issuer": "JwtAuthDemo", //發行人
  "SignKey": "ABCDEFOSAODIOJGOIEJF2902SJDFOISDJGOIJOIJ" //長度大於16個字元以上的字元串 //私鑰
}

四、最重要的Startup類 完成介面的依賴註入 還有鑒權授權

public void ConfigureServices(IServiceCollection services)
      {
          services.AddSwaggerGen(c =>
          {
              c.SwaggerDoc("v1", new OpenApiInfo { Title = "Week2", Version = "v1" });
              #region 開啟Swagger認證   這裡實現的是api界面有一個驗證token碼的視窗 需要輸入token碼才能訪問介面
              c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
              {

                  Description = "在下框中輸入請求頭中需要添加Jwt授權Token:Bearer Token",
                  Name = "Authorization",
                  In = ParameterLocation.Header,
                  Type = SecuritySchemeType.ApiKey,
                  BearerFormat = "JWT",
                  Scheme = "Bearer"
              });

              c.AddSecurityRequirement(new OpenApiSecurityRequirement
              {
                  {
                      new OpenApiSecurityScheme
                      {
                          Reference = new OpenApiReference {
                              Type = ReferenceType.SecurityScheme,
                              Id = "Bearer"
                          }
                      },
                      new string[] { }
                  }
              });
              #endregion
          });
          //實現依賴註入
          services.AddScoped<IPermissionRespository, PermissionRespository>();
          services.AddScoped<IUserRespository, UserRespository>();
          services.AddScoped<IRoleRespository, RoleRespository>();
          services.AddSingleton<JwtToken>();
          //配置Redis
          services.AddStackExchangeRedisCache(options =>
          {
              options.Configuration = Configuration.GetSection("RedisConnectionStrings").Value;
                //options.InstanceName = "SampleInstance";
            });
          //jwp鑒權
          services
          .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
          .AddJwtBearer(options =>
          {
              // 當驗證失敗時,回應標頭會包含 WWW-Authenticate 標頭,這裡會顯示失敗的詳細錯誤原因
              options.IncludeErrorDetails = true; // 預設值為 true,有時會特別關閉

              options.TokenValidationParameters = new TokenValidationParameters
              {
                  // 透過這項宣告,就可以從 "sub" 取值並設定給 User.Identity.Name
                  NameClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier",
                  // 透過這項宣告,就可以從 "roles" 取值,並可讓 [Authorize] 判斷角色
                  RoleClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role",

                  // 一般我們都會驗證 Issuer
                  ValidateIssuer = true,
                  ValidIssuer = Configuration.GetValue<string>("JwtSettings:Issuer"),

                  // 通常不太需要驗證 Audience
                  ValidateAudience = false,
                  //ValidAudience = "JwtAuthDemo", // 不驗證就不需要填寫

                  // 一般我們都會驗證 Token 的有效期間
                  ValidateLifetime = true,

                  // 如果 Token 中包含 key 才需要驗證,一般都只有簽章而已
                  ValidateIssuerSigningKey = false,

                  // "1234567890123456" 應該從 IConfiguration 取得
                  IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration.GetValue<string>("JwtSettings:SignKey")))
              };
          });
      }
       
       
      //中間件需要添加
        //鑒權
          app.UseAuthentication();
          //授權
          app.UseAuthorization();

五、項目使用的nuget包如下


Microsoft.AspNetCore.Authentication.JwtBearer (5.0.16) //jwt鑒權
Microsoft.EntityFrameworkCore(5.0.16)
Microsoft.EntityFrameworkCore.Design (5.0.16)
Microsoft.EntityFrameworkCore.sqlServer (5.0.16)
Microsoft.EntityFrameworkCore.Tools (5.0.16)
Microsoft.Extensions.Caching.StackExchangeRedis (5.0.1) //redis緩存
Swashbuckle.AspNetCore (5.6.3)

六、前端vue

 

1.路由的配置

const routes = [
{
path: '/',
name: 'home',
redirect:'/login', //重定向登陸頁面為初始化
component: Home,
children:[ //導航頁面的子集
{
path: 'system/user', //跳轉到用戶頁面
name: 'User',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/system/User.vue')
},
{
path: 'system/role', //跳轉到角色頁面
name: 'Role',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/system/Role.vue')
},
{
path: 'system/permission', //跳轉到許可權的頁面
name: 'Permission',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/system/Permission.vue')
}
]
},
{
path: '/login',
name: 'Login',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/Login.vue')
}
]


//路由守衛 判斷token碼是否為空 如果空跳轉到登陸頁面
router.beforeEach((to,form,next)=>{
//判斷你要進入的是登陸頁面,正常執行
if(to.path=='/login')next();
else{
let token = sessionStorage.getItem('token');
if(token==null||token == '') next('/login');
next();
}
})

封裝axios的請求

//axios 又封裝了一層
import axios from "axios" //導入axios

//創建axios 起個名$http
const $http = axios.create({
baseURL:'http://localhost:56405/',
timeout:7000 //預設超時時間 1000毫秒 等1秒
})

//vue 請求攔截
$http.interceptors.request.use(config=>{
//獲取token 信息
let token = sessionStorage.getItem('token')
if(token){
//把請求帶上頭部信息 再請求api
config.headers.Authorization = 'Bearer ' +token
}
return config
})


//導出 將當前$http 供外部使用
export default $http

左側菜單遞歸實現

<template>
<div class="page">
<el-container>
<el-header>八位用戶許可權管理系統 <el-button type="danger" @click="quit">退出</el-button>
</el-header>
<el-container>
<el-aside width="200px">
<menu-tree :menuData="this.menus"></menu-tree> //實現父給子組件傳值
</el-aside>
<el-main>
<router-view></router-view>
</el-main>
</el-container>
</el-container>
</div>
</template>

<script>
import MenuTree from "@/components/MenuTree.vue"
export default
{
name: 'aHome',
data () {
return {
menus: []
}
},
components: { MenuTree }, //顯示子組件信息
methods: {
menu () {
var userId = sessionStorage.getItem('userId')
this.$http.get(`/api/Permission/GetPermission?userId=${userId}`).then(res => {
this.menus = res.data
console.log(res.data)
// res.data = this.option(o => {
// this.opens.push(o.Id)
// })
// console.log(res.data)
})
}
},
created () {
this.menu()
}
}
</script>


//子組件遞歸實現左側菜單展示
<template>
<div class="page">
<el-menu default-active="2" class="el-menu-vertical-demo" :default-openeds=opens router background-color="#545c64" text-color="#fff" active-text-color="#ffd04b">
<template v-for="item in this.menuData">
<el-submenu v-if="item.menoDtos.length>0" :index="item.Id.toString()" :key="item.Id">
<template slot="title"> //迴圈一級導航 判斷一級菜單是否大於零 是的話顯示一級菜單
<i :class="item.PermissionIco"></i>
<span>{{item.PermissionName}}</span>
</template>
<MenuTree :menuData="item.menoDtos"></MenuTree> //迴圈調用此組件實現遞歸
</el-submenu>//如果一級導航的子節點有數據則顯示
<el-menu-item v-else :key="item.menoDtos.Id" :index="item.PermissionUrl">
<template slot="title"> <i :class="item.PermissionIco"></i><span>{{item.PermissionName}}</span></template>
</el-menu-item>
</template>
</el-menu>
</div>
</template>

//組件接收父組件的傳值
<script>
export default {
name: 'MenuTree',
data () {
return {
opens: ['1'] //預設index = 1為展開方式
}
}, props: ['menuData'], //接收父組件的數據

}

查看角色的許可權以及給角色分配許可權

//這裡面只是script的methods方法的代碼    頁面佈局直接element托組件
methods: {
upd (index, row) {

this.dialogFormVisible1 = true //關閉模態框
this.RoleName = row.RoleName
this.roleId = row.Id
this.$refs.tree.setCheckedKeys([]) //清空節點的信息 通過角色id查詢許可權的節點
this.$http.get(`/api/Role/GetRoleIdByPermissoins?roleId=${this.roleId}`).then(res => {
res.data.Data.forEach(e => {
let node = this.$refs.tree.getNode(e) //迴圈給節點賦值
//判斷是否為葉子節點
if (node.isLeaf) {
this.$refs.tree.setChecked(node, true)
}
console.log(res.data.Data)
});
})
},
addPermission () {

let chk = this.$refs.tree.getCheckedKeys()
let half = this.$refs.tree.getHalfCheckedKeys() //這兩個方法獲取節點的id 如果只選擇子節點 會自動勾選父節點
this.permissionIds = chk.concat(half) //這個方法把獲取的兩個節點信息拼接成數組
//分配許可權
this.$http.post(`/api/Role/AddRolePermission? roleId=${this.roleId}&permissionIds=${this.permissionIds.toString()}`).then(res => {
if (res.data > 0) {
this.$message.success('許可權設置成功')
this.dialogFormVisible1 = false
} else {
this.$message.error('許可權設置失敗')
}
})
},
//顯示角色信息
load () {
this.$http.get(`/api/Role/GetRole`).then(res => {
this.tableData = res.data.Data
})
},
//通過角色id查詢許可權
getPermission () {
var userId = sessionStorage.getItem('userId')
this.$http.get(`/api/Permission/GetPermission?userId=${userId}`).then(res => {
this.data = res.data
console.log(res.data)
// res.data = this.option(o => {
// this.opens.push(o.Id)
// })
// console.log(res.data)

})
}
}

還有重要的一點就是登陸成功的時候向頭部heads添加token碼 然後給api授權訪問

 Login () {
this.$http.post(`/api/User/Login`, this.ruleForm).then(res => {
if (res.data.Code == 200) {
this.$message.success(res.data.Message)
sessionStorage.setItem('userId', res.data.Data.Id);
//獲取請求頭的信息
sessionStorage.setItem("token", res.headers.token); //這裡是獲取的token碼
this.$router.push('system/role')
} else {
this.$message.error(res.data.Message)
}
})
}
 
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 我前面使用的jdbc和jdbc的工具類集成的但是它們在少部分代碼的情況下會會簡單,但是以後如果項目較大jdbc的固定代碼會很難維護,如果使用框架會簡單很多,也標志著java學習正式進入到框架階段 ...
  • Hi, 我是Mic。 今天分享一道一線互聯網公司必問的面試題。 ”JVM如何判斷一個對象可以被回收“ 關於這個問題,來看看普通人和高手的回答。 普通人: 嗯。。。。。。。。。。 高手: 好的,面試官。 在JVM裡面,要判斷一個對象是否可以被回收,最重要的是判斷這個對象是否還在被使用,只有沒被使用的對 ...
  • 前言 今天的這個腳本,是一個別人發的外包,交互界面的代碼就不在這裡說了,但是可以分享下自動評論、自動點贊、自動關註、採集評論和視頻的數據是如何實現的 開發環境 python 3.8 運行代碼pycharm 2021.2 輔助敲代碼requests 第三方模塊 原理: 模擬客戶端,向伺服器發送請求 對 ...
  • 案例標題:用python可視化分析,B站Top100排行榜數據。 分析流程: 一、數據讀取 二、數據概覽 三、數據清洗 四、可視化分析 ·相關性分析-散點圖(scatter) ·得分分佈-餅圖(pie) ·各指標分佈-箱形圖(boxplot) ·視頻作者分析-詞雲圖(wordcloud) ...
  • 0、前言 這篇博客是給認識的那幫新手搞的,剛進入IT行業的崽們 這個東西配置好了,也可以選擇弄成線上文檔,下一次安裝IDEA時,有一個import導入配置,然後就可以自己配置好了( 雖然方便,但不建議用 ) 另外:IDEA建議別漢化,一開始接觸不習慣,後續使用一段時間之後就很舒服了 jetBrain ...
  • 一、SpringMVC使用 1.工程創建 創建maven工程。 添加java、resources目錄。 引入Spring-webmvc 依賴。 <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc< ...
  • 前後連續的電腦語句組合在一起並有名字可供調用稱之為函數,本章主要介紹如何在程式中定義和使用函數其中包括如何調用函數、使用參數、使用參數的*和**運算,返回數值。如果把電腦語句比為武術動作的話,那麼函數就可以比喻為功夫“套路”,本質上“降龍十八掌”就是包含了18個語句的函數,那麼“葵花寶典”呢? ...
  • .NET CORE 1.Microsoft Azure 微軟擁抱雲計算 2..net core 是為雲所生的技術 3.Net Framework缺點: 系統級別的安裝,互相影響 無法獨立部署 SAP.NET和IIS深度耦合 非雲原生 4.NET Framework歷史包袱 基於拖控制項之上的MVC A ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...