我们分析了ABP如何判断用户登录,下面我们通过一个伪造的登录页面,验证我们的想法。
通过伪造的登录界面通过ABP的权限验证
为了验证我们的猜想,我们创建一个登录页面,在后台代码中写入一些登录信息,看是否能通过ABP的权限验证。我们创建一个Login页面,在后台LoginModel中写入伪登录代码:
using Microsoft.AspNetCore.Authentication;
using System.Collections.Generic;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Mvc.RazorPages;
namespace ZL.Poem.WebApi.Pages
{
public class LoginModel : PageModel
{
public async Task OnGet()
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, "a@b.c"),
new Claim(ClaimTypes.NameIdentifier, "1"),
new Claim("FullName", "admin"),
new Claim(ClaimTypes.Role, "Guest"),
};
var claimsIdentity = new ClaimsIdentity(
claims, CookieAuthenticationDefaults.AuthenticationScheme);
var authProperties = new AuthenticationProperties();
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity),
authProperties);
var user = User;
}
}
}
代码很简单,标准的基于Cookie的验证代码。再次启动程序,首先运行Login页面,然后在执行GetAllCategoires,这次可以了,验证通过了。
权限验证IPermissionChecker
现在我们已经有了解决办法:只要在我们现有系统登录完成后,再使用基于Cookie的HttpContext.SignInAsync对ABP支持的Claim进行注册,就可以通过ABP进行权限验证了。下面,我们看一下,如果在ABP中验证权限。ABP验证权限的接口是IPermissionChecker,我们可以通过实现这个接口,编写自己的权限验证代码:
using Abp;
using Abp.Authorization;
using Abp.Runtime.Session;
using System.Threading.Tasks;
namespace ZL.Poem.Application.Permission
{
public class MyPermissionChecker : IPermissionChecker
{
private IAbpSession session;
public MyPermissionChecker(IAbpSession _session)
{
session = _session;
}
public Task<bool> IsGrantedAsync(string permissionName)
{
var uid = session.UserId;
//throw new NotImplementedException();
return Task.FromResult(true);
}
public Task<bool> IsGrantedAsync(UserIdentifier user, string permissionName)
{
//throw new NotImplementedException();
return Task.FromResult(true);
}
}
}
这里我们只是返回了true,代表允许执行。实际项目中,会根据传入权限的名称以及用户id,从数据库中获取权限数据进行验证。
限制
ABP通过IAbpSession中的UserId,进行权限验证,UserId的数据类型是整型,如果现有系统需要在ClaimTypes.NameIdentifier中写入其它类型变量,会出现错误。如果我们修改伪登录页面的代码,将“1”修改为“admin”:
new Claim(ClaimTypes.NameIdentifier, "admin"),
再次访问GetAllCategories时,会发生没有登录的错误。
总结
在将ABP集成到现有系统时,可以将用户id写入Claim中,与ABP的权限验证进行集成。然后通过实现IPermissionChecker接口实现权限验证。