【问题标题】:ASP.NET MVC 5 - ADAL to MSAL 2.0 migrationASP.NET MVC 5 - ADAL 到 MSAL 2.0 的迁移
【发布时间】:2022-01-21 18:44:09
【问题描述】:

我已尝试按照链接上的此示例对我们在 .NET 4.8 平台上运行的应用实施 MSAL 身份验证(授权代码流):

https://github.com/Azure-Samples/ms-identity-aspnet-webapp-openidconnect/blob/master/WebApp

我在我们应用的以下文件中实现了 MSAL 代码

Startup.cs

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using CompanyApp.Infrastructure;
using CompanyApp.App_Start;
using Owin;
using Microsoft.Owin;
using System.Web.Http;
using System.Net.Http.Formatting;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OpenIdConnect;
using Microsoft.Owin.Security.Notifications;
using System.Threading.Tasks;
using Microsoft.Identity.Client;
using System.Web;
using Microsoft.Identity.Web;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Owin.Host.SystemWeb;
using CompanyApp.Utils;

namespace CompanyApp
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {


            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

            app.UseCookieAuthentication(new CookieAuthenticationOptions());
            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
                {
                    ClientId = AuthenticationConfig.ClientId,
                    Authority = AuthenticationConfig.Authority,
                    RedirectUri = AuthenticationConfig.RedirectUri,
                    PostLogoutRedirectUri = AuthenticationConfig.RedirectUri,
                    Scope = AuthenticationConfig.BasicSignInScopes + $" User.Read",
                    TokenValidationParameters = new TokenValidationParameters()
                    {
                        ValidateIssuer = false
                    },

                    Notifications = new OpenIdConnectAuthenticationNotifications
                    {
                        AuthorizationCodeReceived = OnAuthorizationCodeReceived,
                        AuthenticationFailed = OnAuthenticationFailed
                    }
                }
            );



            RegisterConstants(app);
            RegisterAppFilters(AppFilters.Filters);


            HttpConfiguration config = new HttpConfiguration() {
            };


            config.Formatters.Clear();
            config.Formatters.Add(new JsonMediaTypeFormatter());
            // config.EnsureInitialized();

            app.UseWebApi(config);

            AreaRegistration.RegisterAllAreas();
            RouteConfig.RegisterRoutes(RouteTable.Routes);

        }


        private async Task OnAuthorizationCodeReceived(AuthorizationCodeReceivedNotification context)
        {
            // Upon successful sign in, get the access token & cache it using MSAL
            IConfidentialClientApplication clientApp = MsalAppBuilder.BuildConfidentialClientApplication();
            AuthenticationResult result = await clientApp.AcquireTokenByAuthorizationCode(new[] { "api://<Application ID in azure>/.default" }, context.Code).ExecuteAsync();
        }

        private Task OnAuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> notification)
        {
            notification.HandleResponse();
            notification.Response.Redirect("/Error?message=" + notification.Exception.Message);
            return Task.FromResult(0);
        }
    }
}

HomeController.cs

using Microsoft.Identity.Client;
using Microsoft.Identity.Web;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.OpenIdConnect;
using System;
using System.Diagnostics;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using CompanyApp.Utils;

namespace CompanyApp.Controllers
{
    public class HomeController : Controller
    {
        [Authorize]
        public ActionResult Index()
        {
            IConfidentialClientApplication app = MsalAppBuilder.BuildConfidentialClientApplication();
            var msalAccountId = ClaimsPrincipal.Current.GetMsalAccountId(); // getting null from this line
            var account = await app.GetAccountAsync(msalAccountId);
            string[] scopes = { "api://<Application ID in azure>/.default" };

            try
            {
                // try to get an already cached token
                await app.AcquireTokenSilent(scopes, account).ExecuteAsync().ConfigureAwait(false);
            }
            catch (MsalUiRequiredException ex)
            {
                throw ex;
            }
        
            return View();
        }

    }
}

我尝试在本地运行它

成功认证后进入控制器

我从调用ClaimsPrincipal.Current.GetMsalAccountId() 的行得到空结果

ClaimsPrincipal.Current.GetMsalAccountId() 给出 null 是否缺少什么?

【问题讨论】:

    标签: asp.net-mvc-5 azure-active-directory msal .net-framework-4.8


    【解决方案1】:

    在 ASP.NET 4.x 项目中,通常使用ClaimsPrincipal.Current 来检索当前经过身份验证的用户的身份和声明。在 ASP.NET Core 中,不再设置此属性。依赖于它的代码需要更新以通过不同的方式获取当前经过身份验证的用户的身份。

    有几个选项可以在 ASP.NET Core 中检索当前经过身份验证的用户的 ClaimsPrincipal 来代替 ClaimsPrincipal.Current

    1)ControllerBase.User. MVC 控制器可以使用其User 属性访问当前经过身份验证的用户。

    2)HttpContext.User. 可以访问当前HttpContext的组件(例如中间件)可以从HttpContext.User获取当前用户的ClaimsPrincipal

    3)从调用者传入。无法访问当前 HttpContext 的库通常从控制器或中间件组件调用,并且可以将当前用户的身份作为参数传递。

    4)HttpContextAccessor。迁移到 ASP.NET Core 的项目可能太大,无法轻松地将当前用户的身份传递到所有必要的位置。在这种情况下,IHttpContextAccessor 可以用作解决方法。 IHttpContextAccessor 能够访问当前的HttpContext(如果存在)。如果正在使用 DI,请参阅 ASP.NET Core 中的访问HttpContext。在尚未更新以使用 ASP.NET Core 的 DI 驱动架构的代码中获取当前用户身份的短期解决方案是:

    更多详情请参考document

    【讨论】:

      猜你喜欢
      • 2021-07-16
      • 2021-01-23
      • 2015-01-04
      • 2014-06-06
      • 1970-01-01
      • 1970-01-01
      • 2021-08-21
      • 2019-11-12
      • 2015-02-16
      相关资源
      最近更新 更多