NetCore项目实战篇04---集成IdentityService4

大家都知道我们的项目中已有web api,现在可以正式访问,不论任何人只要通过输入对应的api网址就可以访问到我们的api 资源,这样是很不安全的,我们需求对当前用户进行身份验证,因此我们在项目中使用IdentityServer4来对受保护资源并实现身份验证和/或授权,直接开始上代码,这些代码直接可以在你的项目中使用,并跑起来。

1、  新建一个空的.netcore web项目,并引入IdentityService4的NuGet包。

2、  在项目中增加一个config.cs文件

 public class Config
    {
        public static IEnumerable<Client> GetClients()
        {
            return new List<Client>
            {
                new Client
                {
                    ClientId="iphone",
                    ClientSecrets = new List<Secret>
                    {
                        new Secret("secret".Sha256())
                    },
                    RefreshTokenExpiration = TokenExpiration.Sliding,
                    AllowOfflineAccess = true,
                    RequireClientSecret = false,
                    AllowedGrantTypes = new List<string>{"sms_suth_code"},
                    AlwaysIncludeUserClaimsInIdToken = true,
                    AllowedScopes = new List<string>
                    {
                        "gateway_api",
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        IdentityServerConstants.StandardScopes.OfflineAccess,
                    },

                },
                new Client
                {
                    ClientId="android",
                    ClientSecrets = new List<Secret>
                    {
                        new Secret("secret".Sha256())
                    },
                    RefreshTokenExpiration = TokenExpiration.Sliding,
                    AllowOfflineAccess = true,
                    RequireClientSecret = false,
                    AllowedGrantTypes = new List<string>{"sms_auth_code"},
                    AlwaysIncludeUserClaimsInIdToken = true,
                    AllowedScopes = new List<string>
                    {
                        "gateway_api",
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.Profile,
                        IdentityServerConstants.StandardScopes.OfflineAccess,
                    },

                }
            };
        }
        public static IEnumerable<IdentityResource> GetIdentityResources()
        {
            return new List<IdentityResource>
            {
                new IdentityResources.OpenId(),
                new IdentityResources.Profile(),
            };
        }
        public static IEnumerable<ApiResource> GetApiResources()
        {
            return new List<ApiResource>
            {
                new ApiResource("gateway_api","user service")
            };
        }
        
    }

3、在项目中新增类SmsAuthCodeValidator该类主要是实现IdentityServer4组件中的IextensionGrantValidator接口ValidateAsync()的方法,在该方法写上自己的验证逻辑,这里我们只用户在登录时输入的手机号和验证码进行了校验,当然在校验时会调用用户模块的api,也就是我们_userService.CheckOrCreate(phone)方法,服务之前如何发现和调用这里不展开,下节介绍。SmsAuthCodeValidator代码如下

public class SmsAuthCodeValidator : IExtensionGrantValidator
    {
        private readonly IAuthCodeService _authCodeService;
        private readonly IUserService _userService;
        public SmsAuthCodeValidator(IAuthCodeService authCodeService, IUserService userService)
        {
            _authCodeService = authCodeService;
            _userService = userService;
        }
        public string GrantType => "sms_auth_code";

        public async Task ValidateAsync(ExtensionGrantValidationContext context)
        {
            var phone = context.Request.Raw["phone"];
            var code = context.Request.Raw["auth_code"];
            var error = new GrantValidationResult(TokenRequestErrors.InvalidGrant);
            if(!string.IsNullOrEmpty(phone)&& !string.IsNullOrEmpty(code))
            {
                //用户检查
                _authCodeService.Validate(phone, code);
                //用户注册
                var userId = await _userService.CheckOrCreate(phone);
                if(userId <=0)
                {
                    context.Result = error;
                    return;
                }

                context.Result = new GrantValidationResult(userId.ToString(), GrantType);
            }
            else
            {
                context.Result = error;

            }

            
        }
    }

4、在SmsAuthCodeValidator类我们引用了两个本地的服务,一个是对验证码进行校验的AuthCodeService类,一个是对手机号进行校验的UserService,也就是在这个类中对用户服务模块进行的手机号校验。现将这两个代码的代码写上

public interface IAuthCodeService
    {
        /// <summary>
        /// 验证
        /// </summary>
        /// <param name="phone">手机号</param>
        /// <param name="authCone">验证码</param>
        /// <returns></returns>
        bool Validate(string phone, string authCone);
    }


public class AuthCodeService : IAuthCodeService
    {
        public bool Validate(string phone, string authCone)
        {
            return true;
        }
    }
public interface IUserService
    {
        /// <summary>
        /// 检查手机是否注册,如果没有就创建
        /// </summary>
        /// <param name="phone"></param>
        Task<int> CheckOrCreate(string phone);
    }

public class UserService : IUserService
    {
        
        public async Task<int> CheckOrCreate(string phone)
        {
          
            return 1;

        }
    }

