using System.Globalization;
using OpenIddict.Abstractions;
using OpenIddict.Validation.AspNetCore;
namespace Dpz.Core.Auth.Controllers;
public class HomeController : Controller
{
public async Task<IActionResult> Index(
[FromServices] IHttpCurrentUserService httpCurrentUser,
CancellationToken cancellationToken = default
)
{
VmUserInfo? userInfo = null;
if (User.Identity?.IsAuthenticated == true)
{
userInfo = await httpCurrentUser.GetUserInfoAsync(cancellationToken);
}
return this.ShellView(
new AuthShellViewModel<EmptyAuthShellPayload>
{
EntryName = "public",
PageName = "home",
User = userInfo,
}
);
}
/// <summary>
/// 用户信息
/// </summary>
/// <returns></returns>
[Authorize(AuthenticationSchemes = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme)]
[HttpGet("~/connect/userinfo")]
public IActionResult GetUserInfo()
{
var scopes = User.FindAll("oi_scp").Select(c => c.Value);
var claims = User
.Claims.Where(c => !c.Type.StartsWith("oi_"))
.ToDictionary(c => c.Type, c => c.Value);
claims["scope"] = string.Join(" ", scopes);
var result = claims.ToDictionary(x => x.Key, object (x) => x.Value);
var emailVerifiedValue = User.FindFirst(OpenIddictConstants.Claims.EmailVerified)?.Value;
if (bool.TryParse(emailVerifiedValue, out var emailVerified))
{
result[OpenIddictConstants.Claims.EmailVerified] = emailVerified;
}
var updatedAtValue = User.FindFirst(OpenIddictConstants.Claims.UpdatedAt)?.Value;
if (
long.TryParse(
updatedAtValue,
NumberStyles.Integer,
CultureInfo.InvariantCulture,
out var updatedAt
)
)
{
result[OpenIddictConstants.Claims.UpdatedAt] = updatedAt;
}
return Ok(result);
}
[Route("robots.txt")]
public IActionResult Robots()
{
return Content("User-agent: *\nDisallow: /", "text/plain");
}
#if DEBUG
public IActionResult Forbidden()
{
Response.StatusCode = StatusCodes.Status403Forbidden;
return new EmptyResult();
}
public IActionResult Error()
{
Response.StatusCode = StatusCodes.Status500InternalServerError;
return new EmptyResult();
}
#endif
}
⚠⚠ 以下内容为AI分析的结果,请根据实际情况进行判断。
代码解释
这是一个基于 ASP.NET Core 的 HomeController,整合了 OpenIddict 身份验证框架,主要提供以下功能:
主要功能模块
1. Index 方法 - 首页入口
public async Task<IActionResult> Index(...)
- 功能:应用程序主页入口
- 逻辑流程:
- 检查用户是否已认证(
User.Identity?.IsAuthenticated) - 如果已认证,通过
IHttpCurrentUserService异步获取用户信息 - 返回一个 Shell 视图,包含:
EntryName: "public" - 入口名称PageName: "home" - 页面名称User: 用户信息(已认证)或 null(未认证)
- 检查用户是否已认证(
2. GetUserInfo 方法 - OAuth/OIDC 用户信息端点
[Authorize(...)]
[HttpGet("~/connect/userinfo")]
public IActionResult GetUserInfo()
- 功能:标准的 OpenID Connect UserInfo 端点
- 安全性:需要 OpenIddict 验证令牌(Bearer Token)
- 处理逻辑:
- 提取作用域(Scopes):从 "oi_scp" 声明中获取所有权限范围
- 过滤声明(Claims):
- 移除所有以 "oi_" 开头的内部声明(OpenIddict 内部使用)
- 将剩余声明转换为字典
- 添加 scope 字段:将所有作用域用空格连接
- 特殊字段处理:
email_verified:转换为布尔值updated_at:转换为长整型(Unix 时间戳)
- 返回 JSON:包含用户所有公开信息的字典
3. Robots 方法 - SEO 爬虫控制
[Route("robots.txt")]
public IActionResult Robots()
- 功能:返回 robots.txt 文件
- 内容:禁止所有搜索引擎爬虫访问整个站点
- 用途:隐私保护或避免认证页面被索引
4. 调试端点(仅 DEBUG 模式)
#if DEBUG
public IActionResult Forbidden() // 403 错误测试
public IActionResult Error() // 500 错误测试
#endif
- 用途:开发环境测试错误页面渲染
- 特点:生产环境自动移除(条件编译)
技术要点
| 特性 | 说明 |
|---|---|
| 依赖注入 | IHttpCurrentUserService 通过 [FromServices] 注入 |
| 取消令牌 | 支持异步操作的优雅取消 |
| OpenIddict 集成 | 使用标准 OAuth 2.0 / OIDC 认证方案 |
| Claims 处理 | 智能过滤和类型转换(bool、long) |
| 国际化 | 使用 CultureInfo.InvariantCulture 确保数字解析一致性 |
应用场景
这是一个身份认证服务的核心控制器,典型应用于:
- 单点登录(SSO)系统
- OAuth 2.0 授权服务器
- 企业级身份管理平台
AI 正在分析代码…
评论加载中...