目前我正在使用DotNetOpenAuth CTP版本开发OAuth2授权服务器。我的授权服务器在asp.net MVC3中,它基于库提供的示例。一切正常,直到应用程序达到用户授权消费者客户端的程度。
我的OAuth控制器内部有一个操作,它负责授权过程,与示例中的等效操作非常相似:
[Authorize, HttpPost, ValidateAntiForgeryToken]
public ActionResult AuthorizeResponse(bool isApproved)
{
var pendingRequest = this.authorizationServer.ReadAuthorizationRequest();
if (pendingRequest == null)
{
throw new HttpException((int)HttpStatusCode.BadRequest, "Missing authorization request.");
}
IDirectedProtocolMessage response;
if (isApproved)
{
var client = MvcApplication.DataContext.Clients.First(c => c.ClientIdentifier == pendingRequest.ClientIdentifier);
client.ClientAuthorizations.Add(
new ClientAuthorization
{
Scope = OAuthUtilities.JoinScopes(pendingRequest.Scope),
User = MvcApplication.LoggedInUser,
CreatedOn = DateTime.UtcNow,
});
MvcApplication.DataContext.SaveChanges();
response = this.authorizationServer.PrepareApproveAuthorizationRequest(pendingRequest, User.Identity.Name);
}
else
{
response = this.authorizationServer.PrepareRejectAuthorizationRequest(pendingRequest);
}
return this.authorizationServer.Channel.PrepareResponse(response).AsActionResult();
}
每次程序到达此行:
this.authorizationServer.Channel.PrepareResponse(response).AsActionResult();
系统抛出一个异常,我研究过但没有成功。例外情况如下: LINQ to Entities中仅支持无参数构造函数和初始值设定项。
堆栈跟踪:http://pastebin.com/TibCax2t
我与样本做的唯一不同的是我使用了实体框架的代码第一种方法,我认为样本是使用自动生成实体的设计器完成的。
提前谢谢。
答案 0 :(得分:5)
如果你从这个例子开始,安德鲁所讨论的问题就在DatabaseKeyNonceStore.cs
。这两种方法都有一个例外:
public CryptoKey GetKey(string bucket, string handle) {
// It is critical that this lookup be case-sensitive, which can only be configured at the database.
var matches = from key in MvcApplication.DataContext.SymmetricCryptoKeys
where key.Bucket == bucket && key.Handle == handle
select new CryptoKey(key.Secret, key.ExpiresUtc.AsUtc());
return matches.FirstOrDefault();
}
public IEnumerable<KeyValuePair<string, CryptoKey>> GetKeys(string bucket) {
return from key in MvcApplication.DataContext.SymmetricCryptoKeys
where key.Bucket == bucket
orderby key.ExpiresUtc descending
select new KeyValuePair<string, CryptoKey>(key.Handle, new CryptoKey(key.Secret, key.ExpiresUtc.AsUtc()));
}
我已经解决了在查询之外移动初始化的问题:
public CryptoKey GetKey(string bucket, string handle) {
// It is critical that this lookup be case-sensitive, which can only be configured at the database.
var matches = from key in db.SymmetricCryptoKeys
where key.Bucket == bucket && key.Handle == handle
select key;
var match = matches.FirstOrDefault();
CryptoKey ck = new CryptoKey(match.Secret, match.ExpiresUtc.AsUtc());
return ck;
}
public IEnumerable<KeyValuePair<string, CryptoKey>> GetKeys(string bucket) {
var matches = from key in db.SymmetricCryptoKeys
where key.Bucket == bucket
orderby key.ExpiresUtc descending
select key;
List<KeyValuePair<string, CryptoKey>> en = new List<KeyValuePair<string, CryptoKey>>();
foreach (var key in matches)
en.Add(new KeyValuePair<string, CryptoKey>(key.Handle, new CryptoKey(key.Secret, key.ExpiresUtc.AsUtc())));
return en.AsEnumerable<KeyValuePair<string,CryptoKey>>();
}
我不确定这是最好的方法,但它确实有效!
答案 1 :(得分:1)
看起来您的ICryptoKeyStore
实现可能正在尝试直接存储CryptoKey
,但它不是与Entity框架兼容的类(由于没有公共默认构造函数)。相反,定义您自己的实体类以便在CryptoKey
中存储数据,并且您的ICryptoKeyStore
负责在两种数据类型之间进行转换以进行持久性和检索。