5、最后我们需要增加IdentityServer4中间件,并对我们的服务进行配置

public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddIdentityServer()
                .AddExtensionGrantValidator<SmsAuthCodeValidator>()
                .AddDeveloperSigningCredential()
                .AddInMemoryClients(Config.GetClients())
                .AddInMemoryIdentityResources(Config.GetIdentityResources())
                .AddInMemoryApiResources(Config.GetApiResources());
            services.AddSingleton(new HttpClient());
            services.AddScoped<IAuthCodeService, AuthCodeService>()
                .AddScoped<IUserService, UserService>();

            services.AddMvc();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            app.UseIdentityServer();
            app.UseMvc();
        }
    }

5、 生成并启动该项目,通过postman访问,需求增加如下六个参数

 

 

 

6、如果没有问题的话我们会获取到系统反馈给我们的token值,返回结果如下:

{
    "access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjlhMjJlN2E3Zjg1ZmY5MjNiMTJmM2Nm
NGZkMGM3YzYzIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1ODg5MjE2MjUsImV4cCI6
MTU4ODkyNTIyNSwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDoxMTEwIiwiYXVkIjpb
Imh0dHA6Ly9sb2NhbGhvc3Q6MTExMC9yZXNvdXJjZXMiLCJnYXRld2F5X2FwaSJd
LCJjbGllbnRfaWQiOiJhbmRyb2lkIiwic3ViIjoiMyIsImF1dGhfdGltZSI6MTU4
ODkyMTYyNSwiaWRwIjoibG9jYWwiLCJzY29wZSI6WyJvcGVua
WQiLCJwcm9maWxlIiwiZ2F0ZXdheV9hcGkiLCJvZmZsaW5lX2FjY2VzcyJdLCJhb
XIiOlsic21zX2F1dGhfY29kZSJdfQ.pyEKOe08jiqtg1rgcf0UGO0hmfEhI5a2cIXw
_-YgXdLVceKa14Jhyy8Ezgom3ipNlci5FwmN-p5ro_3ORtzreU0qxhiCzI5kyPgLRP
lOO8cFykYKY4yQOCD_z2LohSxyvAsTPn0B75_iodujGPQAB4Outs9uAjcHXAnxjBkn
DKl6L5uu609ZaugG4X6T2xx0ZDU-VftrrmB-YX5oe6FU70R4jsRLayL8nrM-u-Q_We
UIfY04M91REX9HqneOGyxSDj2Qku22pC68dlIYQNGhBlYUnSqRMkk39Pe9UmjO8dSp
qqBMtHBEwCQn3cMzG7UbP5gB6F2GgTICUBERbxxwRA
", "expires_in": 3600, "token_type": "Bearer", "refresh_token": "f3051fa24cebf7cbfa73b55563a283bb3c15b129c8c5ff732324a653a7c6eff1" }

7、 怀着好奇的心我们来看看这个access_token的值反馈给我们的是什么,其实他就是JWT(Json Web Token),解析成json格式如下

 {
 alg: "RS256",

 kid: "9a22e7a7f85ff923b12f3cf4fd0c7c63",

 typ: "JWT"

}.
{
 nbf: 1588921625,

 exp: 1588925225,

 iss: "http://localhost:1110",

 aud: [
  "http://localhost:1110/resources",

  "gateway_api"

 ],

 client_id: "android",

 sub: "3",

 auth_time: 1588921625,

 idp: "local",

 scope: [
  "openid",

  "profile",

  "gateway_api",

  "offline_access"

 ],

 amr: [
  "sms_auth_code"

 ]

}. 
[signature]

顺便学习一下JWT吧:

       HTTP提供了一套标准的身份验证框架:服务器可以用来针对客户端的请求发送质询(challenge),客户端根据质询提供身份验证凭证。质询与应答的工作流程如下:服务器端向客户端返回401(Unauthorized,未授权)状态码,并在WWW-Authenticate头中添加如何进行验证的信息,其中至少包含有一种质询方式。然后客户端可以在请求中添加Authorization头进行验证,其Value为身份验证的凭证信息。

      Bearer认证(也叫做令牌认证)是一种HTTP认证方案,其中包含的安全令牌的叫做Bearer Token。因此Bearer认证的核心是Token。那如何确保Token的安全是重中之重。一种方式是使用Https,另一种方式就是对Token进行加密签名。而JWT就是一种比较流行的Token编码方式。可以看出JWT有三部分组成:

<header>.<payload>.<signature>

  1. Header:由algtyp组成,alg是algorithm的缩写,typ是type的缩写,指定token的类型。该部分使用Base64Url编码。
  2. Payload:主要用来存储信息,包含各种声明,同样该部分也由BaseURL编码。
  3. Signature:签名,使用服务器端的密钥进行签名。以确保Token未被篡改。

下一篇我们将介绍网关,通过网关来访问我们的用户模块的api资源,并集成IdentityServer4

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值