- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
场景如下:我需要对用户(使用他的大学帐户)执行联合身份验证到他大学的 Sharepoint 站点,并同时获取 FedAuth 和 rtFa cookie(我必须将其传递给 SharePoint REST web 服务才能访问资源)。
我做了一些尝试,但每一个都至少有一个问题:
ClientContext context = new ClientContext(host);
SharePointOnlineCredentials creds = new SharePointOnlineCredentials(user, passw);
context.Credentials = creds;
Uri sharepointuri = new Uri(host);
string authCookie = creds.GetAuthenticationCookie(sharepointuri);
Web web = context.Web;
context.Load(web, w=>w.Lists);
context.ExecuteQuery();
fedAuthString = authCookie.Replace("SPOIDCRL=", string.Empty);
通过这种方式我设法获得了 FedAuth cookie,但我无法获得 rtFa cookie。
此时如何获取 rtFa cookie?我能否拦截此类操作中涉及的 HTTP 请求(即 context.ExecuteQuery())——它可能在 header 中包含 rtFa cookie?或者,我能否仅利用 FedAuth cookie 获取 rtFa cookie?
这是一个可以在 Internet 上找到的辅助类(例如,此处 http://blog.kloud.com.au/tag/msonlineclaimshelper/)。
按原样,此类适用于普通身份验证,但无法使用联合身份验证。
所以我调整了它以使其在这种情况下起作用。据我了解,步骤如下:
我不是这方面的专家,我得出了以下代码:
这是调用上述方法并尝试分两步从凭据中获取 FedAuth 和 rtFa 的代码(第 1 步:从联盟方获取 SAML token ;第 2 步:将 token 从联盟方传递到 Sharepoint):
private List<string> GetCookies(){
// 1: GET SAML XML FROM FEDERATED PARTY THE USER BELONGS TO
string samlToken = getResponse_Federation(sts: "https://sts.FEDERATEDDOMAIN.com/adfs/services/trust/13/usernamemixed/",
realm: "https://login.microsoftonline.com/extSTS.srf");
// 2: PARSE THE SAML ASSERTION INTO A TOKEN
var handlers = FederatedAuthentication.ServiceConfiguration.SecurityTokenHandlers;
SecurityToken token = handlers.ReadToken(new XmlTextReader(new StringReader(samlToken )));
// 3: REQUEST A NEW TOKEN BASED ON THE ISSUED TOKEN
GenericXmlSecurityToken secToken = GetO365BinaryTokenFromToken(token);
// 4: NOW, EASY: I PARSE THE TOKEN AND EXTRACT FEDAUTH and RTFA
...............
}
private string getResponse_Federation(string stsUrl, string relyingPartyAddress)
{
var binding = new Microsoft.IdentityModel.Protocols.WSTrust.Bindings.UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential);
binding.ClientCredentialType = HttpClientCredentialType.None;
var factory = new WSTrustChannelFactory(binding, stsUrl);
factory.Credentials.UserName.UserName = "username";
factory.Credentials.UserName.Password = "password";
factory.Credentials.SupportInteractive = false;
factory.TrustVersion = TrustVersion.WSTrust13;
IWSTrustChannelContract channel = null;
try
{
var rst = new RequestSecurityToken
{
RequestType = WSTrust13Constants.RequestTypes.Issue,
AppliesTo = new EndpointAddress(relyingPartyAddress), //("urn:sharepoint:MYFEDERATEDPARTY"),
ReplyTo = relyingPartyAddress,
KeyType = WSTrust13Constants.KeyTypes.Bearer,
TokenType = "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0",
RequestDisplayToken = true,
};
channel = (WSTrustChannel)factory.CreateChannel();
RequestSecurityTokenResponse response = null;
SecurityToken st = channel.Issue(rst, out response);
var genericToken = st as GenericXmlSecurityToken;
return genericToken.TokenXml.OuterXml;
}
catch (Exception e)
{
return null;
}
}
private GenericXmlSecurityToken GetO365BinaryTokenFromToken(SecurityToken issuedToken)
{
Uri u = new Uri("https://login.microsoftonline.com/extSTS.srf");
WSHttpBinding binding = new WSHttpBinding(SecurityMode.TransportWithMessageCredential);
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
binding.Security.Mode = SecurityMode.TransportWithMessageCredential;
binding.Security.Message.ClientCredentialType = MessageCredentialType.IssuedToken;
Microsoft.IdentityModel.Protocols.WSTrust.WSTrustChannelFactory channel =
new Microsoft.IdentityModel.Protocols.WSTrust.WSTrustChannelFactory(
binding, new EndpointAddress("https://login.microsoftonline.com/extSTS.srf"));
channel.TrustVersion = TrustVersion.WSTrust13;
channel.Credentials.SupportInteractive = false;
GenericXmlSecurityToken token = null;
try
{
RequestSecurityToken rst = new RequestSecurityToken(WSTrust13Constants.RequestTypes.Issue, WSTrust13Constants.KeyTypes.Bearer)
{
};
rst.AppliesTo = new EndpointAddress("urn:sharepoint:MYFEDERATEDPARTY");
channel.ConfigureChannelFactory();
var chan = (Microsoft.IdentityModel.Protocols.WSTrust.WSTrustChannel)channel.CreateChannelWithIssuedToken(issuedToken);
RequestSecurityTokenResponse rstr = null;
token = chan.Issue(rst, out rstr) as GenericXmlSecurityToken;
return token;
}
catch (Exception ex){
Trace.TraceWarning("WebException in getO365BinaryTokenFromADFS: " + ex.ToString());
throw;
}
}
我设法从大学 STS 取回了一个 SAML token 。但是,在解析时,生成的 SecurityToken 没有安全 key (即 SecurityKeys 集合为空)
在没有 key 的情况下,我可以使用 GetO365BinaryTokenFromToken(),但是当我尝试将 token 发送到 SharePoint 身份验证服务时,出现以下错误:“签名 token Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityToken 没有 key 。安全 token 在需要它执行加密操作的上下文中使用,但 token 不包含加密 key 。 token 类型不支持加密操作,或者特定的 token 实例不包含加密 key 。检查您的配置以确保在需要加密操作的上下文中未指定加密禁用的 token 类型(例如,UserNameSecurityToken)(例如,背书支持 token )。“
我认为在双方(大学 STS ADFS 和 Sharepoint STS)上也存在一些我无法直接控制的配置问题。
我希望更多的专家能够阐明这个过程,甚至提供建议让这个场景真正起作用。
使用以下功能,我可以通过发出 BOTH FedAuth 和 rtFa cookie 下载文件(给定 URL,例如 https://myfederatedparty.sharepoint.com/sites/MYSITE/path/myfile.pdf )。如果我不传递 rtFa cookie,我会收到“未经授权”的响应。
public static async Task<byte[]> TryRawWsCall(String url, string fedauth, string rtfa, CancellationToken ct, TimeSpan? timeout = null) {
try {
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = new System.Net.CookieContainer();
CookieCollection cc = new CookieCollection();
cc.Add(new Cookie("FedAuth", fedauth));
cc.Add(new Cookie("rtFa", rtfa));
handler.CookieContainer.Add(new Uri(url), cc);
HttpClient _client = new HttpClient(handler);
if (timeout.HasValue)
_client.Timeout = timeout.Value;
ct.ThrowIfCancellationRequested();
var resp = await _client.GetAsync(url);
var result = await resp.Content.ReadAsByteArrayAsync();
if (!resp.IsSuccessStatusCode)
return null;
return result;
}
catch (Exception) { return null; }
}
最佳答案
事实上,当涉及到 SharePoint Online/Office 365 身份验证时,只有 FedAuth
cookie 是必需的。
根据 Remote Authentication in SharePoint Online Using Claims-Based Authentication :
The
FedAuth
cookies enable federated authorization, and thertFA
cookie enables signing out the user from all SharePoint sites, even if the sign-out process starts from a non-SharePoint site.
因此,为了在 SharePoint Online/Office 365 中执行身份验证,提供 SPOIDCRL
HTTP header 就足够了,例如:
var request = (HttpWebRequest)WebRequest.Create(endpointUri);
var credentials = new SharePointOnlineCredentials(userName,securePassword);
var authCookie = credentials.GetAuthenticationCookie(webUri);
request.Headers.Add(HttpRequestHeader.Cookie, authCookie);
以下示例演示如何通过提供 FedAuth
cookie 在 SharePointOnline/Office 365 中执行主动身份验证。
示例 1:通过 SharePoint 2013 REST API(uisng MsOnlineClaimsHelper 类
)检索 FormDigest
public static string GetFormDigest(Uri webUri, string userName, string password)
{
var claimsHelper = new MsOnlineClaimsHelper(webUri, userName, password);
var endpointUri = new Uri(webUri,"/_api/contextinfo");
var request = (HttpWebRequest)WebRequest.Create(endpointUri);
request.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
request.Method = WebRequestMethods.Http.Post;
request.Accept = "application/json;odata=verbose";
request.ContentType = "application/json;odata=verbose";
request.ContentLength = 0;
var fedAuthCookie = claimsHelper.CookieContainer.GetCookieHeader(webUri); //FedAuth are getting here
request.Headers.Add(HttpRequestHeader.Cookie, fedAuthCookie); //only FedAuth cookie are provided here
//request.CookieContainer = claimsHelper.CookieContainer;
using (var response = (HttpWebResponse) request.GetResponse())
{
using (var streamReader = new StreamReader(response.GetResponseStream()))
{
var content = streamReader.ReadToEnd();
var t = JToken.Parse(content);
return t["d"]["GetContextWebInformation"]["FormDigestValue"].ToString();
}
}
}
示例 2:通过 SharePoint 2013 REST API 检索 FormDigest(使用 SharePointOnlineCredentials 类
)
public static string GetFormDigest(Uri webUri, string userName, string password)
{
var endpointUri = new Uri(webUri, "/_api/contextinfo");
var request = (HttpWebRequest)WebRequest.Create(endpointUri);
request.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
request.Method = WebRequestMethods.Http.Post;
request.Accept = "application/json;odata=verbose";
request.ContentType = "application/json;odata=verbose";
request.ContentLength = 0;
var securePassword = new SecureString();
foreach (char c in password)
{
securePassword.AppendChar(c);
}
request.Credentials = new SharePointOnlineCredentials(userName,securePassword);
using (var response = (HttpWebResponse)request.GetResponse())
{
using (var streamReader = new StreamReader(response.GetResponseStream()))
{
var content = streamReader.ReadToEnd();
var t = JToken.Parse(content);
return t["d"]["GetContextWebInformation"]["FormDigestValue"].ToString();
}
}
}
更新
下载文件示例修改版:
public static async Task<byte[]> DownloadFile(Uri webUri,string userName,string password, string relativeFileUrl, CancellationToken ct, TimeSpan? timeout = null)
{
try
{
var securePassword = new SecureString();
foreach (var c in password)
{
securePassword.AppendChar(c);
}
var credentials = new SharePointOnlineCredentials(userName, securePassword);
var authCookie = credentials.GetAuthenticationCookie(webUri);
var fedAuthString = authCookie.TrimStart("SPOIDCRL=".ToCharArray());
var cookieContainer = new CookieContainer();
cookieContainer.Add(webUri, new Cookie("SPOIDCRL", fedAuthString));
HttpClientHandler handler = new HttpClientHandler();
handler.CookieContainer = cookieContainer;
HttpClient _client = new HttpClient(handler);
if (timeout.HasValue)
_client.Timeout = timeout.Value;
ct.ThrowIfCancellationRequested();
var fileUrl = new Uri(webUri, relativeFileUrl);
var resp = await _client.GetAsync(fileUrl);
var result = await resp.Content.ReadAsByteArrayAsync();
if (!resp.IsSuccessStatusCode)
return null;
return result;
}
catch (Exception) { return null; }
}
关于c# - Sharepoint 2013 中的联合身份验证 : getting rtFa and FedAuth cookies,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25388696/
我在尝试跟踪过期的 WIF 身份验证 session /cookie 时遇到了一个有趣的问题。 作为背景知识:该站点是 MVC 3,使用与 ADFS 服务器作为 STS 的信任的 Windows Id
我是基于声明的身份验证的新手。谁能解释一下什么是 SAML token 和 FedAuth cookie?它们之间的关系是什么? 最佳答案 SAML token 是一段 XML,包含有关用户身份的信息
我有一个 ASP.NET 应用程序,它使用 Azure ACS(和间接 ADFS)进行身份验证 - 一切正常。现在我被要求将 SessionToken 传递给另一个后端服务,在那里可以验证它并提取声明
我们正在使用 Windows Identity Foundation 为我们的应用程序实现单一登录解决方案。我遇到的问题是 FedAuth cookie 在我认为应该在依赖方方面过期时没有过期。 Fe
我有一个在 Azure 上运行的 ASP.NET 站点,网址为 https://[appname].cloudapp.net。我在 https://[appname].cloudapp.net/Web
我有一个使用 SSL 保护的 ASP.Net MVC 站点,我正在使用 System.IdentityModel.Services 并像这样创建 token : SessionSecurityToke
我正在努力弄清楚为什么 ClaimsPrincipal只有 7 项 claim 正在产生 5 FedAuth来自 FAM 的 Cookie(FedAuth1、FedAuth2、FedAuth3、F
场景如下:我需要对用户(使用他的大学帐户)执行联合身份验证到他大学的 Sharepoint 站点,并同时获取 FedAuth 和 rtFa cookie(我必须将其传递给 SharePoint RES
我很难更改 ASP.NET MVC 应用程序上的 SameSite 属性。这是场景: 我正在尝试将我的 ASP.NET 应用程序加载到 iframe 中,并且由于 Google Chrome 80+
我将 WIF 与 WS Federation 结合使用,以便我的 ASP.NET 应用程序可以针对 STS (Thinktecture IdentityServer) 进行身份验证。在我的 RP 中,
我有一个使用 Windows Server 2012 R2、ADFS 和 Sharepoint 2013 设置的测试环境。我可以使用 ADFS 作为声明身份提供程序成功登录到 Sharepoint 2
我认为默认超时是每半小时一次。 我想将其更改为 2 周。有人有任何想法吗? 这通常是从 STS 端还是客户端完成?表单例份验证是否也受到了阻碍,还是现在无关紧要? 最佳答案 我自己刚刚修复了这个问题,
我是一名优秀的程序员,十分优秀!