我有一个用C#编写的通用处理程序 - 这被称为OAuth2流程的一部分,用于通过Google验证用户。
识别出正确的用户后,我需要设置一个cookie,以便网站的其余部分可以识别用户。
问题是为了设置处理程序实现IRequiresSessionState所需的会话变量 - 当我这样做时 - 然后OAuth 2进程失败并出现以下错误。
收到的回调和客户端状态与预期值不匹配的意外OAuth授权响应
所以我可以实现OAuth或编写会话变量,但不能同时执行这两个操作。我可以让OAuth调用第一页,但然后可以在URL中看到代码(我宁愿不这样做 - 因为它为任何邪恶的人提供了破坏安全性的线索)。我可以得到一个页面来调用处理程序,返回JSON来识别用户并让页面本身设置会话变量,然后转到第一页 - 但是这个页面没有内容,还需要两个跳 - 所以如何你有一个基本上是空的HTML页面,或者设置会话而没有IRequiresSessionState打破会话。
OAuth处理程序的代码如下所示。
public void ProcessRequest(HttpContext context)
{
NetworkParameters networkParameters = null;
NetworkParameter networkParameter = null;
WebServerClient consumer = null;
AuthorizationServerDescription server = null;
IAuthorizationState grantedAccess = null;
LoginResult loginResult = null;
String code = String.Empty;
String result = String.Empty;
String consumerSecret = String.Empty;
String consumerKey = String.Empty;
String securityCookieVal = String.Empty;
Uri tokenEndpoint = null;
Uri authorizationEndpoint = null;
Profile profile = null;
Profile profile2 = null;
Profiles profiles = null;
NetworkAuthorizations authorizations = null;
NetworkAuthorization na = null;
try
{
loginResult = new LoginResult();
tokenEndpoint = new Uri("https://accounts.google.com/o/oauth2/token");
authorizationEndpoint = new Uri("https://accounts.google.com/o/oauth2/auth?access_type=offline&approval_prompt=auto");
// retrieve network parameters
networkParameters = new NetworkParameters(Properties.Settings.Default.DatabaseConnection);
authorizations = new NetworkAuthorizations(Properties.Settings.Default.DatabaseConnection);
networkParameter = networkParameters.Select("GOOGLE");
code = context.Request["code"];
consumerKey = networkParameter.ClientId;
consumerSecret = networkParameter.ClientSecret;
// set up request
server = new AuthorizationServerDescription();
server.AuthorizationEndpoint = authorizationEndpoint;
server.TokenEndpoint = tokenEndpoint;
server.ProtocolVersion = ProtocolVersion.V20;
// initialise webserver client
consumer = new WebServerClient(server, consumerKey, consumerSecret);
consumer.ClientCredentialApplicator = ClientCredentialApplicator.PostParameter(consumerSecret);
// retrieve access
grantedAccess = consumer.ProcessUserAuthorization();
profile = GoogleServices.GetProfile(grantedAccess.AccessToken);
profiles = new Profiles(Properties.Settings.Default.DatabaseConnection);
profile2 = profiles.SelectByNetworkId(profile.Network, profile.NetworkId);
if (profile2 == null)
{
na = new NetworkAuthorization()
{
Id = Guid.NewGuid().ToString(),
AccessToken = grantedAccess.AccessToken,
ExpirationDate = (DateTime)grantedAccess.AccessTokenExpirationUtc,
IssueDate = (DateTime)grantedAccess.AccessTokenIssueDateUtc,
RefreshToken = grantedAccess.RefreshToken,
Network = profile.Network,
NetworkId = profile.NetworkId
};
authorizations.Insert(na);
profiles.Insert(profile);
}
loginResult.UserId = profile.NetworkId;
}
catch (System.Exception e)
{
loginResult.Status.Status = "ERROR";
loginResult.Status.Message = e.Message;
}
finally
{
context.Response.ContentType = "application/json";
context.Response.Write(JsonConvert.SerializeObject(loginResult));
}
}
答案 0 :(得分:0)
不是真正的答案 - 但我通过将随机生成的ID传递到网站的第一页并将其存储在用户身上来解决这个问题 - 在调用第一页时设置了cookie。
在查询字符串中发送此类信息并不十分安全,但在原型中就足够了 - 最终计划是使用Node.js,这不会成为问题。