ASP.Net:混合身份验证 Azure AD/表单

2024-04-14

我有一个使用表单身份验证的旧版 Asp.Net/MVC/Razor WebApp。

现在,由于某些用户拥有 Azure AD 帐户,因此我添加了一个特殊的 AD 登录按钮以及常用代码以使其正常工作

app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
                {...})

使用按钮登录后,我在 URL 中输入以下内容:

https://localhost:44361/Account/Index?ReturnUrl=%2fAccount%2fSignIn

因此在我的 Web.config 中我注释掉了:

<!--<authentication mode="Forms">
  <forms loginUrl="~/Account/Index" timeout="2880" cookieless="UseDeviceProfile" />
</authentication>-->

在这个阶段Azure AD 身份验证工作正常!但这样做却破坏了原来的Forms验证 :-(

只是打电话

 FormsAuthentication.SetAuthCookie(email, false);

还不够:当我使用以下命令调用控制器时,我仍然会重定向到 Azure AD 登录页面

[System.Web.Mvc.Authorize]

另外,我收到错误消息是因为

 @Html.AntiForgeryToken()

类型的声明 'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier' 或者 'http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider' 未出现在提供的 ClaimsIdentity 中。启用防伪 令牌支持基于声明的身份验证,请验证 配置的声明提供者正在提供这两个声明 它生成的 ClaimsIdentity 实例。如果配置的声明 提供商改为使用不同的声明类型作为唯一标识符, 可以通过设置静态属性来配置 AntiForgeryConfig.UniqueClaimTypeIdentifier。

有人可以告诉我如何结合这两种身份验证方法吗? 谢谢你!


以下是启动的答案:

    public void ConfigureAuth(IAppBuilder app)
    {
        PublicClientId = "self";

        app.UseCookieAuthentication(new CookieAuthenticationOptions
                                    {
                                            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                                            LoginPath = new PathString("/Account/Index/"),
                                            CookieSecure = CookieSecureOption.Always
                                    });

        app.UseOAuthBearerTokens(new OAuthAuthorizationServerOptions
                                 {
                                         TokenEndpointPath = new PathString("/Token"),
                                         Provider = new ApplicationOAuthProvider(new StatelessRepository(new DataAccessHelper()), PublicClientId),
                                         RefreshTokenProvider = new AuthenticationTokenProvider
                                                                {
                                                                        OnCreate = CreateRefreshToken,
                                                                        OnReceive = RecieveRefreshToken
                                                                },
                                         AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
                                         AccessTokenExpireTimeSpan = TimeSpan.FromHours(1),
                                         AllowInsecureHttp = true
                                 });

        app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

        app.UseCookieAuthentication(new CookieAuthenticationOptions());
        app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
                {
                        ClientId = clientId,
                        Authority = authority,
                        RedirectUri = redirectUri,
                        PostLogoutRedirectUri = redirectUri,
                        Scope = OpenIdConnectScope.OpenIdProfile,
                        ResponseType = OpenIdConnectResponseType.CodeIdToken,
                        TokenValidationParameters = new TokenValidationParameters
                                                    {
                                                            ValidateIssuer = true,
                                                            ValidIssuer = $"https://login.microsoftonline.com/{tenant}/v2.0",
                                                            RoleClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role",
                                                            NameClaimType = "name",
                                                    },
                        Notifications = new OpenIdConnectAuthenticationNotifications
                                        {
                                                AuthenticationFailed = OnAuthenticationFailed,
                                                SecurityTokenValidated = OnAuthenticationSuccessded
                                        }
                }
        );
    }

在 Web.config 中

<system.web>
<authentication mode="None" />
<compilation debug="true" targetFramework="4.8" />
<httpRuntime targetFramework="4.8" />
</system.web>
      <system.webServer>
        <modules>
          <remove name="FormsAuthentication" />
        </modules>
      </system.webServer>

最后在控制器中验证用户凭据后:

List<Claim> claims = new List<Claim>
                             {
                                     new Claim(ClaimTypes.Name, partnerUser.Email),
                                     new Claim(ClaimTypes.Email, partnerUser.Email),
                                     new Claim(ClaimTypes.NameIdentifier, partnerUser.Email)
                             };
        ClaimsIdentity claimsIdentity = new ClaimsIdentity(claims,
                DefaultAuthenticationTypes.ApplicationCookie);

        Request.GetOwinContext().Authentication.SignIn(claimsIdentity);

再加上一个 SignOut 方法:

    public void SignOut()
    {
        IAuthenticationManager authenticationManager = HttpContext.GetOwinContext().Authentication;

        foreach (ClaimsIdentity claimsIdentity in authenticationManager.User.Identities)
        {
            switch (claimsIdentity.AuthenticationType)
            {
                case DefaultAuthenticationTypes.ApplicationCookie:
                    authenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
                    break;

                case CookieAuthenticationDefaults.AuthenticationType:
                    authenticationManager.SignOut(
                            OpenIdConnectAuthenticationDefaults.AuthenticationType,
                            CookieAuthenticationDefaults.AuthenticationType);
                    break;
            }
        }

        Session.Abandon();
        Session.RemoveAll();
    }

最后,这是 Global.asax 的一些内容:

    protected void Application_Start()
    {
        AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
        ...           
    }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ASP.Net:混合身份验证 Azure AD/表单 的相关文章

