webapi框架搭建-安全机制(四)-可配置的基于角色的权限控制

更新时间:2023-05-16 09:23:59 阅读: 评论:0

webapi框架搭建-安全机制(四)-可配置的基于⾓⾊的权限控制
  在上⼀篇的,某个⾓⾊拥有哪些接⼝的权限是⽤硬编码的⽅式写在接⼝上的,如RBAuthorize(Roles = "ur,member"),在⼩的项⽬⾥,其实也够⽤了,但如果项⽬的需求就是要可在后台管理界⾯⾥动态配置某某⾓⾊有某某接⼝的权限怎么办?这编我们⼀起来实现。
  ⾸先,我们要在数据库⾥存储这些需要权限控制的接⼝,其次,要在上编的RBAuthorizeAttribute的IsAuthorized⽅法⾥重写⾃⼰逻辑。实体设计(数据库表设计)
  共4张表:⽤户表、⾓⾊表、资源表、权限表
  ⽤户表:只记录⽤户的基本信息,如id,⽤户名,姓名,性别,密码等
  ⾓⾊表:只记录⾓⾊的基本信息,如⾓⾊名,id
  资源表:只记录“需要做权限控制的资源”,这些“资源”可以是菜单,接⼝等。
  权限表:记录“哪些⾓⾊对哪些资源有访问权限”
  ⽤户⾓⾊关系表:记录⽤户和⾓⾊的关系教学目的
四个表的实体对应如下
⽤户表
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace webapi.Entities
{
/// <summary>
/// ⽤户表
/// </summary>
[Table("Ur")]
public partial class Ur:BaEntity
{
/// <summary>
ps导出gif/// 主键
/// </summary>
[Key, Column(TypeName = "varchar"), MaxLength(50)]
public string Id { get; t; }
/// <summary>
/// 登录名
/// </summary>
[Column(TypeName = "varchar"), MaxLength(50)]
public string LoginName { get; t; }
/// <summary>
/// 真实姓名
/// </summary>
[Column(TypeName = "varchar"), MaxLength(50)]
public string Name { get; t; }
/// <summary>
/// 密码,⽤于存储密码的md5加密
/// </summary>
[Column(TypeName = "varchar"), MaxLength(50)]
public string Pwd { get; t; }
/
// <summary>
/// 性别,1男2⼥,对应Gender枚举
/// </summary>
[Column(TypeName = "int")]
public int? Gender { get; t; }
/// <summary>
/// ⾝份证
/// </summary>
[Column(TypeName = "varchar"), MaxLength(50)]
public string IdentityCard { get; t; }
/// <summary>
/
// 电话
/// </summary>
[Column(TypeName = "varchar"), MaxLength(50)]
public string Tel { get; t; }
/// <summary>
/// 出⽣⽇期
/// </summary>
[Column(TypeName = "datetime")]
public DateTime? Birthdate { get; t; }
/// <summary>
/// 头像
/
// </summary>
[Column(TypeName = "varchar"), MaxLength(500)]
public string UrPic { get; t; }
}
}
  ⾓⾊表
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; namespace webapi.Entities
{
/// <summary>
/// ⾓⾊表
/
// </summary>
[Table("Role")]
public partial class Role:BaEntity
{
/// <summary>
/// ⾓⾊ID
/// </summary>
[Key, Column(TypeName = "varchar"), MaxLength(50)]        public string Id { get; t; }
/// <summary>
/// ⾓⾊名
/// </summary>
[Column(TypeName = "varchar"), MaxLength(20)]
public string Name { get; t; }
}
}
  ⽤户⾓⾊关系表
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; namespace webapi.Entities
{
/// <summary>
/// ⽤户⾓⾊关系对应表,ur role map
/// </summary>
[Table("URM")]
public partial class URM:BaEntity
{
/// <summary>
/// ID主键
/// </summary>
[Key, Column(TypeName = "varchar"), MaxLength(50)]        public string Id { get; t; }
/// <summary>
/// ⽤户ID
/// </summary>
[Column(TypeName = "varchar"), MaxLength(50)]
public string UrId { get; t; }
/// <summary>
/// ⾓⾊ID
/// </summary>
[Column(TypeName = "varchar"), MaxLength(50)]
public string RoleId { get; t; }
}
}
  资源表
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; namespace webapi.Entities
{
/// <summary>
/// 需要做权限控制的资源
/// </summary>
[Table("Resource")]
public class Resource:BaEntity
{
/// <summary>
/// 主键
/// </summary>
[Key,Column(TypeName = "varchar"),MaxLength(50)]
public string Id { t; get; }
/// <summary>
/// 资源类型,如webapi接⼝,菜单等
/// </summary>
[Column(TypeName = "varchar"), MaxLength(20)]
public string Category { t; get; }
/// <summary>
/// 资源名,如“ControllerName.ActionName”,或是“url地址”
/// </summary>
[Column(TypeName = "varchar"), MaxLength(100)]
public string Name { t; get; }
/
// <summary>
/// 资源描述
/// </summary>
[Column(TypeName = "varchar"), MaxLength(200)]
public string Description { t; get; }
}
}
词的定义
  权限表
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace webapi.Entities
{
/// <summary>
/// 权限表,记录⾓⾊和资源的对应关系
/// </summary>
[Table("Permission")]
public class Permission:BaEntity
{
一年级上册试卷/// <summary>
/// 主键
/// </summary>
[Key, Column(TypeName = "varchar"), MaxLength(50)]
public string Id { t; get; }
/// <summary>
/// 资源类型,如webapi接⼝,菜单等
/// </summary>
[Column(TypeName = "varchar"), MaxLength(50)]
public string RoleId { t; get; }
/// <summary>
/// 资源名,如“ControllerName.ActionName”,或是“url地址”
/// </summary>
[Column(TypeName = "varchar"), MaxLength(50)]
墨西哥城市public string ResourceId { t; get; }
}
}
RBAuthorizeAttribute代码修改核⼼代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Security.Principal;
using System.Web.Http;
using System.Web.Http.Controllers;
using webapi.Entities;
identifyingusing webapi.Services;
namespace webapi.Security
{
/// <summary>
/// Role Basic AuthorizeAttribute(基于⾓⾊的授权)
/// </summary>
public class RBAuthorizeAttribute : AuthorizeAttribute
{
public string Description { t; get; }
protected override bool IsAuthorized(HttpActionContext actionContext)
{
// 下在可替换成⾃⼰的授权逻辑代码
AuthorizeService authorizeService =new AuthorizeService(new DB());
var resourceName = actionContext.ActionDescriptor.GetCustomAttributes<RBAuthorizeAttribute>().Any()
actionContext.ActionDescriptor.ActionName
: actionContext.ControllerContext.ControllerDescriptor.ControllerName;
var roleNames = authorizeService.GetResourceRoleNames(resourceName);
IPrincipal principal = actionContext.ControllerContext.RequestContext.Principal;
return principal != null && principal.Identity != null
&& principal.Identity.IsAuthenticated &&
(
(((IEnumerable<string>)roleNames).Any<string>(new Func<string, bool>(principal.IsInRole)))
);
}
protected override void HandleUnauthorizedRequest(HttpActionContext actionContext)
{
actionContext.Respon =
actionContext.ControllerContext.Request.CreateErrorRespon(HttpStatusCode.Unauthorized, "未授权");
}
}
}
  说明:在IsAuthorized⽅法⾥判断⽤户是否有某个资源的权限。下⾯是我的思路
