dotnet core微服务框架Jimu ~ 会员授权微服务

提供授权服务,用户使用会员的用户名和密码获取 token, 带着 token 访问受保护的接口,如浏览和发布新闻。

有 2 个公开的 api:

  1. token: 获取 token;
  2. GetCurrentMemberInfo: 获取当前 token 的会员信息;

有 1 个不公开的方法:

  1. GetMemberInfo:根据会员用户名和密码,获取会员信息,该方法供获取 token 的 api 调用;

1 声明接口,创建基于 .Net Core 6.0 的类库项目,命名为 Auth.IServices

1.1 添加 jimu 引用

复制代码
Install-Package  Jimu

1.2 创建 dto 类

复制代码
using System;
using System.Collections.Generic;
using System.Text;

namespace Auth.IServices
{
    public class MemberInfo
    {
        public string Id { get; set; }
        public string Name { get; set; }
        public string NickName { get; set; }
        public string Role { get; set; }

    }
}

1.3 声明公开的微服务接口

复制代码
using System;
using System.Collections.Generic;
using System.Text;
using Jimu;

namespace Auth.IServices
{
    public interface IAuthMemberService : IJimuService
    {
        MemberInfo GetMemberInfo(string username, string password);
    }
}

上面的接口只继承 IJimuService, 不声明访问路由和接口属性,因为它不公开给外部调用的,但要用 autofac 注册到系统,在生成 token 时调用,所以需要继承 IJimuService。

复制代码
using System;
using System.Threading.Tasks;
using Jimu;

namespace Auth.IServices
{
    [JimuServiceRoute("/api/v1/member")]
    public interface IMemberService : IJimuService
    {
        [JimuService(EnableAuthorization = true, CreatedBy = "grissom", CreatedDate = "2018-07-17", Comment = "get current token member info")]
        MemberInfo GetCurrentMemberInfo();
    }
}

上面的接口声明了 EnableAuthorization = true,需要授权的用户才能访问(即请求时要带上 token),该方法是获取当前会员信息。

2 实现接口,创建基于 .Net Core 6.0 的类库项目,命名为 Auth.Services

2.1 添加对接口项目 Auth.IServices 的引用

2.2 实现接口

复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Auth.IServices;
using Jimu;

namespace Auth.Services
{
    public class AuthMemberService : IAuthMemberService
    {
        static List<MemberInfo> _membersDb = new List<MemberInfo>();
        readonly ILogger _logger;
        public AuthMemberService(ILogger logger)
        {
            _logger = logger;
        }

        static AuthMemberService()
        {
            // mock some member 
            _membersDb.Add(new MemberInfo { Id = Guid.NewGuid().ToString(), Name = "grissom", NickName = "Gil", Role = "admin" });
            _membersDb.Add(new MemberInfo { Id = Guid.NewGuid().ToString(), Name = "foo", NickName = "Fo", Role = "guest" });
        }

        public MemberInfo GetMemberInfo(string username, string password)
        {
            var member = _membersDb.FirstOrDefault(x => x.Name == username && "123" == password);

            _logger.Debug($"username: {username}, found {(member == null ? "no " : "")} member.");

            return member;
        }
    }
}

logger 是通过依赖注入的

复制代码
using Jimu;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Auth.IServices
{
    public class MemberService : IMemberService
    {
        readonly ILogger _logger;
        readonly JimuPayload _jimuPayload;
        public MemberService(ILogger logger, JimuPayload jimuPayload)
        {
            _logger = logger;
            _jimuPayload = jimuPayload;
        }

        public MemberInfo GetCurrentMemberInfo()
        {
            _logger.Debug($"current token member username: {_jimuPayload.Items["username"]}");

            return Newtonsoft.Json.JsonConvert.DeserializeObject<MemberInfo>(_jimuPayload.Items["member"].ToString());
        }


    }
}

logger 和 jimuPayload 都是通过依赖注入的。JimuPayload 是 Jimu 框架解析 token 获取的一些生成 token 时,添加的信息(参考下面生成 token 的方法)。如果请求的 token 无效,则 JimuPayload 为 null。

