mbp-micro微服务解决方案集成使用IdentityServer4的做身份验证服务
一,前言
在Mbp框架中是采用的基于JWT验签这种比较简单的令牌检查方式,基本上是能满足要求。但是不遵循Openid Connect协议,所以在安全性和系统集成方面有短板。所以在mbp-micro的微服务解决方案中,采用IdentityServer4来做身份认证中心。请看交互流程
二,IdentityServer4服务端
1.如何连接到数据库进行账号密码验证
-
打开appsettings.json修改数据库配置,配置节点为:
ConnectionStrings:IBPDatabase
-
编写用户信息模型类,代码文件地址:Model\UserLoginModel.cs
-
编写验证逻辑代码,需要移植原来的登录逻辑,打开代码文件:AdditionalService\ResourceOwnerPasswordValidator
在方法ValidateAsync中进行处理
public Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
{
//根据context.UserName和context.Password与数据库的数据做校验,判断是否合法
if (!string.IsNullOrEmpty(context.UserName) && !string.IsNullOrEmpty(context.Password))
{
UserLoginModel loginInfo = new UserLoginModel();
// 连接数据库进行请求用户的身份验证处理
using (IDbConnection db = new MySqlConnection(Configuration["ConnectionStrings:IBPDatabase"]))
{
loginInfo = db.Query<UserLoginModel>("Select USER_ID,PASSWORD From sys_ac_user where USER_ID=@USER_ID", new { USER_ID = context.UserName }).FirstOrDefault();
}
// 根据返回的用户信息,写入到access_token中
List<Claim> claims = new List<Claim>();
claims.Add(new Claim("cutomize-birday", "生日"));
claims.Add(new Claim("cutomize-address", "地址"));
claims.Add(new Claim(ClaimTypes.Role, "admin"));
context.Result = new GrantValidationResult(
subject: context.UserName,
authenticationMethod: OidcConstants.AuthenticationMethods.Password,
claims: claims
);
}
else
{
//验证失败
context.Result = new GrantValidationResult(
TokenRequestErrors.InvalidGrant,
"invalid custom credential"
);
}
return Task.FromResult(0);
}
2.如何在返回的token信息中添加自定义的key-value键值对
- 打开代码文件:AdditionalService\CustomTokenRequestValidator,在方法ValidateAsync中追加,如下所示
/// <summary>
/// 自定义验证
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public Task ValidateAsync(CustomTokenRequestValidationContext context)
{
if (context.Result.IsError)
{
}
// 添加自定义返回参数
//context.Result.CustomResponse = new Dictionary<string, object>();
//context.Result.CustomResponse.Add("aa", "bb");
// 修改请求token的参数
return Task.FromResult(0);
}
3.如何扩展其他的认证请求方式在
-
在文件夹RequestFactory中添加类并且继承GrantRequest,然后实现Token方法,如下所示
public override async Task<TokenResponse> Token(HttpClient client, DiscoveryDocumentResponse discovery, RequestParam tokenRequest) { var tokenResponse = await client.RequestPasswordTokenAsync(new PasswordTokenRequest { Address = discovery.TokenEndpoint, GrantType = tokenRequest.GrantType, ClientId = "MicroService", ClientSecret = "insces", Scope = "offline_access", Password = tokenRequest.Password, UserName = tokenRequest.UserName }); return tokenResponse; }
4.如何制作证书
#生成私钥文件
openssl genrsa -out idsrv4.key 2048
#创建证书签名请求文件 CSR(Certificate Signing Request),用于提交给证书颁发机构(即 Certification Authority (CA))即对证书签名,申请一个数字证书。
openssl req -new -key idsrv4.key -out idsrv4.csr
#生成自签名证书(证书颁发机构(CA)签名后的证书,因为自己做测试那么证书的申请机构和颁发机构都是自己,crt 证书包含持有人的信息,持有人的公钥,以及签署者的签名等信息。当用户安装了证书之后,便意味着信任了这份证书,同时拥有了其中的公钥。)
openssl x509 -req -days 365 -in idsrv4.csr -signkey idsrv4.key -out idsrv4.crt
#自签名证书与私匙合并成一个文件
openssl pkcs12 -export -in idsrv4.crt -inkey idsrv4.key -out idsrv4.pfx
或
openssl req -newkey rsa:2048 -nodes -keyout idsrv4.key -x509 -days 365 -out idsrv4.cer
openssl pkcs12 -export -in idsrv4.cer -inkey idsrv4.key -out idsrv4.pfx
拷贝出证书文件即可。
文件介绍:idsrv4.crt(公钥),idsrv4.key(密钥),idsrv4.pfx(数字证书)
5.如何管理ApiScope
- 支持但暂不引入
三,Rest API服务端配置
1.fx框架下的token验签和解析
-
使用jwt.io官方推荐的.net库,System.IdentityModel.Tokens.Jwt,这里还给出另一种实现方法,因为另一个官方推荐的库使用人数较多,但是这个库的验证点较少,扩展性不好。
-
验签状态结果码枚举
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp1.Code { /// <summary> /// 验签错误码 /// </summary> public enum EnumVerifyStatusCode { /// <summary> /// 验签成功 /// </summary> OK = 1, /// <summary> /// 过期 /// </summary> TokenExpired = 2, /// <summary> /// 非法Token /// </summary> SecurityTokenInvalid = 3, /// <summary> /// 无效的公钥 /// </summary> Cryptographic = 4, /// <summary> /// 其他错误 /// </summary> Other = 99 } }
-
验签解析成功后的用户信息类
using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp1.Code { public class UserContext { /// <summary> /// 验签状态 /// </summary> public EnumVerifyStatusCode VerifyStatusCode { get; set; } /// <summary> /// 用户名 /// </summary> public string UserName { get; set; } /// <summary> /// 登录名 /// </summary> public string LoginName { get; set; } /// <summary> /// 电子邮箱 /// </summary> public string Email { get; set; } /// <summary> /// 电话号码 /// </summary> public string Phonenumber { get; set; } public override string ToString() { return JsonConvert.SerializeObject(this); } } }
-
还有fx框架下的验签帮助类,这里就不公开了,使用jwt,io推荐的组件。