首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ASP.NET Core 6 Azure B2C Active身份验证问题

ASP.NET Core 6 Azure B2C Active身份验证问题
EN

Stack Overflow用户
提问于 2017-03-10 10:02:52
回答 1查看 686关注 0票数 0

我跟随了这篇文章:https://github.com/Azure-Samples/active-directory-dotnet-webapp-openidconnect-aspnetcore-b2c

在这个示例应用程序中有一个登录按钮。通过提供Azure B2C租户并在租户中注册应用程序,我可以通过单击“登录”按钮成功地登录。

在另一个应用程序中,我想在没有点击登录按钮的情况下进行身份验证--即当我打开URL时,我首先被重定向到Azure B2C广告登录页面,并且在成功验证凭据之后,我应该能够看到主屏幕。

因此,我从文章中提到的URL中复制了SiginIn()方法,如下所示:

代码语言:javascript
复制
public async Task<IActionResult> Index()
{
    await SignIn();

    await GetDataAsync();
}

在运行应用程序时收到一条错误消息:InvalidOperationException:没有配置身份验证处理程序来处理方案: b2c_1_org_b2c_global_signin

请告诉我如何在没有登录按钮的情况下直接验证。在前面的MVC5中,我已经成功地完成了这一工作,在控制器类上使用了授权属性。

基于索引法的控制器代码

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using System.IO;
using System.Net;
using System.Text;
using Newtonsoft.Json;
using Microsoft.AspNetCore.Hosting;
using WebViewerCore.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.AspNetCore.Http.Authentication;
using Microsoft.AspNetCore.Authorization;

namespace WebViewerCore.Controllers
{
    [Authorize]
    public class DocumentController : Controller
    {
        #region GlobalVariables
        private static readonly string serviceUrl = "";
        private string doctype = string.Empty;
        private string dmsno = string.Empty;
        public string documentName = string.Empty;
        private string errMsg = string.Empty;
        StringBuilder msg;
        Document doc;
        private IHostingEnvironment _env;
        private IConfiguration _config;
        #endregion

        #region C'tor
        public DocumentController(IHostingEnvironment env, IConfiguration config)
        {
            _env = env;
            _config = config;
        }
        #endregion

        #region ControllerAction
        public async Task<IActionResult> Index()
        {
            //return View();
            try
            {
                //await SignIn();

                string storageAccount = _config.GetSection("BlobStorage").GetSection("StorageAccount").Value;
                string storageContainer = _config.GetSection("BlobStorage").GetSection("StorageContainer").Value;

                ViewBag.StorageAccount = storageAccount;
                ViewBag.StorageContainer = storageContainer;

                await GetDataAsync();

                //HttpContext.Response.ContentType = "application/vnd.ms-xpsdocument";

                if (TempData["QueryStringMissing"] != null && (bool)TempData["QueryStringMissing"] || doc == null)
                {
                    return View("View");
                }
                else
                {
                    return View("Index", doc);
                }
            }
            catch (Exception ex)
            {
                //logger.LogErrorWithMessage(ex, ex.StackTrace);
                //return View("Error", new HandleErrorInfo(ex, "Document", "Index"));
                throw ex;
            }
        }
        #endregion

Startup.cs代码

代码语言:javascript
复制
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.StaticFiles;
using Microsoft.Extensions.FileProviders;
using Microsoft.AspNetCore.Http;
using System.IO;
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authentication.Cookies;

namespace WebViewerCore
{
    public class Startup
    {
        #region Global Variables
        public static string SignUpPolicyId;
        public static string SignInPolicyId;
        public static string ProfilePolicyId;
        public static string ClientId;
        public static string RedirectUri;
        public static string AadInstance;
        public static string Tenant;
        #endregion
        public Startup(IHostingEnvironment env)
        {
            //var builder = new ConfigurationBuilder()
            //    .SetBasePath(env.ContentRootPath)
            //    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            //    .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            //    .AddEnvironmentVariables();
            //Configuration = builder.Build();

            Configuration = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                .AddEnvironmentVariables()
                .Build();
        }

