Skip to content

Instantly share code, notes, and snippets.

@xcaptain
Last active September 6, 2021 09:57
Show Gist options
  • Save xcaptain/920115af7bfe81a57fa58f62ea9e4887 to your computer and use it in GitHub Desktop.
Save xcaptain/920115af7bfe81a57fa58f62ea9e4887 to your computer and use it in GitHub Desktop.
casbinnet asp dotnet core setup
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using TodoApi.Services;
namespace TodoApi.Middlewares
{
public class AuthzMiddleware
{
private readonly RequestDelegate _next;
public AuthzMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context, ICasbinService casbinService)
{
if (context.User.Claims.Count() > 0)
{
// means this to be a controller with [Authorize] annotation
string account = context.User.Claims.FirstOrDefault(p => p.Type.ToString() == "user_id").Value;
if (!casbinService.CheckPermission())
{
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
await context.Response.WriteAsync("Unauthorized!, no bearer token");
return;
}
}
await _next.Invoke(context);
}
}
}
using NetCasbin;
using NetCasbin.Persist;
using NetCasbin.Model;
using System.Collections.Generic;
using System.Text;
using TodoApi.Models;
using System.Linq;
using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Http;
namespace TodoApi.Services
{
public interface ICasbinService
{
Enforcer enforcer { get; }
IEnumerable<string> GetCurrentRoles();
bool CheckPermission();
}
public class CasbinService : ICasbinService
{
public Enforcer enforcer { get; }
private readonly IHttpContextAccessor _httpContextAccessor;
public CasbinService(IServiceScopeFactory factory, IHttpContextAccessor httpContextAccessor)
{
using (var scope = factory.CreateScope())
{
var adapter = scope.ServiceProvider.GetRequiredService<IAdapter>();
enforcer = new Enforcer("./auth_model.conf", adapter);
}
_httpContextAccessor = httpContextAccessor;
}
public IEnumerable<string> GetCurrentRoles()
{
string account = _httpContextAccessor.HttpContext.User.Claims.FirstOrDefault(p => p.Type.ToString() == "user_id").Value;
return enforcer.GetRolesForUser(account);
}
public bool CheckPermission()
{
string account = _httpContextAccessor.HttpContext.User.Claims.FirstOrDefault(p => p.Type.ToString() == "user_id").Value;
return enforcer.Enforce(account, _httpContextAccessor.HttpContext.Request.Path.ToString(), _httpContextAccessor.HttpContext.Request.Method);
}
}
public class PermDbAdapter : IAdapter
{
private readonly IServiceScopeFactory _factory;
public PermDbAdapter(IServiceScopeFactory factory)
{
_factory = factory;
}
public void LoadPolicy(Model model)
{
using (var scope = _factory.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<DbContext>();
var rules = context.CasbinRule.ToList();
LoadPolicyData(model, Helper.LoadPolicyLine, rules);
}
}
public void RemovePolicy(string a1, string a2, IList<string> a3)
{
throw new NotSupportedException("to be done!");
}
public void RemoveFilteredPolicy(string a1, string a2, int a3, params string[] a4)
{
throw new NotSupportedException("to be done!");
}
public void SavePolicy(Model m)
{
throw new NotSupportedException("to be done!");
}
public void AddPolicy(string a1, string a2, IList<string> a3)
{
throw new NotSupportedException("to be done!");
}
private void LoadPolicyData(Model model, Helper.LoadPolicyLineHandler<string, Model> handler, IEnumerable<CasbinRule> rules)
{
foreach (var rule in rules)
{
handler(GetPolicyCotent(rule), model);
}
}
private string GetPolicyCotent(CasbinRule rule)
{
StringBuilder sb = new StringBuilder(rule.PType);
void Append(string v)
{
if (string.IsNullOrEmpty(v))
{
return;
}
sb.Append($", {v}");
}
Append(rule.V0);
Append(rule.V1);
Append(rule.V2);
Append(rule.V3);
Append(rule.V4);
Append(rule.V5);
return sb.ToString();
}
}
}
services.AddScoped<IAdapter, PermDbAdapter>();
services.AddTransient<ICasbinService, CasbinService>();
app.UseMiddleware<AuthzMiddleware>();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment