.net core webapi + vue 实现RBAC 基本的权限管理

  • .net core webapi + vue 实现RBAC 基本的权限管理已关闭评论
  • 272 次浏览
  • A+
所属分类:.NET技术
摘要

根据用户id显示权限的接口 角色接口及实现 用户信息的接口及实现 返回的apiresult MD5加密方式 还有DTO


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)
}
})
}