        public IConfigurationRoot Configuration { get; set; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            // Add framework services.
            services.AddMvc();

            // Adds a default in-memory implementation of IDistributedCache.
            services.AddDistributedMemoryCache();

            services.AddSession(options =>
            {
                // Set a short timeout for easy testing.
                options.IdleTimeout = TimeSpan.FromSeconds(10);
                options.CookieHttpOnly = true;
            });

            services.AddSingleton<IConfiguration>(Configuration);

            // Add Authentication services.
            services.AddAuthentication(sharedOptions => sharedOptions.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseBrowserLink();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
            }

            app.UseStaticFiles();

            app.UseSession();

            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Document}/{action=Index}/{id?}");
            });

            // App config settings
            ClientId = Configuration["AzureAD:ClientId"];
            AadInstance = Configuration["AzureAD:AadInstance"];
            Tenant = Configuration["AzureAD:Tenant"];
            RedirectUri = Configuration["AzureAD:RedirectUri"];

            // B2C policy identifiers
            SignUpPolicyId = Configuration["AzureAD:SignUpPolicyId"];
            SignInPolicyId = Configuration["AzureAD:SignInPolicyId"];

            // Configure the OWIN pipeline to use OpenID Connect auth.
            //app.UseOpenIdConnectAuthentication(CreateOptionsFromPolicy(SignUpPolicyId));
            app.UseOpenIdConnectAuthentication(CreateOptionsFromPolicy(SignInPolicyId));
        }

        private OpenIdConnectOptions CreateOptionsFromPolicy(string policy)
        {
            policy = policy.ToLower();
            return new OpenIdConnectOptions
            {
                // For each policy, give OWIN the policy-specific metadata address, and
                // set the authentication type to the id of the policy
                MetadataAddress = string.Format(AadInstance, Tenant, policy),
                AuthenticationScheme = policy,
                CallbackPath = new PathString(string.Format("/{0}", policy)),

                // These are standard OpenID Connect parameters, with values pulled from config.json
                ClientId = ClientId,
                PostLogoutRedirectUri = RedirectUri,
                Events = new OpenIdConnectEvents
                {
                    OnRemoteFailure = RemoteFailure,
                },
                ResponseType = OpenIdConnectResponseType.IdToken,

                // This piece is optional - it is used for displaying the user's name in the navigation bar.
                TokenValidationParameters = new TokenValidationParameters
                {
                    NameClaimType = "name",
                }
            };
        }

        // Used for avoiding yellow-screen-of-death
        private Task RemoteFailure(FailureContext context)
        {
            context.HandleResponse();
            if (context.Failure is OpenIdConnectProtocolException && context.Failure.Message.Contains("access_denied"))
            {
                context.Response.Redirect("/");
            }
            else
            {
                context.Response.Redirect("/Home/Error?message=" + context.Failure.Message);
            }

            return Task.FromResult(0);
        }
    }
}
EN

回答 1

Stack Overflow用户

发布于 2017-03-11 18:39:22

要自动将导航到MVC中特定控制器或端点的用户重定向到MVC中,您所需要做的就是添加授权属性,前提是您已经正确配置了中间件。

对于Azure AD B2C,需要确保添加OpenID中间件,如下所示:

代码语言:javascript
复制
    app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
        {
            // For each policy, give OWIN the policy-specific metadata address, and
            // set the authentication type to the id of the policy
            MetadataAddress = string.Format(AadInstance, Tenant, policy),
            AuthenticationScheme = policy,
            CallbackPath = new PathString(string.Format("/{0}", policy)),

            // These are standard OpenID Connect parameters, with values pulled from config.json
            ClientId = ClientId,
            PostLogoutRedirectUri = RedirectUri,
            Events = new OpenIdConnectEvents
            {
                OnRemoteFailure = RemoteFailure,
            },
            ResponseType = OpenIdConnectResponseType.IdToken,

            // This piece is optional - it is used for displaying the user's name in the navigation bar.
            TokenValidationParameters = new TokenValidationParameters
            {
                NameClaimType = "name",
            },
        };);

您所引用的示例在某种程度上已经实现了您想要的效果。在该示例中,如果您尚未登录并导航到/about,则会自动重定向到Azure B2C以进行登录。

目前,示例仅在Home控制器中的控制器操作上有授权属性,您需要将其移到控制器级别,并将其添加到每个控制器中。然后,只需移除登录/登录/注销按钮和控制器操作即可。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42715536

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档