【问题标题】:Does the WebAuthenticationBroker work in Windows 8 Metro App post Release CandidateWebAuthenticationBroker 是否在 Windows 8 Metro App post Release Candidate 中工作
【发布时间】:2012-09-18 21:55:00
【问题描述】:

解决方案 我的工作解决方案可以在答案或我的更新二中找到。

1) 现在,为了在 localhost 上进行测试,请确保您已为 localhost 端口上的入站设置了 windows 防火墙。路由器上的端口转发(如果有)。

2) 然后你需要告诉 IIS Express,请求来自 localhost 外部是可以的: 找到 Documents\IISExpress\config 并编辑 applicationhost.config。在列表中找到您的站点并从绑定中删除 localhost

        <site name="S-Innovations.TrafficTheory.Web2" id="1591449597">
            <application path="/" applicationPool="Clr4IntegratedAppPool">
                <virtualDirectory path="/" physicalPath="G:\Documents\Visual Studio 2012\Projects\S-Innovations.TrafficTheory\S-Innovations.TrafficTheory.Web2" />
            </application>
            <bindings>
                <binding protocol="http" bindingInformation="*:909090:localhost" />
            </bindings>
        </site>

2a) ISS 需要以管理员身份运行,以管理员身份运行 Visual Studio 也以管理员身份启动 iss...

3) 找到您的 ip,www.myip.com 并将 ACS 返回 uri 更改为:http://90.90.90.90:909090/api/federation/

4) 更改网络经纪人以使用您的 ip:

        WebAuthenticationResult webAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(
WebAuthenticationOptions.None,
new Uri("https://traffictheory.accesscontrol.windows.net:443/v2/wsfederation?wa=wsignin1.0&wtrealm=http%3a%2f%2flocalhost%3a48451%2f"),
new Uri("http://99.99.99.99:909090/api/federation/end"));

一切都像这样对我有用。我得到了一个 hello world 作为令牌传递给我的 Metro 应用程序。

问题

我已经设置了 WCF 服务和 Metro 应用程序。 WCF 服务设置为使用 Azure ACS 进行身份验证。

我制作了一个可与 WebService 和 ACS 配合使用的控制台应用程序:

            static void Main(string[] args)
        {
            try
            {

                // First start the web project, then the client
                WebClient client = new WebClient();
                var token = RetrieveACSToken();
                client.Headers.Add("Authorization", token);
                client.Headers.Add("Content-type", "text/xml");
                var url = new Uri("http://traffictheory.azurewebsites.net/UserService.svc/Users");
                //var url = new Uri("http://localhost:4000/UserService.svc/Users");//
                Stream stream = client.OpenRead(url);
                StreamReader reader = new StreamReader(stream);
                String response = reader.ReadToEnd();
                Console.Write(response);

            }
            catch (Exception ex)
            {
                Console.Write(ex.Message);
            }
              Console.ReadLine();
        }

        private static string RetrieveACSToken()
        {
            var acsHostName     = ConfigurationManager.AppSettings.Get("ACSHostName");
            var acsNamespace    = ConfigurationManager.AppSettings.Get("ACSNamespace");
            var username        = ConfigurationManager.AppSettings.Get("ServiceIdentityUserName");
            var password        = ConfigurationManager.AppSettings.Get("ServiceIdentityCredentialPassword");
            var scope = "http://traffictheory.azurewebsites.net/"; 
            //var scope = "http://localhost:4000/";// 
            // request a token from ACS
            WebClient client = new WebClient();
            client.BaseAddress = string.Format("https://{0}.{1}", acsNamespace, acsHostName);
            NameValueCollection values = new
            NameValueCollection();
            values.Add("wrap_name", username);
            values.Add("wrap_password", password);
            values.Add("wrap_scope", scope);
            byte[] responseBytes =
            client.UploadValues("WRAPv0.9", "POST", values);
            string response =
            Encoding.UTF8.GetString(responseBytes);
            string token = response
            .Split('&')
            .Single(value =>
            value.StartsWith("wrap_access_token=",
            StringComparison.OrdinalIgnoreCase))
            .Split('=')[1];
            var decodedToken = string.Format("WRAP access_token=\"{0}\"", HttpUtility.UrlDecode(token));
            return decodedToken;
        }

当我想从 Metro 应用程序中使用它时,我现在面临两个问题。 第一个与服务无关,与 WebAuthenticationBroker 有关。

1) 当我使用

WebAuthenticationResult webAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(
                WebAuthenticationOptions.None,
                new Uri("https://s-innovations.accesscontrol.windows.net:443/v2/wsfederation?wa=wsignin1.0&wtrealm=http%3a%2f%2ftraffictheory.azurewebsites.net%2f"),
                new Uri("https://s-innovations.accesscontrol.windows.net")
            );

我可以使用 LiveID、Facebook 等登录。不是谷歌,因为 ACS 没有正确包含 ID。但我没有得到任何形式的代币或索赔。我只得到:

https://s-innovations.accesscontrol.windows.net/v2/wsfederation?wa=wsignin1.0 https://s-innovations.accesscontrol.windows.net/v2/facebook?cx=cHI9d3NmZWRlcmF0aW9uJn...cmFmZmljdGhlb3J5LmF6dXJld2Vic2l0ZXMubmV0JTJmJmlwPUZhY2Vib29rLTM1NTk5MjQ2NzgxNzc5OQ2&code=AQDagvqoXQ

我如何获得这部电影结尾处的声明: http://channel9.msdn.com/Events/BUILD/BUILD2011/SAC-858T 他的应用程序有效!

2) 上面显示的控制台应用程序在调用 API 时经过身份验证并获取要传递给服务的令牌,我如何从 Metro 应用程序中获取此令牌。

更新

我按照建议创建了控制器:

[HttpPost]
public ActionResult End()
{
    return Json("Hello World");
}

我已经设置了一个断点,看看它是否得到它。还没有命中。

    WebAuthenticationResult webAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(
WebAuthenticationOptions.None,
new Uri("https://traffictheory.accesscontrol.windows.net:443/v2/wsfederation?wa=wsignin1.0&wtrealm=http%3a%2f%2flocalhost%3a48451%2f"),
new Uri("http://localhost:909090/Federation/End"));

在我的依赖方应用程序中,我有

