SSO 单点登录
Identity 的认证能力可对接基于 OpenIddict 实现的 OAuth2/OIDC 单点登录:多个业务应用共享同一个认证入口,用户登录一次即可访问所有受信应用;微服务之间也通过同一套 Token 完成校验。
架构
Auth.Host 是统一认证方,底层身份数据来自 Identity;业务模块不再各自实现登录,而是信任 Auth.Host 签发的 Token。
快速开始
1. 部署 Auth 模块
dotnet run --project src/Services/Auth/FreeKit.Host
2. 配置业务模块
{
"Security": {
"OpenIddict": {
"Authority": "https://auth.example.com",
"ClientId": "my-app",
"ClientSecret": "my-secret",
"Scope": ["openid", "profile", "email"]
}
}
}
3. 注册认证服务
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = OpenIddictValidationDefaults.AuthenticationScheme;
})
.AddOpenIddictValidation(options =>
{
options.Authority = configuration["Security:OpenIddict:Authority"];
options.ClientId = configuration["Security:OpenIddict:ClientId"];
options.ClientSecret = configuration["Security:OpenIddict:ClientSecret"];
});
配置选项
{
"Security": {
"Sso": {
"TokenExpiresIn": 86400,
"CodeExpiresInMinutes": 5
},
"OpenIddict": {
"Authority": "https://auth.example.com",
"ClientId": "my-app",
"ClientSecret": "my-secret",
"Scope": ["openid", "profile", "email", "roles"]
}
}
}
认证流程
授权码流程
刷新令牌流程
账号绑定流程(社交登录)
当用户已在 Identity 登录、再把第三方账号绑定时,走"绑定回调"而非"登录回调",绑定关系落到 IdentityUserLogin,最终仍是同一个 IdentityUser。
前端集成
JavaScript 客户端
// 使用 oidc-client
import { UserManager } from 'oidc-client';
const config = {
authority: 'https://auth.example.com',
client_id: 'my-app',
redirect_uri: 'https://myapp.example.com/callback',
scope: 'openid profile email',
response_type: 'code'
};
const userManager = new UserManager(config);
// 登录
await userManager.signinRedirect();
// 登录回调
const user = await userManager.signinRedirectCallback();
// 获取 Token
const user = await userManager.getUser();
const token = user.access_token;
.NET 客户端
// 添加认证
builder.Services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIddictDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIddict(options =>
{
options.ClientId("my-app");
options.ClientSecret("my-secret");
options.Authority("https://auth.example.com");
options.Scope("openid");
options.Scope("profile");
options.Scope("email");
});
// 使用
[Authorize]
public class ProtectedController : FreeKitController
{
[HttpGet]
public IActionResult Get()
{
return Ok(new { User = CurrentUser });
}
}
运维建议
| 建议 | 说明 |
|---|---|
| 使用 HTTPS | 生产环境必须使用 HTTPS |
| 定期轮换密钥 | 定期轮换 ClientSecret |
| 监控 | 监控 Token 颁发和使用 |
| 备份 | 定期备份授权数据 |
故障排查
| 问题 | 解决方案 |
|---|---|
| 认证失败 | 检查 Authority 和 ClientId |
| Token 无效 | 检查 Token 过期时间 |
| 跨域问题 | 配置 CORS |