asp.net-mvc-4 – OAuth2和DotNetOpenAuth – 实现Google自定义客户端
|
我在使用DotNetOpenAuth和MVC4实现自定义OAuth2Client for google的问题. 我已经到了这一点,我可以成功地向google终端发出授权请求 并且Google询问用户是否允许我的应用访问其帐户.到目前为止都不错当用户点击“确定”后,Google会按预期的方式调用回调URL. 问题是当我在OAuthWebSecurity类(Microsoft.Web.WebPages.OAuth)上调用VerifyAuthentication方法时, var authenticationResult = OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback",new { ReturnUrl = returnUrl }));
它总是返回一个AuthenticationResult与IsSuccessful = false和Provider =“” 我已经查看了这个代码,OAuthWebSecurity类尝试从中获取提供者名称 Request.QueryString["__provider__"] 但是Google并没有在查询字符串中发送此信息.我已经实施的另一个提供商(LinkedIn)正在发送提供商名称,它一切正常. 我不知道我可以做什么,除了放弃Microsoft.Web.WebPages.OAuth类,只是使用DotNetOpenAuth没有他们,但我希望有人可能有另一个解决方案,我可以尝试… 我已经广泛搜索,但似乎找不到任何帮助…我发现真的很难,只是找到人做同样的事情的例子,这真的让我感到惊讶. 任何帮助非常感谢! 解决方法更新:正如Matt Johnson提到的,他已经打包了一个可以从GitHub: https://github.com/mj1856/DotNetOpenAuth.GoogleOAuth2获得的解决方案他说: 重要 – 如果您使用ASP.Net MVC 5,此包不适用.您应该使用Microsoft.Owin.Security.Google. (它也附带VS 2013中的MVC 5启动器模板) 最后我得到了这个结果,通过捕获请求进来,并做我自己的检查,看看它是哪个提供者. Google允许您将参数发送到名为“state”的OAuth请求,当它们进行回调时,它们将直接传递给您,因此我使用此参数传递google的提供程序名称,并且我检查没有“__provider__”. 这样的: public String GetProviderNameFromQueryString(NameValueCollection queryString)
{
var result = queryString["__provider__"];
if (String.IsNullOrWhiteSpace(result))
{
result = queryString["state"];
}
return result;
}
然后,我为Google实现了一个自定义的OAuth2Client,我自己手动调用VerifyAuthentication方法,绕过了Microsoft的包装器. if (provider is GoogleCustomClient)
{
authenticationResult = ((GoogleCustomClient)provider).VerifyAuthentication(context,new Uri(String.Format("{0}/oauth/ExternalLoginCallback",context.Request.Url.GetLeftPart(UriPartial.Authority).ToString())));
}
else
{
authenticationResult = OAuthWebSecurity.VerifyAuthentication(returnUrl);
}
这使我能够保留我已经为其他提供商使用Microsoft包装器的东西. 根据@ 1010100 1001010的要求,这里是我自定义的OAuth2Client for Google(注意:需要一些TIDYING!我没有办法处理代码上升,它的工作虽然): public class GoogleCustomClient : OAuth2Client
{
ILogger _logger;
#region Constants and Fields
/// <summary>
/// The authorization endpoint.
/// </summary>
private const string AuthorizationEndpoint = "https://accounts.google.com/o/oauth2/auth";
/// <summary>
/// The token endpoint.
/// </summary>
private const string TokenEndpoint = "https://accounts.google.com/o/oauth2/token";
/// <summary>
/// The _app id.
/// </summary>
private readonly string _clientId;
/// <summary>
/// The _app secret.
/// </summary>
private readonly string _clientSecret;
#endregion
public GoogleCustomClient(string clientId,string clientSecret)
: base("Google")
{
if (string.IsNullOrWhiteSpace(clientId)) throw new ArgumentNullException("clientId");
if (string.IsNullOrWhiteSpace(clientSecret)) throw new ArgumentNullException("clientSecret");
_logger = ObjectFactory.GetInstance<ILogger>();
this._clientId = clientId;
this._clientSecret = clientSecret;
}
protected override Uri GetServiceLoginUrl(Uri returnUrl)
{
StringBuilder serviceUrl = new StringBuilder();
serviceUrl.AppendFormat("{0}?scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile",AuthorizationEndpoint);
serviceUrl.Append("&state=google");
serviceUrl.AppendFormat("&redirect_uri={0}",returnUrl.ToString());
serviceUrl.Append("&response_type=code");
serviceUrl.AppendFormat("&client_id={0}",_clientId);
return new Uri(serviceUrl.ToString());
}
protected override IDictionary<string,string> GetUserData(string accessToken)
{
RestClient client = new RestClient("https://www.googleapis.com");
var request = new RestRequest(String.Format("/oauth2/v1/userinfo?access_token={0}",accessToken),Method.GET);
IDictionary<String,String> extraData = new Dictionary<String,String>();
var response = client.Execute(request);
if (null != response.ErrorException)
{
return null;
}
else
{
try
{
var json = JObject.Parse(response.Content);
string firstName = (string)json["given_name"];
string lastName = (string)json["family_name"];
string emailAddress = (string)json["email"];
string id = (string)json["id"];
extraData = new Dictionary<String,String>
{
{"accesstoken",accessToken},{"name",String.Format("{0} {1}",firstName,lastName)},{"firstname",firstName},{"lastname",lastName},{"email",emailAddress},{"id",id}
};
}
catch(Exception ex)
{
_logger.Error("Error requesting OAuth user data from Google",ex);
return null;
}
return extraData;
}
}
protected override string QueryAccessToken(Uri returnUrl,string authorizationCode)
{
StringBuilder postData = new StringBuilder();
postData.AppendFormat("client_id={0}",this._clientId);
postData.AppendFormat("&redirect_uri={0}",HttpUtility.UrlEncode(returnUrl.ToString()));
postData.AppendFormat("&client_secret={0}",this._clientSecret);
postData.AppendFormat("&grant_type={0}","authorization_code");
postData.AppendFormat("&code={0}",authorizationCode);
string response = "";
string accessToken = "";
var webRequest = (HttpWebRequest)WebRequest.Create(TokenEndpoint);
webRequest.Method = "POST";
webRequest.ContentType = "application/x-www-form-urlencoded";
try
{
using (Stream s = webRequest.GetRequestStream())
{
using (StreamWriter sw = new StreamWriter(s))
sw.Write(postData.ToString());
}
using (WebResponse webResponse = webRequest.GetResponse())
{
using (StreamReader reader = new StreamReader(webResponse.GetResponseStream()))
{
response = reader.ReadToEnd();
}
}
var json = JObject.Parse(response);
accessToken = (string)json["access_token"];
}
catch(Exception ex)
{
_logger.Error("Error requesting OAuth access token from Google",ex);
return null;
}
return accessToken;
}
public override AuthenticationResult VerifyAuthentication(HttpContextBase context,Uri returnPageUrl)
{
string code = context.Request.QueryString["code"];
if (string.IsNullOrEmpty(code))
{
return AuthenticationResult.Failed;
}
string accessToken = this.QueryAccessToken(returnPageUrl,code);
if (accessToken == null)
{
return AuthenticationResult.Failed;
}
IDictionary<string,string> userData = this.GetUserData(accessToken);
if (userData == null)
{
return AuthenticationResult.Failed;
}
string id = userData["id"];
string name;
// Some oAuth providers do not return value for the 'username' attribute.
// In that case,try the 'name' attribute. If it's still unavailable,fall back to 'id'
if (!userData.TryGetValue("username",out name) && !userData.TryGetValue("name",out name))
{
name = id;
}
// add the access token to the user data dictionary just in case page developers want to use it
userData["accesstoken"] = accessToken;
return new AuthenticationResult(
isSuccessful: true,provider: this.ProviderName,providerUserId: id,userName: name,extraData: userData);
} (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- asp.net-mvc-3 – 在MVC 3.0中重写Html.BeginForm()并保持不
- asp.net – 组合两个List(Of String)最有效的方法是什么?
- asp.net – AsyncPostBackTrigger和PostBackTrigger有什么区
- .net – 每个堆栈跟踪线末尾的标志是什么?
- asp.net-mvc-4 – 在VS2012中运行代码分析时出错
- MVC 5远程验证
- asp.net – 通过IP地址在IIS 6中调节Bandands
- asp.net – 注册.NET 4.5 IIS 10 Windows 10
- asp.net-mvc – 使JSON.NET和Serializable属性一起工作
- oauth-2.0 – 覆盖AccessTokenExpireTimeSpan
- 将数据从ASP.net返回到ExtJS网格
- ASP.NET 4 URL限制:为什么URL不能包含任何内容?
- asp.net – 如何从ASP Web服务的JSON响应中删除d
- asp.net-mvc – 在链接文本中使用HTML元素创建一
- ASP.NET Core 2.0 Razor vs Angular/React/etc.
- ASP.net使用表单将数据插入到sql server表中
- 在ASP.NET MVC网站中无法获取详细的错误信息
- ASP.NET 清除模式窗口数据缓存的操作方式
- asp.net-mvc – 404 Asp.Net中的Http错误处理程序
- 为什么要使用ASP.NET MVC 2进行REST服务?为什么
