[英]How to use authentication cookie from WCF Authentication Service in an ASP.Net MVC application
Okay, I've had little luck finding any documentation or tutorials for my specific scenario. 好的,我没有找到适合我特定场景的任何文档或教程。
I have an ASP.Net MVC web application that will be using WCF services for everything including authentication and roles (via membership providers on the WCF backend). 我有一个ASP.Net MVC Web应用程序,它将使用WCF服务,包括身份验证和角色(通过WCF后端的成员资格提供程序)。
I've had no problem setting up the authentication services but it does not set a cookie in the web app. 我设置身份验证服务没有问题,但它没有在Web应用程序中设置cookie。 The docs for the Login method of the service indicate that wiring up the CreatingCookie Event is possible, but it does not have any affect on the client (I tried on the service side as well, again no affect).
该服务的Login方法的文档表明可以连接CreatingCookie事件,但它对客户端没有任何影响(我在服务端尝试过,再次没有影响)。 So I figured out how to capture the cookie .
所以我想出了如何捕获cookie 。 I have tried to manually set the auth cookie on the client, but so far it is not working;
我试图在客户端上手动设置auth cookie,但到目前为止它没有工作; decrypting fails due to padding, and setting the cookie value from the one given by the server is not readable by the client.
由于填充而导致解密失败,并且客户端无法读取服务器给出的cookie值。
Does anybody know how you are supposed to use the cookie that is generated by the WCF Authentication Service? 有人知道你应该如何使用WCF身份验证服务生成的cookie吗? Do I just assume the session is all managed on the WCF server and just check IsLoggedIn() on the service at every page load?
我是否只是假设会话全部在WCF服务器上进行管理,并在每次加载页面时检查服务上的IsLoggedIn()?
Thanks in advance. 提前致谢。
I have recently been trying to implement the same functionality you have described. 我最近一直在尝试实现您描述的相同功能。 I have managed to get it working with the following code:
我已设法使用以下代码:
private readonly AuthenticationServiceClient service = new AuthenticationServiceClient();
public void SignIn(string userName, string password, bool createPersistentCookie)
{
using (new OperationContextScope(service.InnerChannel))
{
// login
service.Login(userName, password, String.Empty, createPersistentCookie);
// Get the response header
var responseMessageProperty = (HttpResponseMessageProperty)
OperationContext.Current.IncomingMessageProperties[HttpResponseMessageProperty.Name];
string encryptedCookie = responseMessageProperty.Headers.Get("Set-Cookie");
// parse header to cookie object
var cookieJar = new CookieContainer();
cookieJar.SetCookies(new Uri("http://localhost:1062/"), encryptedCookie);
Cookie cookie = cookieJar.GetCookies(new Uri("http://localhost:1062/"))[0];
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);
if (null != ticket)
{
//string[] roles = RoleManager.GetRolesFromString(ticket.UserData);
HttpContext.Current.User = new GenericPrincipal(new FormsIdentity(ticket), null);
FormsAuthentication.SetAuthCookie(HttpContext.Current.User.Identity.Name, createPersistentCookie);
}
}
}
It does exactly what you have described the comment to your question. 它完全按照您描述的问题评论。
EDIT 编辑
I am posting here the Server-Side portion of this code for reference. 我在这里发布此代码的服务器端部分以供参考。
public class HttpResponseMessageInspector : BehaviorExtensionElement, IDispatchMessageInspector, IServiceBehavior
{
public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
{
HttpRequestMessageProperty httpRequest = request.Properties[HttpRequestMessageProperty.Name]
as HttpRequestMessageProperty;
if (httpRequest != null)
{
string cookie = httpRequest.Headers[HttpRequestHeader.Cookie];
if (!string.IsNullOrEmpty(cookie))
{
FormsAuthentication.Decrypt(cookie);
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(cookie);
string[] roles = PrincipalHelper.GetUserRoles(authTicket);
var principal = new BreakpointPrincipal(new BreakpointIdentity(authTicket), roles);
HttpContext.Current.User = principal;
}
// can deny request here
}
return null;
}
}
This works for me... First setup the authentication behavior of the host (here shown through code, but can also be done in config): 这对我有用...首先设置主机的身份验证行为(这里通过代码显示,但也可以在配置中完成):
ServiceAuthorizationBehavior author = Description.Behaviors.Find<ServiceAuthorizationBehavior>();
author.ServiceAuthorizationManager = new FormCookieServiceAuthorizationManager();
author.PrincipalPermissionMode = PrincipalPermissionMode.Custom;
author.ExternalAuthorizationPolicies = new List<IAuthorizationPolicy> { new CustomAuthorizationPolicy() }.AsReadOnly();
And then the helper classes 然后是辅助类
internal class FormCookieServiceAuthorizationManager : ServiceAuthorizationManager
{
public override bool CheckAccess(OperationContext operationContext)
{
ParseFormsCookie(operationContext.RequestContext.RequestMessage);
return base.CheckAccess(operationContext);
}
private static void ParseFormsCookie(Message message)
{
HttpRequestMessageProperty httpRequest = message.Properties[HttpRequestMessageProperty.Name] as HttpRequestMessageProperty;
if (httpRequest == null) return;
string cookie = httpRequest.Headers[HttpRequestHeader.Cookie];
if (string.IsNullOrEmpty(cookie)) return;
string regexp = Regex.Escape(FormsAuthentication.FormsCookieName) + "=(?<val>[^;]+)";
var myMatch = Regex.Match(cookie, regexp);
if (!myMatch.Success) return;
string cookieVal = myMatch.Groups["val"].ToString();
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(cookieVal);
Thread.CurrentPrincipal = new GenericPrincipal(new GenericIdentity(authTicket.Name), new string[0]);
}
}
internal class CustomAuthorizationPolicy : IAuthorizationPolicy
{
static readonly string _id = Guid.NewGuid().ToString();
public string Id
{
get { return _id; }
}
public bool Evaluate(EvaluationContext evaluationContext, ref object state)
{
evaluationContext.Properties["Principal"] = Thread.CurrentPrincipal;
evaluationContext.Properties["Identities"] = new List<IIdentity> { Thread.CurrentPrincipal.Identity };
return true;
}
public ClaimSet Issuer
{
get { return ClaimSet.System; }
}
}
And for when AspNetCompatibility is set, then FormCookieServiceAuthorizationManager
is slightly simpler: 并且当设置AspNetCompatibility时,
FormCookieServiceAuthorizationManager
稍微简单一些:
internal class FormCookieServiceAuthorizationManager : ServiceAuthorizationManager
{
public override bool CheckAccess(OperationContext operationContext)
{
Thread.CurrentPrincipal = HttpContext.Current.User;
return base.CheckAccess(operationContext);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.