解
我的工作解决方案可以在答案中找到,也可以在我的更新二中找到。
1)现在,为了在localhost上进行测试,请确保已在localhost端口上设置了用于入站的Windows防火墙。路由器上的端口转发(如果有)。
2)然后,您需要告诉IIS Express,该请求来自本地主机的本地站点是可以的:
查找Documents \ IISExpress \ config并编辑applicationhost.config。在列表中找到您的站点,然后从绑定中删除本地主机。
<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 return uri更改为:
http://90.90.90.90:909090/api/federation/
4)更改webbroker以同时使用您的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"));
一切对我来说都是这样。我获得了一个问候世界作为令牌传递到我的地铁应用程序。
问题
我已经设置了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 App中使用它时遇到两个问题。
第一个与服务无关,与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等登录。不是Google,因为ACS没有正确包含ID。但是我没有得到任何形式的代币或索偿。我只会得到:
https://s-innovations.accesscontrol.windows.net/v2/wsfederation?wa=wsignin1.0
HTTPS://s-innovations.accesscontrol.windows.net/v2/facebook CX = cHI9d3NmZWRlcmF0aW9uJn ... cmFmZmljdGhlb3J5LmF6dXJld2Vic2l0ZXMubmV0JTJmJmlwPUZhY2Vib29rLTM1NTk5MjQ2NzgxNzc5OQ2&代码= 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"));
最佳答案
WebAuthenticationBroker
一直保持浏览状态,直到下一个请求的页面是callbackUri
参数指定的页面为止。到那时,它将返回最终URL给您,因此,如果您想取回任何东西,则需要将该URL编码。
在依赖方的ACS控制面板中,您需要指定站点上某个位置的返回URL。例如https://traffictheory.azurewebsites.net/federationcallback
。然后创建一个控制器来处理接受该URL的帖子。该帖子将具有一个表单域wresult
,该域是一些xml,其中将包含从ACS返回的令牌。
然后,您可以通过重定向到WebAuthenticationBroker
将令牌发送回https://traffictheory.azurewebsites.net/federationcallback/end?token={whatever you want to return}
然后,您需要将身份验证代理的用法更改为以下内容:
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中的saveBootstrapTokens="true"
下的<service>
元素上包含<microsoft.identityModel>
属性来启用它。我的看起来像这样:<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>
关于c# - WebAuthenticationBroker是否在Windows 8 Metro App发布候选版本中工作,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/12485665/