ASP.NET Identity OWIN中间件Google OAuth2 AuthenticationManager登

本文关键字:OAuth2 AuthenticationManager Google 中间件 NET Identity OWIN ASP | 更新日期: 2023-09-27 18:20:04

我创建了一个简单的ASP.NET MVC4网站来测试新的OWIN身份验证中间件,我决定从Google OAuth2开始,我在配置方面遇到了很多困难,但我已经设法让Google授权用户,我现在的问题是OWIN没有对用户进行身份验证。

我想我在网络配置中有正确的设置

<system.web>
     <authentication mode="None" />
</system.web>
<system.webServer>
     <modules>
        <remove name="FormsAuthenticationModule" />
     </modules>
</system.webServer>

然后我在启动类中有一个非常简单的配置

public partial class Startup
{
    public void Configuration(IAppBuilder app)
    {
        ConfigureAuth(app);
    }
    public void ConfigureAuth(IAppBuilder app)
    {
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
        // Enable the External Sign In Cookie.
        app.SetDefaultSignInAsAuthenticationType(DefaultAuthenticationTypes.ExternalCookie);
        // Enable Google authentication.
        app.UseGoogleAuthentication(GetGoogleOptions());
    }
    private static GoogleOAuth2AuthenticationOptions GetGoogleOptions()
    {
        var reader = new KeyReader();
        var keys = reader.GetKey("google");
        var options = new GoogleOAuth2AuthenticationOptions()
        {
            ClientId = keys.Public,
            ClientSecret = keys.Private
        };
        return options;
    }
}

AccountController中,我以以下方式对操作进行了编码,这同样非常简单,但它应该可以工作。

[AllowAnonymous, HttpPost, ValidateAntiForgeryToken]
    public ActionResult ExternalLogin(string provider, string returnUrl)
    {
        return new ChallengeResult(provider, Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }));
    }
    [AllowAnonymous, HttpGet]
    public async Task<ActionResult> ExternalLoginCallback(string returnUrl)
    {
        var loginInfo = await AuthenticationManager.GetExternalLoginInfoAsync();
        if (loginInfo == null || !loginInfo.ExternalIdentity.IsAuthenticated)
        {
            return RedirectToAction("Login");
        }
        var identity = new ClaimsIdentity(new[] {
            new Claim(ClaimTypes.Name, loginInfo.DefaultUserName),
            new Claim(ClaimTypes.Email, loginInfo.Email)
        }, DefaultAuthenticationTypes.ExternalCookie);
        AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
        AuthenticationManager.SignIn(new AuthenticationProperties
                {
                    IsPersistent = false
                }, identity);
        return RedirectToLocal(returnUrl);
    }

我遇到的主要问题是,当用户被重定向到主页时,对方法AuthenticationManager.SignIn的调用似乎没有做任何事情,即使谷歌正在授予对该请求的访问权限,我在主页中有以下代码

@using Microsoft.AspNet.Identity
@{
    Layout = "~/Views/Shared/_Main.cshtml";
}
<h2>Welcome</h2>
@{
    if (Request.IsAuthenticated)
    {
        <p>Welcome @User.Identity.GetUserName()</p>
    }
    else
    {
        @Html.ActionLink("Login", "Login", "Account") 
    }
}

Request.IsAuthenticated的值总是假的,有人知道我在这里缺少什么吗?从我在网上看到的情况来看,这应该是可行的。

我在浏览器和其他谷歌OAuth示例中启用了cookie,这些示例依赖于UserManager类,但我的这个简单实现无法运行

ASP.NET Identity OWIN中间件Google OAuth2 AuthenticationManager登

在网上阅读了无数个小时的答案后,我决定调试OWIN源代码以找到这个问题的解决方案,而调试会话中我在AuthenticationHandler类中遇到了这个问题

if (BaseOptions.AuthenticationMode == AuthenticationMode.Active)
        {
            AuthenticationTicket ticket = await AuthenticateAsync();
            if (ticket != null && ticket.Identity != null)
            {
                Helper.AddUserIdentity(ticket.Identity);
            }
        }

在我最初的Startup类中,我使用这个方法启用了外部登录cookie

app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

该方法使用了一个默认的CookieAuthenticationOptions实例,该实例具有AuthenticationMode = AuthenticationMode.Passive,这阻止了类读取cookie中存储的信息,这样,在每次新请求时,OwinContext都不会加载经过身份验证的身份,并导致Request.IsAuthenticated

在我意识到这一点后,我所做的就是用这个更改app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

app.UseCookieAuthentication(new CookieAuthenticationOptions()
            {
                AuthenticationMode = AuthenticationMode.Passive,
                AuthenticationType = DefaultAuthenticationTypes.ExternalCookie,
                ExpireTimeSpan = TimeSpan.FromMinutes(30)
            });

一切都很顺利

我也遇到了同样的问题,但我所需要做的就是在谷歌开发者控制台中将"Google+neneneba API"添加到我的APIS列表中。在那之后,一切都成功了。