Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc 使用mvc从google api获取访问令牌的困惑_Asp.net Mvc_Google Api_Google Oauth - Fatal编程技术网

Asp.net mvc 使用mvc从google api获取访问令牌的困惑

Asp.net mvc 使用mvc从google api获取访问令牌的困惑,asp.net-mvc,google-api,google-oauth,Asp.net Mvc,Google Api,Google Oauth,我一直在尝试遵循一些我可以找到的教程,让mvc应用程序允许用户对应用程序进行身份验证,并获得访问和刷新令牌。不幸的是,我找不到任何足够清楚的地方,我可以跟踪正在发生的事情。我从谷歌开始,然后发现了其他一些像和 当我运行我的应用程序时,我试图去点击该方法,该方法最终点击AppFlowMetadata.GetUserId方法,然后点击我的自定义TenixDataStore类的GetAsync方法 令人困惑的是 首先,我要使用正确的url/方法吗?我想我是基于谷歌的代码示例,但不确定 我以为我得到的密

我一直在尝试遵循一些我可以找到的教程,让mvc应用程序允许用户对应用程序进行身份验证,并获得访问和刷新令牌。不幸的是,我找不到任何足够清楚的地方,我可以跟踪正在发生的事情。我从谷歌开始,然后发现了其他一些像和

当我运行我的应用程序时,我试图去点击该方法,该方法最终点击AppFlowMetadata.GetUserId方法,然后点击我的自定义TenixDataStore类的GetAsync方法

