在不发出身份验证请求的情况下手动强制身份验证用户

时间:2014-02-03 03:47:45

标签: servicestack

我有一个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 - 为什么这不起作用?

1 个答案:

答案 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;
    }
}