Silky微服务框架在线文档Silky微服务框架在线文档
首页
文档
配置
源码解析
博文
github
gitee
  • 简体中文
  • English
首页
文档
配置
源码解析
博文
github
gitee
  • 简体中文
  • English
  • 简介

    • silky 框架介绍
  • 入门

    • 名词解释
    • 快速开始
    • 脚手架
    • 微服务模块化架构的最佳实践 & 约定
    • 示例
  • 主机与模块

    • 主机
    • 网关
    • 模块
    • 插件
  • 网关与 HTTP

    • Swagger 文档
    • 性能分析(MiniProfiler)
    • 跨域(CORS)
    • 审计日志
  • 服务与 RPC

    • 应用服务和服务条目
    • rpc通信
    • websocket通信
    •  服务注册中心
    • 服务治理
  • 数据与缓存

    • EFCore 数据访问
    • 缓存
    • 分布式锁
  • 安全与认证

    • 身份认证与授权
    • 分布式事务
  • 基础设施

    • 依赖注入
    • 对象到对象的映射
    • 参数验证
    • 链路跟踪
    • 日志(Serilog)
    • 健康检查
    • 消息总线(MassTransit)
    • 单元测试与集成测试

概述

silky 框架的身份认证与授权采用网关统一处理的设计理念:

  • 认证(Authentication):在网关层通过 JWT Token 验证请求来源的合法性
  • 授权(Authorization):通过 [Authorize]、[AllowAnonymous] 等特性控制接口访问权限
  • RPC 安全:集群内部通过 rpc.token 保护 RPC 通道,外部无法直接访问

生成 JWT Token

步骤一:注入 JWT 服务

在账号管理微服务的服务注册中引入 JWT 服务:

public class ConfigureService : IConfigureService
{
    public void ConfigureServices(IServiceCollection services, IConfiguration configuration)
    {
        services.AddJwt();  // 注册 JWT 服务
    }
}

步骤二:配置 JWT 参数

在 appsettings.yaml 中添加 JWT 配置:

jwtSettings:
  secret: jaoaNPA1fo1rcPfK23iNufsQKkhTy8eh  # Token 密钥(生产环境请使用强密钥)
  issuer: http://silky.com/issuer             # 颁发者,缺省值
  audience: http://silky.com/audience         # 受众,缺省值
  expiredTime: 24                             # Token 有效期,单位:小时,缺省值 24
  algorithm: HS256                            # 加密算法,支持 HS256、HS384、HS512、RS256 等

步骤三:定义登录接口

应用接口层中定义账号服务接口,登录接口使用 [AllowAnonymous] 标记允许匿名访问:

[ServiceRoute]
public interface IAccountAppService
{
    /// <summary>
    /// 用户登录,返回 JWT Token
    /// </summary>
    [AllowAnonymous]  // 登录接口允许匿名访问
    Task<string> Login(LoginInput input);
}

步骤四:实现登录方法

应用层中实现登录逻辑,通过 IJwtTokenGenerator 生成 Token:

public class AccountAppService : IAccountAppService
{
    private readonly IJwtTokenGenerator _jwtTokenGenerator;

    public AccountAppService(IJwtTokenGenerator jwtTokenGenerator)
    {
        _jwtTokenGenerator = jwtTokenGenerator;
    }

    public async Task<string> Login(LoginInput input)
    {
        // 1. 验证用户名和密码(根据实际业务实现)
        var user = await ValidateUserAsync(input.UserName, input.Password);
        if (user == null)
        {
            throw new AuthenticationException("用户名或密码不正确");
        }

        // 2. 构建 Token Payload(Claim 信息)
        var payload = new Dictionary<string, object>
        {
            { ClaimTypes.NameIdentifier, user.Id },
            { ClaimTypes.Name, user.UserName },
            { ClaimTypes.Role, string.Join(",", user.Roles) }
        };

        // 3. 生成 JWT Token
        var token = _jwtTokenGenerator.Generate(payload);

        // 4. 写入响应头 access-token,Swagger 可自动登录
        RpcContext.Context.SigninToSwagger(token);

        return token;
    }
}

登录成功后,通过 /api/account/login 接口即可获取 JWT Token:

identity1.png

identity2.png


在网关中配置统一身份认证

silky 的 HTTP 请求身份认证在网关统一进行。在网关的 Startup 中注册并启用认证中间件:

public void ConfigureServices(IServiceCollection services)
{
    services
        .AddSilkyHttpCore()
        .AddSwaggerDocuments()
        .AddRouting()
        .AddSilkyIdentity();  // 注册身份认证服务
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // ...
    app.UseRouting();
    app.UseSilkyIdentity();  // 启用身份认证中间件(必须在 UseEndpoints 之前)
    app.UseEndpoints(endpoints =>
    {
        endpoints.MapSilkyRpcServices();
    });
}

AuthorizeAttribute 特性

通过 [Authorize] 特性标记需要认证的接口:

[ServiceRoute]
public interface IOrderAppService
{
    // 所有方法默认需要认证(继承接口级别的 [Authorize])
    [Authorize]
    Task<OrderOutput> GetOrderAsync(long id);

    // 也可以基于角色鉴权
    [Authorize(Roles = "Admin,Manager")]
    Task DeleteOrderAsync(long id);
}

AllowAnonymous 特性

通过 [AllowAnonymous] 标记无需认证可公开访问的接口:

[ServiceRoute]
public interface IProductAppService
{
    // 商品列表查询无需登录
    [AllowAnonymous]
    Task<PagedList<ProductOutput>> GetProductsAsync(ProductQueryInput input);

    // 创建商品需要登录
    Task<ProductOutput> CreateProductAsync(CreateProductInput input);
}

获取当前登录用户信息

在微服务中,可以通过 NullSession.Instance 静态属性获取当前登录用户的信息。框架会自动从 RPC 上下文(RpcContext)中解析 JWT Token 携带的用户信息,并使其在整个调用链路中透明传递。

NullSession.Instance 实现了 ISession 接口,包含以下属性:

属性说明
UserId当前登录用户的 ID(对应 JWT 中的 ClaimTypes.NameIdentifier)
UserName当前登录用户的用户名(对应 JWT 中的 ClaimTypes.Name)
TenantId当前租户 ID(多租户场景使用,对应 JWT 中的租户声明)

可以通过扩展方法 IsLogin() 判断当前请求是否已认证:

using Silky.Core.Runtime.Session;

public class OrderAppService : IOrderAppService
{
    public async Task<OrderOutput> GetOrderAsync(long id)
    {
        var session = NullSession.Instance;

        if (!session.IsLogin())
        {
            throw new AuthenticationException("未登录");
        }

        var userId = session.UserId;       // 当前用户 ID
        var userName = session.UserName;   // 当前用户名
        var tenantId = session.TenantId;   // 当前租户 ID(多租户场景)

        // ...业务逻辑
    }
}

说明

NullSession.Instance 底层使用 RpcContextSession,会自动从 RPC 上下文的附件(Attachment)中读取用户信息。只要经过网关身份认证后的请求,在整个 RPC 调用链路中均可通过此方式获取当前用户信息,无需额外注入。


RPC Token 校验

集群内所有微服务(包括网关)必须配置相同的 rpc.token,silky 在 RPC 通信时会自动校验 Token,防止外部绕过网关直接访问 RPC 端口:

rpc:
  token: ypjdYOzNd4FwENJiEARMLWwK0v7QUHPW  # 集群内所有服务必须一致

安全提示

生产环境中 rpc.token 应使用随机生成的强密钥,并通过环境变量或配置中心进行管理,不应硬编码在配置文件中。

编辑当前页
Next
分布式事务