令人困惑的是

  • 首先,我要使用正确的url/方法吗?我想我是基于谷歌的代码示例,但不确定
  • 我以为我得到的密钥是电子邮件地址,而不是GUID。这就是谷歌识别用户的方式吗
  • 如果我要找到正确的url,为什么页面会挂起,永远不会返回。我以为它会打开一个谷歌授权页面,但这并没有发生
  • 这是我的密码

    AppFlowMetadata类

    using System.Web.Mvc;
    using Google.Apis.Auth.OAuth2;
    using Google.Apis.Auth.OAuth2.Flows;
    using Google.Apis.Auth.OAuth2.Mvc;
    using Google.Apis.Gmail.v1;
    using Tenix.Domain.Constants;
    
    namespace MyApp.Areas.Integration.Controllers
    {
        public class AppFlowMetadata : FlowMetadata
        {
            private static readonly IAuthorizationCodeFlow flow =
                new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
                {
                    ClientSecrets = new ClientSecrets
                    {
                        ClientId = APIConstants.GMailApiKey,
                        ClientSecret = APIConstants.GmailApiSecret
                    },
                    Scopes = new[] {GmailService.Scope.GmailReadonly},
                    DataStore = new TenixDataStore()
                });
    
            public override IAuthorizationCodeFlow Flow
            {
                get { return flow; }
            }
    
            public override string GetUserId(Controller controller)
            {
                // In this sample we use the session to store the user identifiers.
                // That's not the best practice, because you should have a logic to identify
                // a user. You might want to use "OpenID Connect".
                // You can read more about the protocol in the following link:
                // https://developers.google.com/accounts/docs/OAuth2Login.
                var user = controller.Session["UserID"];
                if (user == null) return null;
                return user.ToString();
            }
        }
    }
    
    谷歌控制器

    using System.Threading;
    using System.Threading.Tasks;
    using System.Web.Mvc;
    using Google.Apis.Auth.OAuth2.Mvc;
    using Google.Apis.Gmail.v1;
    using Google.Apis.Services;
    
    namespace MyApp.Areas.Integration.Controllers
    {
        public class GoogleController : Controller
        {
            public async Task IndexAsync(CancellationToken cancellationToken)
            {
                if (Session["UserID"] == null)
                {
                    Response.Redirect("~/Login.aspx", true);
                }
    
                var result = await new AuthorizationCodeMvcApp(this, new AppFlowMetadata()).AuthorizeAsync(cancellationToken);
    
                if (result.Credential != null)
                {
                    var service = new GmailService(new BaseClientService.Initializer
                    {
                        HttpClientInitializer = result.Credential,
                        ApplicationName = "Tenix Gmail Integration"
                    });
                }
            }
        }
    }
    
    using Google.Apis.Auth.OAuth2.Mvc;
    
    namespace MyApp.Areas.Integration.Controllers
    {
        public class AuthCallbackController : Google.Apis.Auth.OAuth2.Mvc.Controllers.AuthCallbackController
        {
            protected override FlowMetadata FlowData
            {
                get { return new AppFlowMetadata(); }
            }
        }
    }
    
    TenixDataStore类

    using System;
    using System.Threading.Tasks;
    using DataBaseUtilitiesTEN;
    using Google.Apis.Json;
    using Google.Apis.Util.Store;
    using Newtonsoft.Json.Linq;
    using Synergy.Extensions;
    using Tenix.Domain.Data.Respositories;
    using Tenix.Domain.Model.Integration;
    using Tenix.Domain.Services;
    
    namespace MyApp.Areas.Integration.Controllers
    {
        public class TenixDataStore : IDataStore
        {
            private readonly string conStr = ConnectionStrings.GeneralInfo;
            private CredentialService _service;
    
            public TenixDataStore()
            {
                _service = new CredentialService(new CredentialRepository(conStr));
            }
    
            public Task StoreAsync<T>(string key, T value)
            {
                if (string.IsNullOrEmpty(key))
                    throw new ArgumentException("Key MUST have a value");
    
                var serialized = NewtonsoftJsonSerializer.Instance.Serialize(value);
                var jObject = JObject.Parse(serialized);
    
                var access_token = jObject.SelectToken("access_token");
                var refresh_token = jObject.SelectToken("refresh_token");
    
                if (access_token == null) 
                    throw new ArgumentException("Missing access token");
    
                if (refresh_token == null)
                    throw new ArgumentException("Missing refresh token");
    
                _service.SaveUserCredentials(new UserCredential
                {
                    EmailAddress = key,
                    AccessToken = (string)access_token,
                    RefreshToken = (string)refresh_token
                });
    
                return Task.Delay(0);
            }
    
            public Task DeleteAsync<T>(string key)
            {
                _service.DeleteCredentials(key);
                return Task.Delay(0);
            }
    
            public Task<T> GetAsync<T>(string userId)
            {
                var credentials = _service.GetUserCredentials(userId.To<int>());
                var completionSource = new TaskCompletionSource<T>();
    
                if (!string.IsNullOrEmpty(credentials.AccessToken))
                    completionSource.SetResult(NewtonsoftJsonSerializer.Instance.Deserialize<T>(credentials.AccessToken));
    
                return completionSource.Task;
            }
    
            public Task ClearAsync()
            {
                return Task.Delay(0);
            }
        }
    }
    

    在花了几天时间试图弄明白这一点,但在使用GoogleAPI.net库方面没有取得任何进展之后,我最终只使用了自己的实现,这至少是我能够完全理解的。如果任何人都能使用代码,下面是我的结论。仍然需要进行一些重构,但目前它正在工作

    只需要确保AuthorizeResponse和authorizeRoutes注册为authorized redirect URI

    public class GoogleController : Controller
    {
        private readonly CredentialService _credentialService;
        private readonly GoogleEndpoints _endpoints;
    
        public GoogleController()
        {
            _endpoints = new GoogleEndpoints();
            _credentialService = new CredentialService(new CredentialRepository(ConnectionStrings.GeneralInfo));
        }
    
        private string AuthorizeUrl
        {
            get
            {
                return "/Integration/Google/Authorize";
            }
        }
    
        private string AuthorizeResponseUrl
        {
            get
            {
                return "/Integration/Google/AuthorizeResponse";
            }
        }
    
        private string SaveResponseUrl
        {
            get
            {
                return "/Integration/Google/SaveResponse";
            }
        }
    
        public void Authorize()
        {
            if (Session["UserID"] == null || Session["Email"] == null)
            {
                Response.Redirect("~/Login.aspx", true);
                Session["LoginSource"] = AuthorizeUrl;
                Response.End();
            }
            else
            {
                if (Session["SessionId"] == null || Session["SessionId"].ToString().Trim().Length == 0)
                    Session["SessionId"] = _credentialService.CreateSessionId(Session["UserID"].To<int>());
    
                var url = _endpoints.AuthorizationEndpoint + "?" +
                          "client_id=" + APIConstants.GMailApiKey + "&" +
                          "response_type=code&" +
                          "scope=openid%20email&" +
                          "redirect_uri=" + AuthorizeResponseUrl + "&" +
                          "state=" + Session["SessionId"] + "&" +
                          "login_hint=" + Session["Email"] + "&" +
                          "access_type=offline";
    
                Response.Redirect(url);
            }
        }
    
        public ActionResult AuthorizeResponse()
        {
            var state = Request.QueryString["state"];
            if (state == Session["SessionId"].ToString())
            {
                var code = Request.QueryString["code"];
                var values = new Dictionary<string, object>
                {
                    {"code", code},
                    {"redirect_uri", AuthorizeResponseUrl},
                    {"client_id", APIConstants.GMailApiKey},
                    {"client_secret", APIConstants.GmailApiSecret},
                    {"grant_type", "authorization_code"},
                    {"scope", ""}
                };
    
                var webmethods = new WebMethods();
                var tokenResponse = webmethods.Post(_endpoints.TokenEndpoint, values);
    
                var jobject = JObject.Parse(tokenResponse);
                var access_token = jobject.SelectToken("access_token");
                var refresh_token = jobject.SelectToken("refresh_token");
    
                if (access_token == null || access_token.ToString().Trim().Length == 0)
                {
                    //notify devs something went wrong
                    return View(new GoogleAuthResponse(tokenResponse, false));
                }
    
                var credentials = _credentialService.GetUserCredentials(Session["SessionId"].ToString());
    
                credentials.AccessToken = access_token.ToString();
                credentials.RefreshToken = refresh_token.ToString();
                credentials.EmployeeId = Session["UserId"].To<int>();
    
                _credentialService.SaveUserCredentials(credentials);
    
                return View(new GoogleAuthResponse("Integration successful!", true));
            }
    
            return View(new GoogleAuthResponse("Missing state information.", false));
        }
    }
    

    控制器使用另外两个助手类来解析json并发布表单数据,但这应该是非常简单的。

    在花了几天时间试图解决这个问题,但在使用google api.net库方面没有取得任何进展之后,我最终只使用了我自己的实现,这至少是我能够完全理解的。如果任何人都能使用代码,下面是我的结论。仍然需要进行一些重构,但目前它正在工作

    只需要确保AuthorizeResponse和authorizeRoutes注册为authorized redirect URI

    public class GoogleController : Controller
    {
        private readonly CredentialService _credentialService;
        private readonly GoogleEndpoints _endpoints;
    
        public GoogleController()
        {
            _endpoints = new GoogleEndpoints();
            _credentialService = new CredentialService(new CredentialRepository(ConnectionStrings.GeneralInfo));
        }
    
        private string AuthorizeUrl
        {
            get
            {
                return "/Integration/Google/Authorize";
            }
        }
    
        private string AuthorizeResponseUrl
        {
            get
            {
                return "/Integration/Google/AuthorizeResponse";
            }
        }
    
        private string SaveResponseUrl
        {
            get
            {
                return "/Integration/Google/SaveResponse";
            }
        }
    
        public void Authorize()
        {
            if (Session["UserID"] == null || Session["Email"] == null)
            {
                Response.Redirect("~/Login.aspx", true);
                Session["LoginSource"] = AuthorizeUrl;
                Response.End();
            }
            else
            {
                if (Session["SessionId"] == null || Session["SessionId"].ToString().Trim().Length == 0)
                    Session["SessionId"] = _credentialService.CreateSessionId(Session["UserID"].To<int>());
    
                var url = _endpoints.AuthorizationEndpoint + "?" +
                          "client_id=" + APIConstants.GMailApiKey + "&" +
                          "response_type=code&" +
                          "scope=openid%20email&" +
                          "redirect_uri=" + AuthorizeResponseUrl + "&" +
                          "state=" + Session["SessionId"] + "&" +
                          "login_hint=" + Session["Email"] + "&" +
                          "access_type=offline";
    
                Response.Redirect(url);
            }
        }
    
        public ActionResult AuthorizeResponse()
        {
            var state = Request.QueryString["state"];
            if (state == Session["SessionId"].ToString())
            {
                var code = Request.QueryString["code"];
                var values = new Dictionary<string, object>
                {
                    {"code", code},
                    {"redirect_uri", AuthorizeResponseUrl},
                    {"client_id", APIConstants.GMailApiKey},
                    {"client_secret", APIConstants.GmailApiSecret},
                    {"grant_type", "authorization_code"},
                    {"scope", ""}
                };
    
                var webmethods = new WebMethods();
                var tokenResponse = webmethods.Post(_endpoints.TokenEndpoint, values);
    
                var jobject = JObject.Parse(tokenResponse);
                var access_token = jobject.SelectToken("access_token");
                var refresh_token = jobject.SelectToken("refresh_token");
    
                if (access_token == null || access_token.ToString().Trim().Length == 0)
                {
                    //notify devs something went wrong
                    return View(new GoogleAuthResponse(tokenResponse, false));
                }
    
                var credentials = _credentialService.GetUserCredentials(Session["SessionId"].ToString());
    
                credentials.AccessToken = access_token.ToString();
                credentials.RefreshToken = refresh_token.ToString();
                credentials.EmployeeId = Session["UserId"].To<int>();
    
                _credentialService.SaveUserCredentials(credentials);
    
                return View(new GoogleAuthResponse("Integration successful!", true));
            }
    
            return View(new GoogleAuthResponse("Missing state information.", false));
        }
    }
    
    控制器使用另外两个助手类来解析json和发布表单数据,但这应该非常简单