随机推荐

  • 如何装饰可调用类的实例?

    def decorator fn def wrapper args kwargs print With sour cream and chives return fn args kwargs return wrapper class Pot
  • 为什么 Nokogiri 没有安装?

    我在安装 Nokogiri 时遇到问题 当我跑步时bundle install or gem install nokogiri安装失败 我收到的错误是 注 此失败是由于使用nokogiri org上的安装命令造成的 Building nat
  • 如何结束谈话?

    我已经使用 Bot Framework 创建了一个机器人 并且正在使用conversationID用我的后端对话引擎维护状态 我在文档中找不到用于结束对话的信息 至关重要的是 在某些时候 用户能够发出对话 结束或退出 的信号 以便下次他们开
  • 如何跨域使用 SignalR

    我正在尝试将 SignalR 与跨域一起使用 但在调用启动函数时收到错误消息 错误信息是 Uncaught TypeError Cannot call method start of undefined 我正在使用代码 服务器端 assem
  • 已编译的Azure功能监控:“没有可用数据”

    我在 Azure 上使用几个编译的 C 函数 它们按预期工作 但是当我单击任一功能上的 监视 时 它只显示 无可用数据 我可以在 开发 选项卡的日志上看到该函数正在运行 但希望了解该函数的用法的概述 我有什么遗漏的吗 我也看到这些了我将一个
  • jQuery 上一个按钮在单击时返回到 Q。) 1 而不是一一向后退

    jQuery 上一个按钮无法按预期工作 基本上最好的解释方法是 如果我在回答问题 5 时单击上一个按钮 则它默认为问题 1 而不是问题 4 所以它默认为问题1 这是一个问题 该怎么办 jQuery 位于脚本标签的底部 if i Questi
  • 如何为 docker 容器的日志着色

    我有一个容器 有时在日志中写入对我来说很重要的关键字 我想在终端中以颜色突出显示该单词 但同样重要的是仍然实时查看所有内容日志 follow 我刚刚尝试过命令 docker logs f my app tail 100 grep color
  • 大于100,000的随机数

    我正在用 C C 编写 我想创建很多大于 100 000 的随机数 我该怎么做呢 和rand 你不会那样做rand 但使用较新的 C 附带的适当随机数生成器 请参见例如cppreference com http en cppreferenc
  • Eclipse android ADT安装问题

    我按照每个步骤使用 Eclipse IDE 安装 android ADT 插件 我在 Windows 7 计算机上安装了 Eclipse for Java 我遵循每一步 尽管做了所有的事情 我还是收到以下错误 没有人犯过这个错误 我很着急请
  • Cython:类似 CPP 字典的地图性能

    我一直在比较使用模仿 python 字典的 c 映射与在 cython 中使用普通 python 字典的性能 我在 sklearn 中编写了 fast dict 实现的 简化 变体 https github com scikit learn
  • 如何在linux中的hdfs超级组中添加用户? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我正在研究 hdfs 然后我发现某些内容没有为超级用户执行权限检查 如果我的 linux 用户是 sandy 并且我想将 sandy 添加
  • 如何让tinymce(浏览器内的“富编辑器”)保留缩进

    问题 我将 Drupal 与丰富的编辑器一起使用 而丰富的编辑器喜欢通过删除缩进和格式来破坏我的文本 这在桌面编辑器中是不可接受的 但人们似乎可以在浏览器内编辑器中容忍这种情况 问 如何关闭此功能 我已经四处搜索 但尚未找到告诉富编辑器保留
  • 如何将 Javascript 数组传递给 Spring 控制器类

    我创建了 JS 数组并尝试将数组传递给 Controller 类 但它显示了NullPointerException 我通过 FireBug 检查了 URL 其中值正在传递 但在控制器类中 如果我尝试检索它 则显示 NULL JavaScr
  • List 或 IList [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 谁能向我解释为什么我想在 C 中使用 IList 而不是 List 相关问题 为什么暴露被认为是不好的List
  • Ruby 最大整数

    我需要能够确定 Ruby 中的系统最大整数 有人知道怎么做吗 或者是否可能 FIXNUM MAX 2 0 size 8 2 1 FIXNUM MIN 2 0 size 8 2
  • 自动更新 .net 应用程序

    到目前为止 我已经在 net 中编写了 2 个相当大型的应用程序 它们都需要一个更新工具 以便在我推出新代码时自动更新应用程序 我发现 企业应用程序块更新程序 对于我的需求来说有点过于复杂 并且在发布时我发现 单击一次 令人沮丧 我发现的最
  • 错误:unpack_from 需要缓冲区

    我正在使用 struct 来格式化固定分隔的 txt 文件 这是前两行 Sat Jan 3 18 15 05 2009 62e907b15cbf27d5425399ebf6f0fb50ebb88f18 4a5e1e4baab89f3a325
  • 如何将图像路径和名称上传到数据库 - Codeigniter

    我知道这个问题已经被问过好几次了 但是我发现的所有其他问题都与我想要的不同 我想将文件名和文件路径上传到名为 工厂图像 的表 这样做的最佳方法是什么 我的控制器功能 function do upload config upload path
  • 这是 IOC 的典型用例吗?

    我当前的应用程序允许用户通过一组管理屏幕定义自定义 Web 表单 它本质上是一个 EAV 类型的应用程序 因此 我无法对 HTML 或 ASP NET 标记进行硬编码来呈现给定页面 相反 UI 从服务层请求 Form 对象的实例 服务层又使
  • ASP.Net:混合身份验证 Azure AD/表单

    我有一个使用表单身份验证的旧版 Asp Net MVC Razor WebApp 现在 由于某些用户拥有 Azure AD 帐户 因此我添加了一个特殊的 AD 登录按钮以及常用代码以使其正常工作 app UseOpenIdConnectAu