如何强制 Microsoft.IdentityModel.S2S.Protocols.OAuth2.OAuth2S2SClient.Issue 使用网络代理?
How to force Microsoft.IdentityModel.S2S.Protocols.OAuth2.OAuth2S2SClient.Issue to use web proxy?
我正在创建一个将使用 CSOM 连接到 SharePoint Online 的守护程序应用程序。我的应用程序将 运行 在互联网代理后面的公司环境中。我正在使用标准的 SharePoint 加载项模型,提供 TokenHelper 和 SharePointContext 类,使用 Microsoft.IdentityModel.Extensions.dll.
我在两个地方设置了 TokenHelper 使用代理:GetRealmFromTargetUrl 中的 WebRequest 和 AcsMetadataParser 中的 WebClient。
但它不起作用,因为在我看来 DLL 使用了另一个 Web 请求。以下是触发异常的执行的 StackTraces:
Exception Message: Token request failed.
Stack Trace:
at Microsoft.IdentityModel.S2S.Protocols.OAuth2.OAuth2S2SClient.Issue(String securityTokenServiceUrl, OAuth2AccessTokenRequest oauth2Request)
at ScriptTask_d38d98a4cb054097ac7c2ece4802bf9a.spo.TokenHelper.GetAppOnlyAccessToken(String targetPrincipalName, String targetHost, String targetRealm)
at ScriptTask_d38d98a4cb054097ac7c2ece4802bf9a.ScriptMain.Main()
Inner Exception Message: Unable to connect to the remote server
Inner Stack Trace:
at System.Net.HttpWebRequest.GetRequestStream(TransportContext& context)
at System.Net.HttpWebRequest.GetRequestStream()
at Microsoft.IdentityModel.S2S.Protocols.OAuth2.OAuth2WebRequest.GetResponse()
at Microsoft.IdentityModel.S2S.Protocols.OAuth2.OAuth2S2SClient.Issue(String securityTokenServiceUrl, OAuth2AccessTokenRequest oauth2Request)
不知是否有解决办法?
绕过它。
而不是这个调用:
oauth2Response =
client.Issue(AcsMetadataParser.GetStsUrl(targetRealm),
oauth2Request) as OAuth2AccessTokenResponse;
我使用以下代码创建了一个静态方法 IssueToken 和一个虚拟方法 "mapping" class:
private static OAuth2AccessTokenResponse IssueToken(string sts, OAuth2AccessTokenRequest oauth2Request) {
string requestString = "grant_type=" + System.Web.HttpUtility.UrlEncode(oauth2Request.GrantType) +
"&client_id=" + System.Web.HttpUtility.UrlEncode(oauth2Request.ClientId) +
"&client_secret=" + System.Web.HttpUtility.UrlEncode(oauth2Request.ClientSecret) +
"&resource=" + System.Web.HttpUtility.UrlEncode(oauth2Request.Resource);
string tokenResponse;
byte[] byteArray = Encoding.UTF8.GetBytes(requestString);
WebRequest request = WebRequest.Create(sts);
request.Proxy = new System.Net.WebProxy { Address = new Uri(InternetProxy) };
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = byteArray.Length;
using (Stream reqStream = request.GetRequestStream()) {
reqStream.Write(byteArray, 0, byteArray.Length);
}
using (WebResponse response = request.GetResponse()) {
using (Stream respStream = response.GetResponseStream()) {
using (StreamReader reader = new StreamReader(respStream)) {
tokenResponse = reader.ReadToEnd();
}
}
}
JavaScriptSerializer jss = new JavaScriptSerializer();
OAuth2AccessTokenResponseDummy dummy = jss.Deserialize<OAuth2AccessTokenResponseDummy>(tokenResponse);
OAuth2AccessTokenResponse oauth2Response = new OAuth2AccessTokenResponse () {
TokenType = dummy.token_type,
ExpiresIn = dummy.expires_in,
NotBefore = jss.Deserialize<DateTime>(@"""\/Date(" + dummy.not_before + @")\/""").ToLocalTime(),
ExpiresOn = jss.Deserialize<DateTime>(@"""\/Date(" + dummy.expires_on + @")\/""").ToLocalTime(),
Scope = dummy.resource,
AccessToken = dummy.access_token
};
return oauth2Response;
}
private class OAuth2AccessTokenResponseDummy {
public string token_type { get; set; }
public string expires_in { get; set; }
public string not_before { get; set; }
public string expires_on { get; set; }
public string resource { get; set; }
public string access_token { get; set; }
}
而且我还在 GetClientContextWithAccessToken 的委托中添加了网络代理:
public static ClientContext GetClientContextWithAccessToken(string targetUrl, string accessToken) {
ClientContext clientContext = new ClientContext(targetUrl);
clientContext.AuthenticationMode = ClientAuthenticationMode.Anonymous;
clientContext.FormDigestHandlingEnabled = false;
clientContext.ExecutingWebRequest +=
delegate(object oSender, WebRequestEventArgs webRequestEventArgs) {
webRequestEventArgs.WebRequestExecutor.RequestHeaders["Authorization"] = "Bearer " + accessToken;
webRequestEventArgs.WebRequestExecutor.WebRequest.Proxy = webProxy;
};
return clientContext;
}
我正在创建一个将使用 CSOM 连接到 SharePoint Online 的守护程序应用程序。我的应用程序将 运行 在互联网代理后面的公司环境中。我正在使用标准的 SharePoint 加载项模型,提供 TokenHelper 和 SharePointContext 类,使用 Microsoft.IdentityModel.Extensions.dll.
我在两个地方设置了 TokenHelper 使用代理:GetRealmFromTargetUrl 中的 WebRequest 和 AcsMetadataParser 中的 WebClient。
但它不起作用,因为在我看来 DLL 使用了另一个 Web 请求。以下是触发异常的执行的 StackTraces:
Exception Message: Token request failed.
Stack Trace:
at Microsoft.IdentityModel.S2S.Protocols.OAuth2.OAuth2S2SClient.Issue(String securityTokenServiceUrl, OAuth2AccessTokenRequest oauth2Request)
at ScriptTask_d38d98a4cb054097ac7c2ece4802bf9a.spo.TokenHelper.GetAppOnlyAccessToken(String targetPrincipalName, String targetHost, String targetRealm)
at ScriptTask_d38d98a4cb054097ac7c2ece4802bf9a.ScriptMain.Main()
Inner Exception Message: Unable to connect to the remote server
Inner Stack Trace:
at System.Net.HttpWebRequest.GetRequestStream(TransportContext& context)
at System.Net.HttpWebRequest.GetRequestStream()
at Microsoft.IdentityModel.S2S.Protocols.OAuth2.OAuth2WebRequest.GetResponse()
at Microsoft.IdentityModel.S2S.Protocols.OAuth2.OAuth2S2SClient.Issue(String securityTokenServiceUrl, OAuth2AccessTokenRequest oauth2Request)
不知是否有解决办法?
绕过它。
而不是这个调用:
oauth2Response =
client.Issue(AcsMetadataParser.GetStsUrl(targetRealm),
oauth2Request) as OAuth2AccessTokenResponse;
我使用以下代码创建了一个静态方法 IssueToken 和一个虚拟方法 "mapping" class:
private static OAuth2AccessTokenResponse IssueToken(string sts, OAuth2AccessTokenRequest oauth2Request) {
string requestString = "grant_type=" + System.Web.HttpUtility.UrlEncode(oauth2Request.GrantType) +
"&client_id=" + System.Web.HttpUtility.UrlEncode(oauth2Request.ClientId) +
"&client_secret=" + System.Web.HttpUtility.UrlEncode(oauth2Request.ClientSecret) +
"&resource=" + System.Web.HttpUtility.UrlEncode(oauth2Request.Resource);
string tokenResponse;
byte[] byteArray = Encoding.UTF8.GetBytes(requestString);
WebRequest request = WebRequest.Create(sts);
request.Proxy = new System.Net.WebProxy { Address = new Uri(InternetProxy) };
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = byteArray.Length;
using (Stream reqStream = request.GetRequestStream()) {
reqStream.Write(byteArray, 0, byteArray.Length);
}
using (WebResponse response = request.GetResponse()) {
using (Stream respStream = response.GetResponseStream()) {
using (StreamReader reader = new StreamReader(respStream)) {
tokenResponse = reader.ReadToEnd();
}
}
}
JavaScriptSerializer jss = new JavaScriptSerializer();
OAuth2AccessTokenResponseDummy dummy = jss.Deserialize<OAuth2AccessTokenResponseDummy>(tokenResponse);
OAuth2AccessTokenResponse oauth2Response = new OAuth2AccessTokenResponse () {
TokenType = dummy.token_type,
ExpiresIn = dummy.expires_in,
NotBefore = jss.Deserialize<DateTime>(@"""\/Date(" + dummy.not_before + @")\/""").ToLocalTime(),
ExpiresOn = jss.Deserialize<DateTime>(@"""\/Date(" + dummy.expires_on + @")\/""").ToLocalTime(),
Scope = dummy.resource,
AccessToken = dummy.access_token
};
return oauth2Response;
}
private class OAuth2AccessTokenResponseDummy {
public string token_type { get; set; }
public string expires_in { get; set; }
public string not_before { get; set; }
public string expires_on { get; set; }
public string resource { get; set; }
public string access_token { get; set; }
}
而且我还在 GetClientContextWithAccessToken 的委托中添加了网络代理:
public static ClientContext GetClientContextWithAccessToken(string targetUrl, string accessToken) {
ClientContext clientContext = new ClientContext(targetUrl);
clientContext.AuthenticationMode = ClientAuthenticationMode.Anonymous;
clientContext.FormDigestHandlingEnabled = false;
clientContext.ExecutingWebRequest +=
delegate(object oSender, WebRequestEventArgs webRequestEventArgs) {
webRequestEventArgs.WebRequestExecutor.RequestHeaders["Authorization"] = "Bearer " + accessToken;
webRequestEventArgs.WebRequestExecutor.WebRequest.Proxy = webProxy;
};
return clientContext;
}