概述
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:


在网关中配置统一身份认证
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 应使用随机生成的强密钥,并通过环境变量或配置中心进行管理,不应硬编码在配置文件中。