3 微服务的宿主服务器,创建基于 .Net Core 2.0 的控制台应用, 命名为 Auth.Server

3.1 添加对项目: Auth.Services 的引用

3.2 添加 jimu.server 和 Jimu.Common.Discovery.ConsulIntegration 引用

复制代码
Install-Package  Jimu.Server
Install-Package  Jimu.Common.Discovery.ConsulIntegration

3.3 启动 jimu 服务和生成 token 的代码

复制代码
using System;
using Autofac;
using Jimu;
using Jimu.Server;
using Jimu.Server.OAuth;
using Auth.IServices;

namespace Auth.Server
{
    class Program
    {
        static void Main(string[] args)
        {
            IServiceHost host = null;

            var builder = new ServiceHostServerBuilder(new ContainerBuilder())
             .UseLog4netLogger()
             .LoadServices("Auth.IServices", "Auth.Services")
             .UseDotNettyForTransfer("127.0.0.1", 8000)
             .UseConsulForDiscovery("127.0.0.1", 8500, "JimuService", $"127.0.0.1:8000")
             .UseJoseJwtForOAuth<DotNettyAddress>(new JwtAuthorizationOptions
             {
                 SecretKey = "123456", // 生成 token 的密钥
                 ExpireTimeSpan = new TimeSpan(3, 0, 0, 0), // token 有效时间 3 天
                 ValidateLifetime = true, // 是否启动验证 token 的有效时间
                 ServerIp = "127.0.0.1", // 生成 token 的宿主服务器地址
                 ServerPort = 8000, // 生成 token 的宿主服务器端口
                 TokenEndpointPath = "api/oauth/token?username=&password=", // 获取 token 的路由,注意后缀 ?username=&password= 是固定的
                 CheckCredential = new Action<JwtAuthorizationContext>(ctx =>
                 {
                     var memberService = host.Container.Resolve<IAuthMemberService>();

                     var member = memberService.GetMemberInfo(ctx.UserName, ctx.Password);
                     if (member == null)
                     {
                         ctx.Rejected("username or password is incorrect.", "");
                     }
                     else
                     {
                         // 上面提到的 JimuPayload 就是包含这些数据
                         ctx.AddClaim("roles", member.Role); // 添加角色到 token
                         ctx.AddClaim("member", Newtonsoft.Json.JsonConvert.SerializeObject(member)); // 把整个 member 序列化打包到 token

                     }
                 }), // 生成 token 的配置项和验证逻辑
             });
            using (host = builder.Build())
            {
                host.Run();
                while (true)
                {
                    Console.ReadKey();
                }
            }
        }
    }
}
相关推荐
fanly111 天前
Surging AI Agent 完整产品介绍
微服务·microservice
曲幽7 天前
Termux里的二进制和脚本,到底怎么运行才不踩坑?Termux-service 保活妙招!
android·termux·nohup·services·wake-lock
蝎子莱莱爱打怪7 天前
XZLL-IM干货系列 04|Netty 长连接实战:Pipeline 怎么排、心跳怎么跳、连接怎么管
后端·微服务·面试
SamDeepThinking8 天前
Java微服务练习方式
java·后端·微服务
米丘11 天前
微前端之 Web Components 完全指南
微服务·html
霸道流氓气质14 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
霸道流氓气质14 天前
Spring Boot 微服务性能优化完全指南
spring boot·微服务·性能优化
地瓜伯伯15 天前
从MESI缓存一致性协议讲透synchronized的底层
java·spring boot·spring·spring cloud·微服务·springcloud
Devin~Y15 天前
大厂 Java 面试实录:从音视频内容社区到 AI RAG 的全链路技术设计
java·spring boot·redis·spring cloud·微服务·kafka·音视频
递归尽头是星辰15 天前
AI 访问数据仓库:从直连到微服务化
数据仓库·人工智能·微服务·dataagent·ai数据治理