我正在尝试使用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
所以它没有正确验证。
答案 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();
}
}