【问题标题】:ServiceStack Authentication You don't need to use IHttpRequest.TryResolve<IHttpRequest> to resolve itselfServiceStack 身份验证您不需要使用 IHttpRequest.TryResolve<IHttpRequest> 自行解析
【发布时间】:2014-02-01 17:30:44
【问题描述】:

我正在尝试创建一个使用AuthenticateService 自动将用户登录到系统的服务。 (ServiceStack v4.0.8.0)

AppHost配置:

//Plugins
Plugins.Add(new RazorFormat());
Plugins.Add(new SessionFeature());
Plugins.Add(new AuthFeature(() => new CustomUserSession(),
            new IAuthProvider[] { new CustomCredentialsAuthProvider() }));

container.Register<ICacheClient>(new MemoryCacheClient());

我的CustomCredentialsAuthProvider

public class CustomCredentialsAuthProvider : CredentialsAuthProvider
{
    public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
    {
        // Custom Auth Logic
        // Return true if credentials are valid, otherwise false
        // bool isValid = Membership.ValidateUser(userName, password);
        return true;
    }

    public override void OnAuthenticated(IServiceBase authService, IAuthSession session, IAuthTokens tokens, Dictionary<string, string> authInfo)
    {
        base.OnAuthenticated(authService, session, tokens, authInfo);

        var loginManager = authService.TryResolve<LoginManager>();
        var loginInfo = loginManager.GetLoginInfo(session.UserAuthName);

        authService.SaveSession(loginInfo.CustomUserSession, SessionExpiry);
    }
}

我的TestService

public class TestService : Service
{       
    public object Any(Test request)
    {
        var response = new TestResponse();

        var authService = base.ResolveService<AuthenticateService>();            
        var authResponse = authService.Authenticate(new Authenticate
        {
            UserName = "user",
            Password = "password",
            RememberMe = false
        });           

        return response;
    }
}

当我运行它时,authService 会解析并且TryAuthenticate()OnAuthenticated() 方法中的代码执行时不会出错。

最后,当它返回响应并在浏览器中呈现页面时,我看到了这个错误:

“/”应用程序中的服务器错误。

你不需要使用 IHttpRequest.TryResolve 来解决 自己

描述:执行过程中发生了未处理的异常 当前的网络请求。请查看堆栈跟踪以获取更多信息 有关错误的信息以及它在代码中的来源。

异常详细信息:System.Exception:您不需要使用 IHttpRequest.TryResolve 自行解决

来源错误:

在执行过程中产生了一个未处理的异常 当前的网络请求。有关原产地和位置的信息 可以使用下面的异常堆栈跟踪来识别异常。

堆栈跟踪:

[Exception: You don't need to use IHttpRequest.TryResolve<IHttpRequest> to resolve itself]   
ServiceStack.Host.AspNet.AspNetRequest.TryResolve() +194   
ServiceStack.Formats.MarkdownFormat.GetPageName(Object dto, IRequestrequestContext) +94   
ServiceStack.Formats.MarkdownFormat.SerializeToStream(IRequest request, Object response, Stream stream) +284   
ServiceStack.Host.<>c__DisplayClass2.<GetResponseSerializer>b__1(IRequest httpReq, Object dto, IResponse httpRes) +92   
ServiceStack.HttpResponseExtensionsInternal.WriteToResponse(IResponse response, Object result, ResponseSerializerDelegate defaultAction,
IRequest request, Byte[] bodyPrefix, Byte[] bodySuffix) +2477

[AggregateException: One or more errors occurred.]   
System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions) +3650617   
System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken) +10816173   
System.Threading.Tasks.Task.Wait() +10
ServiceStack.Host.Handlers.HttpAsyncTaskHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +83   
System.Web.CallHandlerExecutionStep.OnAsyncHandlerCompletion(IAsyncResult ar) +129

版本信息:Microsoft .NET Framework 版本:4.0.30319; ASP.NET 版本:4.0.30319.18408

base.ResolveService&lt;T&gt; 应该已经在AuthenticateService 中设置了Request 上下文。但以防万一我也尝试过。

var authService = base.ResolveService<AuthenticateService>();
authService.Request = this.Request;

结果:同样的错误信息。

我也试过这个:

var authService = base.ResolveService<AuthenticateService>();
authService.Request = System.Web.HttpContext.Current.ToRequest();

结果:我没有收到任何错误,而且我看到了 TestResponse!另外,我取回了“ss-id”和“ss-pid”cookie。

