企业级工作流解决方案(十二)--集成Abp和ng-alain--用户身份认证与权限验证
多租户
如果系统需要支持多租户,那么最好事先定义好多租户的存储部署方式,Abp提供了几种方式,根据需要选择,每一个用户身份认证与权限验证都需要完全的隔离
这里设计的权限数据全部存储在缓存中,每个租户单独建立缓存Key,见权限系统服务章节介绍。
用户accesstoken
accesstoken的定义就不多的介绍了,Abp其实就是直接使用微软IdentityModel这套组件,并且zero项目还直接使用的微软的用户角色相关管理,这里面性能存在一定的问题,而且使用相对比较复杂,还不利于扩展,其实功能就那么一些,完全没有必要用这一套用户角色管理。
其实这里要做的核心扩展,就是自定义Claim信息,accesstoken信息其实是存在Claim集合里面的,我们可以自定义Claim信息,用户登录的时候,调用组件提供的接口,创建用户访问的accesstoken信息,我这里扩展了RoleIds集合信息和UserName信息,UserName在系统很多地方都可能用到,而RoleIds集合信息用于做权限控制。
实现代码
public class AuthTokenProvider: IAuthTokenProvider
{
private readonly TokenAuthConfiguration _configuration;
public AuthTokenProvider(TokenAuthConfiguration configuration)
{
_configuration = configuration;
}
public AuthenticateResultModel Authenticate(LoginResultModel loginResultModel)
{
List<Claim> claims = new List<Claim>();
claims.Add(new Claim(AbpClaimTypes.UserId, loginResultModel.UserId.ToString()));
if (loginResultModel.TenantId.HasValue)
{
claims.Add(new Claim(AbpClaimTypes.TenantId, loginResultModel.TenantId.ToString()));
}
claims.Add(new Claim(AbpClaimTypes.RoleIds, loginResultModel.RoleIds)); // 自定义RoleIds和UserName申明
claims.Add(new Claim(AbpClaimTypes.UserName, loginResultModel.UserName)); var accessToken = CreateAccessToken(claims); return new AuthenticateResultModel
{
AccessToken = accessToken,
EncryptedAccessToken = GetEncrpyedAccessToken(accessToken),
ExpireInSeconds = (int)_configuration.Expiration.TotalSeconds,
UserId = loginResultModel.UserId
};
} private string CreateAccessToken(IEnumerable<Claim> claims, TimeSpan? expiration = null)
{
var now = DateTime.UtcNow; var jwtSecurityToken = new JwtSecurityToken(
issuer: _configuration.Issuer,
audience: _configuration.Audience,
claims: claims,
notBefore: now,
expires: now.Add(expiration ?? _configuration.Expiration),
signingCredentials: _configuration.SigningCredentials
); return new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken);
} private static List<Claim> CreateJwtClaims(List<Claim> claims)
{
var nameIdClaim = claims.First(c => c.Type == ClaimTypes.NameIdentifier); // Specifically add the jti (random nonce), iat (issued timestamp), and sub (subject/user) claims.
claims.AddRange(new[]
{
//new Claim(JwtRegisteredClaimNames.Sub, nameIdClaim.Value),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Iat, DateTimeOffset.Now.ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64)
}); return claims;
} private string GetEncrpyedAccessToken(string accessToken)
{
return SimpleStringCipher.Instance.Encrypt(accessToken, CoreModule.DefaultPassPhrase);
}
}
Ng-alain前端页面Token
ng-alain前端页面也有权限管理,主要是delon项目里面的权限管理,核心其实也是在Token的管理,ITokenService,定义了管理Token的接口,ITokenModel定义了token和一个自定义存储的数据字典,在路由拦截的时候,添加了对Token是否为空的验证,我们在登录的时候,对token进行赋值,退出登录清空token。
默认Token是存储在LocalStorage里面的,根据需要,可以改为SessionStorage。
用户登录
/**
* 登录结果回调
* @param authenticateResult 登录结果
*/
private processAuthenticateResult(authenticateResult: AuthenticateResultModel) {
if (authenticateResult.accessToken) {
// 设置用户Token信息
this.tokenService.set({
token: authenticateResult.accessToken, userId: authenticateResult.userId
, expireInSeconds: authenticateResult.expireInSeconds,encryptedAccessToken:authenticateResult.encryptedAccessToken
});
// 重新获取 StartupService 内容,我们始终认为应用信息一般都会受当前用户授权范围而影响
this.startupSrv.load().then(() => {
let url = this.tokenService.referrer.url || '/';
if (url.includes('/passport')) url = '/';
this.router.navigateByUrl(url);
}); } else {
this.error = "用户名或密码错误!";
return;
}
}
退出登录
logout() {
this.tokenService.clear();
this.signalRService.CloseSignalr();
this.router.navigateByUrl(this.tokenService.login_url);
}
ng-alain权限管理
export interface ITokenModel {
[key: string]: any;
token: string;
}
export interface AuthReferrer {
url?: string;
}
export interface ITokenService {
set(data: ITokenModel): boolean;
/**
* 获取Token,形式包括:
* - `get()` 获取 Simple Token
* - `get<JWTTokenModel>(JWTTokenModel)` 获取 JWT Token
*/
get(type?: any): ITokenModel;
/**
* 获取Token,形式包括:
* - `get()` 获取 Simple Token
* - `get<JWTTokenModel>(JWTTokenModel)` 获取 JWT Token
*/
get<T extends ITokenModel>(type?: any): T;
clear(): void;
change(): Observable<ITokenModel>;
/** 获取登录地址 */
readonly login_url: string;
/** 获取授权失败前路由信息 */
readonly referrer?: AuthReferrer;
}
http拦截
由于Abp后端需要验证accesstoken,abp对错误信息和请求结果信息进行了封装,因此,需要替换ng-alain的http拦截器,自定义拦截器。
自定义拦截器主要是对每一个http请求,从ITokenService里面获取token,添加到请求Header里面;以及对答复内容,提取答复内容和显示错误信息。
添加请求Token
protected addAuthorizationHeaders(headers: HttpHeaders): HttpHeaders {
let authorizationHeaders = headers ? headers.getAll('Authorization') : null;
if (!authorizationHeaders) {
authorizationHeaders = [];
}
if (!this.itemExists(authorizationHeaders, (item: string) => item.indexOf('Bearer ') == 0)) {
let token = (this.injector.get(DA_SERVICE_TOKEN) as ITokenService).get();
// let token = this._tokenService.getToken();
if (headers && token) {
headers = headers.set('Authorization', 'Bearer ' + token.token);
}
}
return headers;
}
答复内容参照abp提供的前端框架代码即可
Ng-alain前端权限验证
也是delon项目里面的acl功能模块,只需要在用户登录成功的时候,把用户能够访问的操作Code集合传递给acl,以及在页面使用的地方,定义权限控制的Code即可
// ACL:设置权限为全量
// this.aclService.setFull(true);
this.aclService.setAbility(res.operate);
控件控制
<button (click)="add()" acl [acl-ability]="'adminuser-add'" nz-button nzType="primary">新建</button>
列表按钮控制
{
text: '删除', type: 'del', acl:{ ability:['adminuser-delete']}, click: (item: any) => {
this.http.delete(`api/services/app/SEC_AdminUser/Delete?Id=${item.id}`).subscribe(() => this.st.reload());
}
},
路由控制
{ path: 'operate', loadChildren: './sec-operate/sec-operate.module#SecOperateModule', canActivate: [ACLGuard], data: {
guard: <ACLType>{ability: ['operate-mgt']}
}}, // 操作管理
企业级工作流解决方案(十二)--集成Abp和ng-alain--用户身份认证与权限验证的更多相关文章
- 企业级工作流解决方案(六)--微服务消息处理模型之与Abp集成
身份认证传递 对于Abp比较熟悉的朋友应该对他里面的用户身份认证比较熟悉,他是通过实现微软提供的权限认证方式实现的,用户登录身份信息存储在System.Security.Claims.ClaimsPr ...
- JEECG 集成KiSSO单点登录实现统一身份认证
JEECG 集成KiSSO单点登录实现统一身份认证 JEECG 如何为其他第三方系统实现统一身份认证服务,实现单点登录? 第三方系统如何对接呢? 今天为大家揭开这层面纱,让大家了解实质,使用它更快速的 ...
- 企业级工作流解决方案(十五)--集成Abp和ng-alain--Abp其他改造
配置功能增强 Abp定义了各种配置接口,但是没有定义这些配置数据从哪里来,但是管理配置数据对于一个应用程序来说,是必不可少的一件事情. .net的配置数据管理,一般放在Web.config文件或者Ap ...
- 企业级工作流解决方案(十)--集成Abp和ng-alain--权限系统
权限系统 应用系统离不开权限控制,权限中心不一定能抽象出所有的业务场景,这里定义的权限系统不一定能够满足所有的场景,但应该可以满足多数的业务需求. Abp的zero项目也定义了权限相关的表,但里面很多 ...
- 企业级工作流解决方案(十一)--集成Abp和ng-alain--权限系统服务
权限系统主要定义为管理员增删改查权限数据,直接读取数据库,权限系统服务主要定义为供其他系统调用的权限验证接口,定义为两个不同的微服务. 权限系统有一个特点,数据变动比较小,数据量本身并不是很大,访问量 ...
- 企业级工作流解决方案(十四)--集成Abp和ng-alain--自动化脚本
对于.net方向,做过自动化的,应该没有人不熟悉msbuild吧,非常强大的代码编译工具,.net平台的编译工作都是交给他来完成的,包括.net core的命令,本质上都是调用msbuild来执行的 ...
- 企业级工作流解决方案(十三)--集成Abp和ng-alain--数据库读写分离
说到程序里面数据库管理,无非就是两件事情,一是数据库操作,对于数据库的操作,各种程序语言都有封装,也就是所谓的ORM框架,.net 方向一般用得比较多和就是.net framework和dapper, ...
- ABP源码分析三十二:ABP.SignalR
Realtime Realtime是ABP底层模块提供的功能,用于管理在线用户.它是使用SignalR实现给在线用户发送通知的功能的前提 IOnlineClient/OnlineClient: 封装在 ...
- SpringCloud微服务实战——搭建企业级开发框架(十二):OpenFeign+Ribbon实现负载均衡
Ribbon是Netflix下的负载均衡项目,它主要实现中间层应用程序的负载均衡.为Ribbon配置服务提供者地址列表后,Ribbon就会基于某种负载均衡算法,自动帮助服务调用者去请求.Ribbo ...
随机推荐
- 阿里云服务器SQLSERVER 2019 远程服务器环境搭建【原创】【转载请注明出处】
之前做过本地服务器SQLSERVER环境搭建.局域网环境SQLSERVER搭建.一直没有尝试自己完成一个云端服务器的环境搭建.今天就根据一个成功的例子给大家分享一下. 一.云端数据库安装与搭建 我的服 ...
- Spring Boot 学习摘要--关于配置
date: 2019-12-27 09:00:00 updated: 2019-12-30 13:20:00 Spring Boot 学习摘要--关于配置 学习教程来自:B站 尚硅谷 1. 关于配置 ...
- SPI、I2C、I2S、UART、GPIO、SDIO、CAN、JTAG的区别及使用方法。
SPI 全称及由来:SPI接口的全称是"Serial Peripheral Interface",意为串行外围接口,是Motorola首先在其MC68HCXX系列处理器上定义的. ...
- tp3.2,php5使用PHPExcel将数据导出至Excel
安装类库 从GitHub上下载PHPExcel类库 地址:https://github.com/PHPOffice/PHPExcel public function checkexcel($id){ ...
- vue-打包遇到的问题
vue-打包 打包后用iframe引入的html文件乱码 原因: 解决:用live server打开就不会乱码 生产环境移除所有的console命令 三种解决方法 发现vue-cli3.0在打包过程中 ...
- 水题挑战2 :NOIP提高组 2011 聪明的质监员
小T 是一名质量监督员,最近负责检验一批矿产的质量.这批矿产共有 \(n\) 个矿石,从\(1\) 到 \(n\) 逐一编号,每个矿石都有自己的重量 \(w_i\) 以及价值 \(v_i\) .检验矿 ...
- Python调用飞书发送消息
一.创建飞书机器人 自定义飞书机器人操作步骤,具体详见飞书官方文档:<机器人 | 如何在群聊中使用机器人?>
- WSL Ubuntu 18.04 LTS + VS Code
WSL Ubuntu 18.04 LTS + VS Code WSL(Windows Subsystem for Linux)使得Windows用户能够在Windows系统上使用原生的Linux环 ...
- SQL Server中约束的介绍
SQL Server中约束的介绍(转载收藏) Posted on 2010-09-03 11:05 grayboy 阅读(8501) 评论(0) 编辑 收藏 作者:GrayBoy 出处:http:// ...
- R-C3D:用于时间活动检测的区域3D网络
论文原称:R-C3D: Region Convolutional 3D Network for Temporal Activity Detection(2017) 主要贡献: 1.提出一个包括活动候选 ...