Realm http://localhost:909090/
Return Url: Nothing  (have tried http://localhost:909090/Federation/End )

响应数据现在包含:http://localhost:909090/Federation/End

更新 2

我还尝试使用 api 控制器,如您在另一篇文章中所示:

公共类 FederationController : ApiController {

public HttpResponseMessage Post()
{
    var response = this.Request.CreateResponse(HttpStatusCode.Redirect);
    response.Headers.Add("Location", "/api/federation/end?acsToken=" + ExtractBootstrapToken());

    return response;
}
public string Get()
{
    return "hello world";
}
protected virtual string ExtractBootstrapToken()
{
    return "Hello World";
}

}

现在登录屏幕只是挂起,并以您正在寻找的服务尚未准备好(或类似的东西)结束。

acs 返回网址http://localhost:48451/api/Federation

        WebAuthenticationResult webAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(
WebAuthenticationOptions.None,
new Uri("https://traffictheory.accesscontrol.windows.net:443/v2/wsfederation?wa=wsignin1.0&wtrealm=http%3a%2f%2flocalhost%3a909090%2f"),
new Uri("http://localhost:909090/api/federation/end"));

【问题讨论】:

    标签: c# .net windows-8 microsoft-metro


    【解决方案1】:

    WebAuthenticationBroker 只是继续浏览,直到下一个请求的页面是 callbackUri 参数指定的页面。此时它会返回最终的 URL 给您,因此如果您想取回任何内容,则需要在该 URL 中进行编码。

    在依赖方的 ACS 控制面板中,您需要指定位于您网站某处的返回 URL。例如https://traffictheory.azurewebsites.net/federationcallback。然后创建一个控制器来处理接受该 URL 的帖子。帖子将有一个表单字段wresult,这是一些包含从 ACS 返回的令牌的 xml。

    然后您可以通过重定向到https://traffictheory.azurewebsites.net/federationcallback/end?token={whatever you want to return} 将令牌发送回WebAuthenticationBroker

    然后,您需要将身份验证代理的使用更改为以下内容:

    var webAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(
                WebAuthenticationOptions.None,
                new Uri("https://s-innovations.accesscontrol.windows.net:443/v2/wsfederation?wa=wsignin1.0&wtrealm=http%3a%2f%2ftraffictheory.azurewebsites.net%2f"),
                new Uri("https://traffictheory.azurewebsites.net/federationcallback/end")
            );
    
    // The data you returned
    var token = authenticateResult.ResponseData.Substring(authenticateResult.ResponseData.IndexOf("token=", StringComparison.Ordinal) + 6);
    

    我用于处理身份验证回调帖子的控制器如下所示。

    public class FederationcallbackController : ApiController
    {
        public HttpResponseMessage Post()
        {
            var response = this.Request.CreateResponse(HttpStatusCode.Redirect);
            response.Headers.Add("Location", "/api/federationcallback/end?acsToken=" + ExtractBootstrapToken());
    
            return response;
        }
    
        protected virtual string ExtractBootstrapToken()
        {
            return HttpContext.Current.User.BootstrapToken();
        }
    }
    

    BootstrapToken() 扩展方法是wif.swt NuGet 包的一部分。默认情况下,WIF 不会将任何内容保存到引导令牌属性,您需要通过在 web.config 中的&lt;microsoft.identityModel&gt; 下的&lt;service&gt; 元素上包含saveBootstrapTokens="true" 属性来启用它。我的看起来像这样:

    <microsoft.identityModel>
        <service saveBootstrapTokens="true">
            <audienceUris>
                <add value="http://localhost:3949/" />
            </audienceUris>
            <federatedAuthentication>
                <wsFederation passiveRedirectEnabled="true" issuer="https://xyz.accesscontrol.windows.net/v2/wsfederation" realm="http://localhost:3949/" reply="http://localhost:3949/" requireHttps="false" />
                <cookieHandler requireSsl="false" path="/" />
            </federatedAuthentication>
            <issuerNameRegistry type="Microsoft.IdentityModel.Swt.SwtIssuerNameRegistry, Wif.Swt">
                <trustedIssuers>
                    <add name="https://readify.accesscontrol.windows.net/" thumbprint="{thumbprint}" />
                </trustedIssuers>
            </issuerNameRegistry>
            <securityTokenHandlers>
                <add type="Microsoft.IdentityModel.Swt.SwtSecurityTokenHandler, Wif.Swt" />
            </securityTokenHandlers>
            <issuerTokenResolver type="Microsoft.IdentityModel.Swt.SwtIssuerTokenResolver, Wif.Swt" />
        </service>
    </microsoft.identityModel>
    

    【讨论】:

    • 我做对了吗? ACS 站点将令牌发送到我的网站,然后我需要将令牌存储在那里直到经纪人要求它?
    • 我想我现在明白你的意思了,我尝试并用信息更新了问题。希望有意义
    • 所以我找到了解决方案。你是对的。但是要在 localhost 上测试所有这些,人们必须确保入站规则和 ACS 可以访问您的本地计算机。
    • 我正在使用 Microsoft.Identity 和我的 ((ClaimsIdentity)((ClaimsPrincipal)HttpContext.Current.User).Identity).BootstrapToken 不作为字符串传递。关于我应该如何序列化要发送的令牌的任何建议。
    • 您需要在 web.config 中设置一个属性。我已经用详细信息更新了这个答案。
    猜你喜欢
    • 2014-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-26
    • 2012-02-20
    相关资源
    最近更新 更多