ServiceStack Global Request Filter Not Firing

2019-06-18 02:51发布

问题:

I have a global request filter for authentication as suggested by mythz (ServiceStack dev), in this SO Answer

My filter:

RequestFilters.Add((httpReq, httpResp, requestDto) =>
{
    if (!PublicRoutes.Contains(httpReq.PathInfo))
    {
        new AuthenticateAttribute().Execute(httpReq, httpResp, requestDto);
    }
});

The filter does not fire for me when I request ServiceStack Razor pages that inherit dynamic ViewPage

Example /Default.cshtml:

@inherits ViewPage
<!DOCTYPE html>
<html>
    <head>
        <title>HOME</title>
...
...
ETC

Down the bottom of the answer, in the comments, the question raiser suggests similar behaviour, but does not accurately describe how to reproduce, so I cannot see a solution.

Is there a solution? Did I do something incorrect?


UPDATE

I've discovered I can declare attributes on my page directly:

@using ServiceStack.ServiceInterface
@inherits ViewPage

@{
    new AuthenticateAttribute().Execute(Request, Response, this);
}
<!DOCTYPE html>
...
...
ETC

Or I'm sure I could create a class inherit ViewPage and run them in its Init method and use the new class on the Razor pages.

Both of those solutions seem extraneous and not very DRY, though.

回答1:

I ended up creating my own ViewPage class to achieve this and invoking the filters after the model has been set on the page:

public abstract class FilterViewPage<TModel> : ViewPage<TModel>
    where TModel : class
{
    public override void SetModel(object o)
    {
        base.SetModel(o);

        this.AppHost.RequestFilters.ForEach(action => action.Invoke(this.Request, this.Response, this.Model));
        this.AppHost.ResponseFilters.ForEach(action => action.Invoke(this.Request, this.Response, this.Model));
    }
}

I ensure only top-level pages inherit this, rather than applying it to partials so the filters only fire once.



回答2:

Well, other than simply checking if someone is logged in, much of the roles based stuff is handled for you based on attributes on the request DTO. For what you are doing there are a few options. The first is to have an empty dto that doesn't do anything:

[Route("/")]
[Authenticate]
public class Default { }

public class DefaultService : Service
{
    public object Get(Default req)
    {
         return new object();
    }
}

The second is a simple check if a user is logged in the razor page

@{
    var session = Cache.SessionAs<AuthUserSession>();
    if (!session.IsAuthenticated) throw new HttpException(403, "You are not logged in.");
}