我会在这里停下来,但是如果我向具有[Authenticate] 属性的服务发出请求,即使我有 cookie。我明白了:

未找到请求的处理程序:
Request.HttpMethod: 获取
Request.PathInfo: /login
Request.QueryString:ServiceStack.NameValueCollectionWrapper
Request.RawUrl:/login?redirect=http%3a%2f%2flocalhost%3a50063%2fBOP%2fbasic-info-2

所以它没有正确验证。

【问题讨论】:

    标签: authentication servicestack


    【解决方案1】:

    好的,v4.08 fixed in this commit 中似乎有一个错误。

    要解决此问题,您可以手动重置 ResponseContentType,例如:

    public class TestService : Service
    {       
        public object Any(Test request)
        {
            var response = new TestResponse();
    
            var authService = base.ResolveService<AuthenticateService>();            
            var authResponse = authService.Authenticate(new Authenticate
            {
                UserName = "user",
                Password = "password",
                RememberMe = false
            });           
    
            base.Request.ResponseContentType = MimeTypes.Html;
    
            return response;
        }
    }
    

    您可以在 v4.09+ 中忽略此解决方法,您 can now get on MyGet

    【讨论】:

    • 谢谢!我刚刚测试了临时解决方法,它解决了第一个错误。但是,在我调用 TestService 并成功登录用户后(我得到了 ss-id 和 ss-pid cookie),然后我尝试点击一个具有 [Authenticate] 属性的服务,我得到了未找到请求的处理程序因为它试图将我重定向到 /login。我认为最好将其分解为一个单独的问题,我接下来会做。
    • 这里是该问题第二部分的链接,其中包含更多详细信息。 stackoverflow.com/questions/21482929/…
    【解决方案2】:

    不确定这是否有帮助,但我以另一种方式进行了攻击。我创建了一个属性,你把它放在你的服务上,如下所示:

    [ServiceStackToAspNetAuthorize(Roles = "somerole")]
    

    它使用 asp.net 来确定您是否处于该角色,如果您已登录。这是属性代码。

    public class ServiceStackToAspNetAuthorizeAttribute : RequestFilterAttribute
    {
        private string _roles;
        private string[] _rolesSplit = new string[0];
    
        public string Roles
        {
            get { return _roles ?? String.Empty; }
            set
            {
                _roles = value;
                _rolesSplit = SplitString(value);
            }
        }
    
        public ServiceStackToAspNetAuthorizeAttribute(ApplyTo applyTo)
            : base(applyTo)
        {
            this.Priority = (int)RequestFilterPriority.Authenticate;
        }
    
        public ServiceStackToAspNetAuthorizeAttribute()
            : this(ApplyTo.All) { }
    
    
        public override void Execute(IRequest req, IResponse res, object requestDto)
        {
            if (!InternalAuthorize())
            {
                res.StatusCode = (int)HttpStatusCode.Unauthorized;
                res.EndRequest();
            }
        }
    
        private bool InternalAuthorize()
        {
            var context = HttpContext.Current;
            if (context != null)
            {
                var user = context.User;
                if (user != null)
                {
                    if (!user.Identity.IsAuthenticated)
                        return false;
                    if (_rolesSplit.Length > 0 && !_rolesSplit.Any(user.IsInRole))
                        return false;
                    return true;
                }
            }
            return false;
        }
    
        private static string[] SplitString(string original)
        {
            if (String.IsNullOrEmpty(original))
            {
                return new string[0];
            }
    
            var split = from piece in original.Split(',')
                        let trimmed = piece.Trim()
                        where !String.IsNullOrEmpty(trimmed)
                        select trimmed;
            return split.ToArray();
        }
    
    }
    

    【讨论】:

    • 我给了他们另一种方式来进行 Scott 的身份验证。如果它没有帮助他们,那很好,这只是另一种方式。
    • 我想,现在我重新阅读了这个问题,你是对的。但是,我回答了这个问题,因为这个问题的原始背景故事始于付费客户的私人服务堆栈论坛。在那里,他谈到了他试图在 SS 和 asp.net 会话之间映射安全性。
    • 我没有看到 OP 的响应,我只是看到对话移到了这里,并试图将它“移到”这里。否决票 - 不用担心,这对我来说无关紧要 :-) 谢谢 Scott。
    • 当然,不用担心。 SS见!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-18
    • 1970-01-01
    相关资源
    最近更新 更多