作为这个问题的延续,我遇到了 dotnetopenauth 的问题。
我导航到我的依赖方代码并创建请求,但是当我的提供者收到请求OpenIdProvider.GetRequest()
时返回 null。我浏览了代码,据我所知,这是因为我的依赖方没有交付 openid 有效负载(request.form);但我不知道为什么会这样。
代码:
依赖方:
public ActionResult Authenticate(string RuserName = "")
{
UriBuilder returnToBuilder = new UriBuilder(Request.Url);
returnToBuilder.Path = "/OpenId/Authenticate";
returnToBuilder.Query = null;
returnToBuilder.Fragment = null;
Uri returnTo = returnToBuilder.Uri;
returnToBuilder.Path = "/";
Realm realm = returnToBuilder.Uri;
var response = openid.GetResponse();
if (response == null) {
if (Request.QueryString["ReturnUrl"] != null && User.Identity.IsAuthenticated) {
} else {
string strIdentifier = "http://localhost:3314/User/Identity/" + RuserName;
var request = openid.CreateRequest(
strIdentifier,
realm,
returnTo);
var fetchRequest = new FetchRequest();
request.AddExtension(fetchRequest);
request.RedirectToProvider();
}
} else {
switch (response.Status) {
case AuthenticationStatus.Canceled:
break;
case AuthenticationStatus.Failed:
break;
case AuthenticationStatus.Authenticated:
//log the user in
break;
}
}
return new EmptyResult();
}
提供者:
public ActionResult Index()
{
IRequest request = OpenIdProvider.GetRequest();
if (request != null) {
if (request.IsResponseReady) {
return OpenIdProvider.PrepareResponse(request).AsActionResult();
}
ProviderEndpoint.PendingRequest = (IHostProcessedRequest)request;
return this.ProcessAuthRequest();
} else {
//user stumbled on openid endpoint - 404 maybe?
return new EmptyResult();
}
}
public ActionResult ProcessAuthRequest()
{
if (ProviderEndpoint.PendingRequest == null) {
//there is no pending request
return new EmptyResult();
}
ActionResult response;
if (this.AutoRespondIfPossible(out response)) {
return response;
}
if (ProviderEndpoint.PendingRequest.Immediate) {
return this.SendAssertion();
}
return new EmptyResult();
}
日志:
RP:1)http://pastebin.com/Pnih3ND7 2)http://pastebin.com/eBzGun9y
提供者:http: //pastebin.com/YAUTBzHk
有趣的是,RP 日志说 localhost 是不受信任的......但是我将它添加到我的 web.config 中的白名单主机中,并且它昨天“工作”......
编辑:好的,这很奇怪。昨天我正在逐步浏览 DNOA 源,试图找出问题所在。我启用了 log4net,它创建了日志文件并将其留空。今天我再次设置了 log4net——它记录得很好,但是我遇到了一个没有意义的错误(见上文)。我也无法进入 DNOA 来源。我删除并重新添加了对 dotnetopenauth.dll 的引用,然后我与白名单主机的“原始错误”消失了,我能够进入源代码,但日志文件又是空白的。而且我仍然有 request.form 没有被填充的问题......
EDIT2:我的两个控制器都被命名为“OpenIdController”(在 RP 和 EP 上)。我的 RP 在 localhost:1903 上运行,我的端点在 localhost:3314 上运行。
EDIT3:在我进行更改后,您建议事情开始工作。RP 可以很好地执行发现,但是当它实际发出请求时我遇到了问题。
该行IRequest i_request = OpenIdProvider.GetRequest();
工作正常,但是当我尝试转换它时:IAuthenticationRequest iR = (IAuthenticationRequest)i_request;
它给了我以下错误:
System.InvalidCastException was unhandled by user code
Message=Unable to cast object of type 'DotNetOpenAuth.OpenId.Provider.AutoResponsiveRequest' to type 'DotNetOpenAuth.OpenId.Provider.IAuthenticationRequest'.
Source=Portal
StackTrace:
at Portal.Controllers.OpenIdController.Index() in Controllers\OpendIdController.cs:line 35
at lambda_method(Closure , ControllerBase , Object[] )
at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass42.<BeginInvokeSynchronousActionMethod>b__41()
at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.End()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass37.<>c__DisplayClass39.<BeginInvokeActionMethodWithFilters>b__33()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49()
这段代码在我发现相关的两个样本之间有点大杂烩。我想设置一个 SSO 类型环境,所以我使用的大部分代码来自\DotNetOpenAuth-4.1.0.12182\Samples\OpenIdWebRingSsoProvider\Code\Util.cs
(ProcessAuthenticationChallenge 函数)。但是,由于该函数需要一个IAuthenticationRequest
但 OpenIdProvider.GetRequest 返回一个,AutoResponsiveRequest
我想我可以强制转换它以使用IAuthenticationRequest
该类的属性和方法。显然我错了。
在这一点上,我不太确定如何处理事情。我应该使用 OpenIdProviderMVC 示例中的示例代码吗?关键是登录就像单点登录一样工作,并且从未真正提示用户输入 OpenId。我也只会有一个端点(尽管我会有多个 RP)。
这是最新 RP 日志的链接:http: //pastebin.com/enpwYqq3
EDIT4:我按照你的建议做了,并取得了一些进展。据我所知,我的 EP 收到响应并对其进行处理,但是当它重定向回领域 url 时,它会出错。
012-10-10 13:55:01,171 (GMT-4) [25] ERROR DotNetOpenAuth.Messaging - Protocol error: An HTTP request to the realm URL (http://localhost:1903/) resulted in a redirect, which is not allowed during relying party discovery.
Realm
与 相对的功能究竟是什么ReturnTo
?使用示例代码,Realm 最终成为http://localhost:1903/
并且 ReturnTo 最终成为http://localhost:1903/OpenId/Authenticate
看起来很好。为什么 EP 需要向领域提出请求?我原以为它应该只是在完成处理后将断言发送到 returnTo 。如果我手动将 Realm 设置为http://localhost:1903/OpenId/Authenticate
然后relyingParty.GetResponse()
返回 null。
我确实将我的应用程序设置为在有人访问基本 url ( http://localhost:1903
) 时重定向 - 我应该在那里运行什么代码来拦截 DNOA EP 请求?
新日志:
RP: http: //pastebin.com/L9K5Yft4
EP: http: //pastebin.com/kBPWiUxp
我还更新了问题开头的代码,以更好地反映我所做的更改。
EDIT5:领域是否必须是应用程序的实际基本 URL?也就是说,( http://localhost:1903
)? 鉴于现有的架构,很难删除重定向 - 我尝试将领域设置为基本 OpenId 控制器 ( http://localhost:1903/OpenId
),并且手动测试确实生成了 XRDS 文档。但是,应用程序似乎冻结了,EP 日志显示以下错误:
2012-10-10 15:17:46,000 (GMT-4) [24] ERROR DotNetOpenAuth.OpenId - Attribute Exchange extension did not provide any aliases in the if_available or required lists.