我有一个ServiceStack应用程序,它与mvc5在一个Web项目中共存。 mvc5部分的唯一目的是托管一个控制器动作,该动作接收来自janrain的回调,用于javascript启动的社交登录。我也可以在SS服务请求中收到此回调,但后来我不知道如何重定向到从javascript上下文一直传递的returnUrl。即使我能够解决这个问题,我的问题仍然是一样的。
在控制器操作内部,一旦我验证了janrain提供的令牌解析为我系统中的用户,我需要手动告诉ServiceStack“嘿相信我 - 这个人是被授权的”。
我的所有搜索都引出了以下代码段的代码:
var authService = AppHostBase.Resolve<AuthService>();
authService.RequestContext = System.Web.HttpContext.Current.ToRequestContext();
var AuthResponse = authService.Authenticate(new Auth
{
provider = "credentials",
UserName = user.user_id,
Password = user.password,
RememberMe = true
});
我的第一个问题是我存储了哈希密码(我支持社交登录以及手动登录),所以我不知道用户的密码(我不应该)。
我的第二个问题是这个代码似乎只适用于SS 3.X而不是4.X.我需要一个在4.X中神秘地缺少的ServiceStack.ServiceInterface.dll。
是否有一种简短而精确的方法可以在服务器端手动验证具有SS的用户?
由于
编辑: 到目前为止,这就是我正在做的事情:(这不是最终的代码 - 我已经注释了一些我不知道该怎么做的事情):
public class UsernameOnlyAuthorizationService : Service
{
public object Post(UsernameOnlyLoginRequest request)
{
var authProvider = new UsernameOnlyAuthProvider();
authProvider.Authenticate(this, GetSession(), new Authenticate()
{
UserName = request.username,
Password = "NotRelevant",
RememberMe = true
});
return HttpResult.Redirect(request.returnUrl);
}
}
public class UsernameOnlyAuthProvider : CredentialsAuthProvider
{
public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
{
var authRepo = authService.TryResolve<IAuthRepository>().AsUserAuthRepository(authService.GetResolver());
ReferScienceDataContext db = authService.TryResolve<ReferScienceDataContext>();
var session = authService.GetSession();
IUserAuth userAuth;
var user = db.Users.FirstOrDefault(u => u.Username == userName);
if (user != null)
{
//AssertNotLocked(userAuth);
//session.PopulateWith(userAuth);
session.Id = user.Id.ToString();
session.UserName = user.Username;
session.FirstName = user.FirstName;
session.LastName = user.LastName;
session.IsAuthenticated = true;
session.UserAuthId = user.Id.ToString(CultureInfo.InvariantCulture);
session.ProviderOAuthAccess = authRepo.GetUserAuthDetails(session.UserAuthId)
.ConvertAll(x => (IAuthTokens)x);
return true;
}
return false;
}
}
从我的Janrain成功回调代码中我称之为:
HostContext.ResolveService<UsernameOnlyAuthorizationService>().Post(new UsernameOnlyLoginRequest() {username = user.Username, returnUrl= returnUrl});
这似乎工作得很好,但是,我无法记住我在浏览器关闭时的会话。我正在硬编码RememberMe = true - 为什么这不起作用?
答案 0 :(得分:2)
我会通过创建一个内部服务来执行此操作,您可以从MVC5控制器操作调用该服务,您只需要传递已经过身份验证的用户的用户名。
public class JanrainSuccessService : Service
{
public void CreateSessionFor(string username)
{
var repository = TryResolve<IAuthRepository>().AsUserAuthRepository(GetResolver());
var user = repository.GetUserAuthByUserName(username);
var session = GetSession();
session.PopulateWith(user);
session.IsAuthenticated = true;
session.UserAuthId = user.Id.ToString(CultureInfo.InvariantCulture);
session.ProviderOAuthAccess = repository.GetUserAuthDetails(session.UserAuthId).ConvertAll(x => (IAuthTokens)x);
}
}
此方法中的代码实际上与CredentialsAuthProvider
使用的代码相同,但具有不需要用户密码的优点。 (有关原始代码,请参阅TryAuthenticate
method here)
在MVC5控制器操作方法中,您需要调用:
HostContext.ResolveService<JanrainSuccessService>().CreateSessionFor(user.user_id);
这假设您有一个有效的用户存储库配置为匹配用户名。
您应该将代码更新为:
public class UsernameOnlyAuthorizationService : Service
{
public object Post(UsernameOnlyLoginRequest request)
{
var authProvider = new UsernameOnlyAuthProvider();
authProvider.Authenticate(this, GetSession(), new Authenticate()
{
UserName = request.username,
Password = "NotRelevant",
RememberMe = true
});
// Remember the session
base.Request.AddSessionOptions(SessionOptions.Permanent);
return HttpResult.Redirect(request.returnUrl);
}
}
public class UsernameOnlyAuthProvider : CredentialsAuthProvider
{
public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
{
var authRepo = authService.TryResolve<IAuthRepository>().AsUserAuthRepository(authService.GetResolver());
ReferScienceDataContext db = authService.TryResolve<ReferScienceDataContext>();
var session = authService.GetSession();
var user = db.Users.FirstOrDefault(u => u.Username == userName);
if (user == null)
return false;
session.Id = user.Id.ToString();
session.UserName = user.Username;
session.FirstName = user.FirstName;
session.LastName = user.LastName;
session.IsAuthenticated = true;
session.UserAuthId = user.Id.ToString(CultureInfo.InvariantCulture);
session.ProviderOAuthAccess = authRepo.GetUserAuthDetails(session.UserAuthId).ConvertAll(x => (IAuthTokens)x);
return true;
}
}