using System; using System.Collections.Generic; using System.Linq; using System.Security.Claims; using System.Threading.Tasks; using Infrastructure; using Microsoft.AspNetCore; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using OpenAuth.App; using OpenIddict.Abstractions; using OpenIddict.Server.AspNetCore; using static OpenIddict.Abstractions.OpenIddictConstants; namespace OpenAuth.IdentityServer.Controllers { /// /// 处理 OpenID Connect 授权请求 /// public class AuthorizationController : Controller { private readonly UserManagerApp _userManager; public AuthorizationController(UserManagerApp userManager) { _userManager = userManager; } /// /// 处理授权端点请求 /connect/authorize /// [HttpGet("~/connect/authorize")] [HttpPost("~/connect/authorize")] public async Task Authorize() { var request = HttpContext.GetOpenIddictServerRequest() ?? throw new InvalidOperationException("无法获取 OpenID Connect 请求。"); // 尝试获取已登录用户 var result = await HttpContext.AuthenticateAsync(CookieAuthenticationDefaults.AuthenticationScheme); if (!result.Succeeded) { // 未登录 → 重定向到登录页面 return Challenge( authenticationSchemes: new[] { CookieAuthenticationDefaults.AuthenticationScheme }, properties: new AuthenticationProperties { RedirectUri = Request.PathBase + Request.Path + QueryString.Create( Request.HasFormContentType ? Request.Form.ToList() : Request.Query.ToList()) }); } // 已登录 → 从 Cookie 中获取用户信息 var userId = result.Principal.FindFirst(ClaimTypes.NameIdentifier)?.Value; if (string.IsNullOrEmpty(userId)) { return Challenge( authenticationSchemes: new[] { CookieAuthenticationDefaults.AuthenticationScheme }, properties: new AuthenticationProperties { RedirectUri = Request.PathBase + Request.Path + QueryString.Create( Request.HasFormContentType ? Request.Form.ToList() : Request.Query.ToList()) }); } // 加载用户信息 var user = GetUser(userId); if (user == null) { return Forbid(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); } // 构建 Claims var claims = new List { new Claim(Claims.Subject, user.Id), new Claim(Claims.Name, user.Name ?? user.Account), new Claim(ClaimTypes.Name, user.Account), }; var identity = new ClaimsIdentity(claims, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); var principal = new ClaimsPrincipal(identity); // 设置请求的 scopes principal.SetScopes(request.GetScopes()); // 设置 access_token 的 audience(对应 WebApi 的 options.Audience) principal.SetResources("openauthapi"); // 设置 Claims 目标(决定哪些 Claims 出现在 access_token / id_token 中) foreach (var claim in principal.Claims) { claim.SetDestinations(GetDestinations(claim, principal)); } // 签发授权码 return SignIn(principal, OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); } /// /// 处理登出端点请求 /connect/logout /// [HttpGet("~/connect/logout")] [HttpPost("~/connect/logout")] public async Task Logout() { // 清除本地 Cookie await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); // 通知 OpenIddict 登出完成 return SignOut(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme); } /// /// 根据用户ID获取用户 /// private OpenAuth.Repository.Domain.SysUser GetUser(string id) { if (id == Define.SYSTEM_USERNAME) { return new OpenAuth.Repository.Domain.SysUser { Account = Define.SYSTEM_USERNAME, Id = Define.SYSTEM_USERNAME, Name = Define.SYSTEM_USERNAME }; } return _userManager.Get(id); } /// /// 确定 Claim 的目标(access_token / id_token) /// private static IEnumerable GetDestinations(Claim claim, ClaimsPrincipal principal) { switch (claim.Type) { case Claims.Name: yield return Destinations.AccessToken; if (principal.HasScope(Scopes.Profile)) yield return Destinations.IdentityToken; yield break; case ClaimTypes.Name: yield return Destinations.AccessToken; if (principal.HasScope(Scopes.Profile)) yield return Destinations.IdentityToken; yield break; case Claims.Subject: yield return Destinations.AccessToken; yield return Destinations.IdentityToken; yield break; default: yield return Destinations.AccessToken; yield break; } } } }