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推荐的组件。

posted @ 2020-08-21 23:52  mbpframework  阅读(205)  评论(0编辑  收藏  举报