ServiceStack身份验证您不需要使用IHttpRequest.TryResolve <ihttprequest>来解决自身</ihttprequest>

时间:2014-01-30 21:37:11

标签: authentication servicestack

我正在尝试使用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<T>应该已经在Request中设置了AuthenticateService上下文。但万一我也试过这个。

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]属性的服务发出请求。我明白了:

  

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

所以它没有正确验证。

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

不确定这是否有帮助,但我以另一种方式攻击。我创建了一个属性,如下所示:

[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();
    }

}