c# - 在 Winfroms 浏览器控件中查看 Google 日历
问题描述
我想在 winforms 的网络浏览器控件中显示我的 Google 日历。
我试图按照教程https://www.daimto.com/google-api-and-oath2/
但不幸的是,我仍然没有获得访问我的谷歌日历的权限,“浏览器不安全......”。
我知道我必须以某种方式使用访问权限,但我不知道如何使用。
编码:
public partial class Kalender : UserControl
{
public string clientId = "897492813624-glvfpm6heik1fqr7s2mjtl6eme5ad8bq.apps.googleusercontent.com";
public string redirectUri = "https://calendar.google.com/";
public string clientSecret = "HYGFBEd_BZPcWcrPopsX4uZr";
public string redirectURI = "https://calendar.google.com/";
public AuthResponse access;
public Kalender()
{
InitializeComponent();
webKalender.Navigate(AuthResponse.GetAutenticationURI(clientId, redirectUri));
}
private void webKalender_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
string Mytitle = ((WebBrowser)sender).DocumentTitle.ToLower();
if (Mytitle.IndexOf("success code=") > -1)
{
webKalender.Visible = false;
// searching the body for our code
string AuthCode = webKalender.DocumentTitle.Replace("Success code=", "");
string webText = ((WebBrowser)sender).DocumentText;
int start = webText.IndexOf("id=\"code\"");
start = webText.IndexOf(AuthCode, start);
int end = webText.IndexOf('"', start);
string authCode = webText.Substring(start, end - start);
//Exchange the code for Access token and refreshtoken.
access = AuthResponse.Exchange(authCode, clientId, clientSecret, redirectURI);
//processAccess();
}
}
教程中的课程:
public class AuthResponse
{
private string access_token;
public string Access_token
{
get
{
// Access token lasts an hour if its expired we get a new one.
if (DateTime.Now.Subtract(created).Hours > 1)
{
refresh();
}
return access_token;
}
set { access_token = value; }
}
public string refresh_token { get; set; }
public string clientId { get; set; }
public string secret { get; set; }
public string expires_in { get; set; }
public DateTime created { get; set; }
//"{\n \"access_token\" : \"ya29.kwFUj-la2lATSkrqFlJXBqQjCIZiTg51GYpKt8Me8AJO5JWf0Sx6-0ZWmTpxJjrBrxNS_JzVw969LA\",\n \"token_type\" : \"Bearer\",\n \"expires_in\" : 3600,\n \"refresh_token\" : \"1/ejoPJIyBAhPHRXQ7pHLxJX2VfDBRz29hqS_i5DuC1cQ\"\n}"
public static AuthResponse get(string response)
{
AuthResponse result = (AuthResponse)JsonConvert.DeserializeObject(response);
result.created = DateTime.Now; // DateTime.Now.Add(new TimeSpan(-2, 0, 0)); //For testing force refresh.
return result;
}
public void refresh()
{
var request = (HttpWebRequest)WebRequest.Create("https://accounts.google.com/o/oauth2/token");
string postData = string.Format("client_id={0}&client_secret={1}&refresh_token={2}&grant_type=refresh_token", this.clientId, this.secret, this.refresh_token);
var data = Encoding.ASCII.GetBytes(postData);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
var response = (HttpWebResponse)request.GetResponse();
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
var refreshResponse = AuthResponse.get(responseString);
this.access_token = refreshResponse.access_token;
this.created = DateTime.Now;
}
public static AuthResponse Exchange(string authCode, string clientid, string secret, string redirectURI)
{
var request = (HttpWebRequest)WebRequest.Create("https://accounts.google.com/o/oauth2/token");
string postData = string.Format("code={0}&client_id={1}&client_secret={2}&redirect_uri={3}&grant_type=authorization_code", authCode, clientid, secret, redirectURI);
var data = Encoding.ASCII.GetBytes(postData);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
using (var stream = request.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
var response = (HttpWebResponse)request.GetResponse();
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
var x = AuthResponse.get(responseString);
x.clientId = clientid;
x.secret = secret;
return x;
}
public static Uri GetAutenticationURI(string clientId, string redirectUri)
{
string scopes = "https://www.googleapis.com/auth/calendar";
if (string.IsNullOrEmpty(redirectUri))
{
redirectUri = "urn:ietf:wg:oauth:2.0:oob";
}
string oauth = string.Format("https://accounts.google.com/o/oauth2/auth?client_id={0}&redirect_uri={1}&scope={2}&response_type=code", clientId, redirectUri, scopes);
return new Uri(oauth);
}
}
对不起德国人,但它说的是:“浏览器或应用程序我不安全。使用不同的浏览器。”
解决方案
我想在 winforms 的网络浏览器控件中显示我的 Google 日历。
您应该了解的第一件事是,如果您尝试在您的应用程序中显示 Google 日历 Web 应用程序,那么如果不使用该代码或任何代码,它就无法工作。
您可以做的是使用 Google 日历 API 访问 Google 日历数据,然后在您的 Web 表单中创建您自己的数据显示。
这就是您使用的代码旨在执行的操作。然而,它已经九岁多了。
如果可能的话,您应该使用 Google .net 客户端库。话虽如此,您使用的代码最初是为 .Net 3.5 九年前编写的。google .net 客户端库不支持 .net 3.5。(我不是指我们谈论的更老的 .Net core 3.1。)
从那时起,安全性发生了很多变化。如果 Google 检测到您正在 web 视图中打开它,那么它可能无法正常工作。这些天,身份验证屏幕工作的唯一方法是在机器上安装的浏览器中打开 oauth 窗口。
.net 客户端库就是为此而设计的。
这里有一些授权代码可以帮助您入门。
public static class Oauth2Example
{
/// <summary>
/// ** Installed Aplication only **
/// This method requests Authentcation from a user using Oauth2.
/// </summary>
/// <param name="clientSecretJson">Path to the client secret json file from Google Developers console.</param>
/// <param name="userName">Identifying string for the user who is being authentcated.</param>
/// <param name="scopes">Array of Google scopes</param>
/// <returns>CalendarService used to make requests against the Calendar API</returns>
public static CalendarService GetCalendarService(string clientSecretJson, string userName, string[] scopes)
{
try
{
if (string.IsNullOrEmpty(userName))
throw new ArgumentNullException("userName");
if (string.IsNullOrEmpty(clientSecretJson))
throw new ArgumentNullException("clientSecretJson");
if (!File.Exists(clientSecretJson))
throw new Exception("clientSecretJson file does not exist.");
var cred = GetUserCredential(clientSecretJson, userName, scopes);
return GetService(cred);
}
catch (Exception ex)
{
throw new Exception("Get Calendar service failed.", ex);
}
}
/// <summary>
/// ** Installed Aplication only **
/// This method requests Authentcation from a user using Oauth2.
/// Credentials are stored in System.Environment.SpecialFolder.Personal
/// Documentation https://developers.google.com/accounts/docs/OAuth2
/// </summary>
/// <param name="clientSecretJson">Path to the client secret json file from Google Developers console.</param>
/// <param name="userName">Identifying string for the user who is being authentcated.</param>
/// <param name="scopes">Array of Google scopes</param>
/// <returns>authencated UserCredential</returns>
private static UserCredential GetUserCredential(string clientSecretJson, string userName, string[] scopes)
{
try
{
if (string.IsNullOrEmpty(userName))
throw new ArgumentNullException("userName");
if (string.IsNullOrEmpty(clientSecretJson))
throw new ArgumentNullException("clientSecretJson");
if (!File.Exists(clientSecretJson))
throw new Exception("clientSecretJson file does not exist.");
// These are the scopes of permissions you need. It is best to request only what you need and not all of them
using (var stream = new FileStream(clientSecretJson, FileMode.Open, FileAccess.Read))
{
string credPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
credPath = Path.Combine(credPath, ".credentials/", System.Reflection.Assembly.GetExecutingAssembly().GetName().Name);
// Requesting Authentication or loading previously stored authentication for userName
var credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.Load(stream).Secrets,
scopes,
userName,
CancellationToken.None,
new FileDataStore(credPath, true)).Result;
credential.GetAccessTokenForRequestAsync();
return credential;
}
}
catch (Exception ex)
{
throw new Exception("Get user credentials failed.", ex);
}
}
/// <summary>
/// This method get a valid service
/// </summary>
/// <param name="credential">Authecated user credentail</param>
/// <returns>CalendarService used to make requests against the Calendar API</returns>
private static CalendarService GetService(UserCredential credential)
{
try
{
if (credential == null)
throw new ArgumentNullException("credential");
// Create Calendar API service.
return new CalendarService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Calendar Oauth2 Authentication Sample"
});
}
catch (Exception ex)
{
throw new Exception("Get Calendar service failed.", ex);
}
}
}
推荐阅读
- cookies - 我应该使用哪个触发器来为分配 cookie 留出时间?
- python - 如何使用主机 Web 浏览器访问 docker 容器中正在运行的 dashapp(IP 端口)?
- mongodb - 更新和建模 nosql 记录
- css - 如何用纯 css 覆盖 hsl 亮度
- node.js - 长时间运行过程的最佳方法 - NodeJS
- php - 为什么 CONTEXT_DOCUMENT_ROOT 使用不安全?
- python-3.x - Python烧瓶mqtt socketio并在启动时订阅
- python - 如何在烧瓶服务器端接收动态 jQuery 字段
- java - Spark 内存问题 - “没有足够的内存来构建哈希映射”
- reactjs - [CRA][Vscode] 创建新文件时绝对导入不起作用