1)获取⽤户的⾓⾊
  在前⾯的博客⾥,IdentityBasicAuthentication已经从http请求头⾥将token解密并知道了⽤户的⾓⾊,并将⾓⾊写⼊到了IPrincipal对象,所以RBAuthorizeAttribute只要从IPrincipal⾥取出来就⾏,即如下的代码:IPrincipal principal =
actionContext.ControllerContext.RequestContext.Principal;
  2)获取该请求资源的所有⾓⾊数组
  我创建了authorizeService类,⽤于处理这⼀个逻辑,博友们可以下载我的框架,只要改⼀下authorizeService类⾥的GetResourceRoleNames⽅法就⾏。 
  3)判断是否有权限
    ⾸先principal不能为空,且principal.Identity是已经通过⾝份验证的(即Identity.IsAuthenticated==true),并且⽤户的⾓⾊在资源权限⾓⾊数组⾥。
return principal != null && principal.Identity != null
&& principal.Identity.IsAuthenticated &&
(
(((IEnumerable<string>)roleNames).Any<string>(new Func<string, bool>(principal.IsInRole)))
);
各辅助代码也附上
AuthorizeService代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using webapi.Entities;
namespace webapi.Services
樱桃番茄
{
public class AuthorizeService:BaService
{
public AuthorizeService(DB db) : ba(db)
{
}
/// <summary>
/// 获取资源的⾓⾊名数组
/// </summary>
/// <param name="resourceName"></param>
/// <returns></returns>
public string[] GetResourceRoleNames(string resourceName)
{
var resource=_db.Resources.FirstOrDefault(a => a.Name == resourceName);
var roleIds = _db.Permissions.Where(a => a.ResourceId == resource.Id).Select(a => a.RoleId).ToArray();
var roleNames = _db.Roles.Where(a => roleIds.Contains(a.Id)).Select(a => a.Name).ToArray();
return roleNames;
王雨晴
}
}
}

本文发布于:2023-05-16 09:23:59,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/82/652310.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:资源   权限   逻辑   代码   记录
相关文章
留言与评论(共有 0 条评论)
   
验证码:
推荐文章
排行榜
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图