ServiceStack API和ASP MVC认证两种方式 [英] ServiceStack API and ASP MVC Authentication in two ways

查看:184
本文介绍了ServiceStack API和ASP MVC认证两种方式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个ASP MVC应用程序的麻烦解决架构,通过ServiceStack服务器HTML网页和Web服务。

I'm having trouble solving architecture of an ASP MVC application that servers html pages and web services through ServiceStack.

应用程序生命的基本URL,例如 http://myapplication.com 和SS住在的http://myapplication.com/api ,因为它是配置两个最简单的方法。

The application lives in the base url eg "http://myapplication.com" and SS lives in "http://myapplication.com/api" because it is the easiest way to configure both.

在一般的一切工作正常,但是当我到达的授权和认证的一部分,就是我卡住了。

In general everything works fine, but when I reached the part of the authorization and authentication, is where I'm stuck.

首先,我需要的应用程序句柄饼干作为ASP通常做FormsAuthentication通过,而且用户会去通过登录屏幕,并使用了属性授权的时候会消耗行动和控制器。这是典型的ASP,所以我没有与它的问题,如 http://myapplication.com/PurchaseOrders

For one, I need the application handle cookies as ASP normally do FormsAuthentication through, and users would go through a login screen and could consume actions and controllers when the attribute "Authorize" is used. This is typical of ASP, so I have no problem with it, such as "http://myapplication.com/PurchaseOrders".

在另一方面,我的应用程序的客户端将使用来自我的JavaScript的Web服务API。这些web服务也将标记在某些情况下,与ServiceStack的属性验证。例如,<一个href=\"http://myapplication.com/api/purchaseorders/25\">http://myapplication.com/api/purchaseorders/25\"必须验证用户是否可以查看特定采购订单,否则发送401未授权使JavaScript可以处理这些案件,并显示错误消息。

On the other hand, clients of my application will consume my web service api from javascript. Those web services will also be tagged in some cases with the attribute "Authenticate" of ServiceStack. For example "http://myapplication.com/api/purchaseorders/25" would have to validate if the user can view that particular purchase order, otherwise send a 401 Unauthorized so javascript can handle those cases and display the error message.

最后但并非最不重要的,另一组用户会利用我的API的一个记号,使用任何外部的应用程序(可能是Java或.NET)。所以,我需要通过令牌来解决两种认证的,一个使用用户名和密码,其他的,让他们持续性因此一旦它们已通过认证的第一次,下一次调用更快从API来解决。

Last but not least, another group of users will make use of my API by a token, using any external application (probably Java or .NET). So I need to solve two types of authentication, one using username and password, the other by the token and make them persistant so once they are authenticated the first time, the next calls are faster to solve from the API.

这是code,我到目前为止,我已经把很简单地做出明确的例子。

This is the code that I have so far, I've put it very simply to make clear the example.

    [HttpPost]
    public ActionResult Logon(LogOnModel model, string returnUrl)
    {
        if (ModelState.IsValid)
        {
            JsonServiceClient client = new JsonServiceClient("http://myapplication.com/api/");
            var authRequest = new Auth { provider = CredentialsAuthProvider.Name, UserName = model.UserName, Password = model.Password, RememberMe = model.RememberMe };
            try
            {

                var loginResponse = client.Send(authRequest);

                FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(loginResponse.UserName, false, 60);
                var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(ticket));
                Response.Cookies.Add(cookie);

                if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/") && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
                {
                    return Redirect(returnUrl);
                }
                else
                {
                    return RedirectToAction("Index", "Test");
                }

            }
            catch (Exception)
            {
                ModelState.AddModelError("", "Invalid username or password");
            }
        }

        return View();
    }

至于我使用这个类的身份验证提供者

As for the authentication provider I am using this class

    public class MyCredentialsAuthProvider : CredentialsAuthProvider
{
    public MyCredentialsAuthProvider(AppSettings appSettings)
        : base(appSettings)
    {

    }

    public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
    {
        //Add here your custom auth logic (database calls etc)
        //Return true if credentials are valid, otherwise false
        if (userName == "testuser" && password == "nevermind")
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    public override void OnAuthenticated(IServiceBase authService, IAuthSession session, IOAuthTokens tokens, Dictionary<string, string> authInfo)
    {
        //Fill the IAuthSession with data which you want to retrieve in the app eg:
        session.FirstName = "some_firstname_from_db";
        //...

        session.CreatedAt = DateTime.Now;
        session.DisplayName = "Mauricio Leyzaola";
        session.Email = "mauricio.leyzaola@gmail.com";
        session.FirstName = "Mauricio";
        session.IsAuthenticated = true;
        session.LastName = "Leyzaola";
        session.UserName = "mauricio.leyzaola";
        session.UserAuthName = session.UserName;
        var roles = new List<string>();
        roles.AddRange(new[] { "admin", "reader" });
        session.Roles = roles;

        session.UserAuthId = "uniqueid-from-database";

        //base.OnAuthenticated(authService, session, tokens, authInfo);

        authService.SaveSession(session, SessionExpiry);
    }
}

在APPHOST的配置功能,我设置我的自定义验证类使用它作为默认。我想我应该创建另一个类,并添加在这里为好,处理令牌的场景。

On the Configure function of AppHost I am setting my custom authentication class to use it as the default. I guess I should create another class and add it here as well, to handle the token scenario.

            Plugins.Add(new AuthFeature(() => new CustomUserSession(),
            new IAuthProvider[] {
                new MyCredentialsAuthProvider(appSettings)
            }, htmlRedirect: "~/Account/Logon"));

到目前为止,ServiceStack按预期工作。我可以提交一个帖子通过用户名和密码/认证/证书并存储这些信息,所以下一次调用一个服务请求已经授权,伟大为止!

So far, ServiceStack is working as expected. I can submit a post to /auth/credentials passing username and password and it stores this information, so next call to a service the request is already authorized, great so far!

我需要知道的问题是,如何调用(可能在SS设置的地方),这是从我的账户控制器注销用户。如果你看到code的首块我试图调用Web服务(看起来像我这样做是错误的)和它的作品,但对任何Web服务的下一次调用看起来未经认证的。

The question I need to know is how to call (and probably set somewhere in SS) the user that is logging in from my Account controller. If you see the first block of code I am trying to call the web service (looks like I am doing it wrong) and it works, but the next call to any web service looks unauthenticated.

请不要点我ServiceStack教程,我去过那里的最后两天,但还是无法弄清楚。

Please don't point me to ServiceStack tutorials, I've been there for the last two days and still cannot figure it out.

非常感谢在前进。

推荐答案

下面是我经常使用:

您可以替换登录的操作方法与下面的code:

You can replace the "Logon" action method with the code below:

    public ActionResult Login(LogOnModel model, string returnUrl)
    {
        if (ModelState.IsValid)
        {
            try
            {
                var authService = AppHostBase.Resolve<AuthService>();
                authService.RequestContext = System.Web.HttpContext.Current.ToRequestContext();
                var response = authService.Authenticate(new Auth
                {
                    UserName = model.UserName,
                    Password = model.Password,
                    RememberMe = model.RememberMe
                });

                // add ASP.NET auth cookie
                FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);

                return RedirectToLocal(returnUrl);
            }
            catch (HttpError)
            {
            }
        }

        // If we got this far, something failed, redisplay form
        ModelState.AddModelError("", "The user name or password provided is incorrect.");
        return View(model);
    }

...和插件:

...and the plugins:

           //Default route: /auth/{provider}
            Plugins.Add(new AuthFeature(() => new CustomUserSession(),
            new IAuthProvider[] {
                new CustomCredentialsAuthProvider(),
                new CustomBasicAuthProvider()
            }));

....的验证提供者类:

....the Auth provider classes:

public class CustomCredentialsAuthProvider : CredentialsAuthProvider
{  
    public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
    {
        return UserLogUtil.LogUser(authService, userName, password);
    }
}

public class CustomBasicAuthProvider : BasicAuthProvider
{
    public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
    {
        return UserLogUtil.LogUser(authService, userName, password);
    }
}

......最后,记录工具类

...finally, the logging utility class

internal static class UserLogUtil
{
    public static bool LogUser(IServiceBase authService, string userName, string password)
    {
        var userService = new UserService(); //This can be a webservice; or, you can just call your repository from here
        var loggingResponse = (UserLogResponse)userService.Post(new LoggingUser { UserName = userName, Password = password });

        if (loggingResponse.User != null && loggingResponse.ResponseStatus == null)
        {
            var session = (CustomUserSession)authService.GetSession(false);
            session.DisplayName = loggingResponse.User.FName.ValOrEmpty() + " " + loggingResponse.User.LName.ValOrEmpty();
            session.UserAuthId = userName;
            session.IsAuthenticated = true;
            session.Id = loggingResponse.User.UserID.ToString();

            // add roles and permissions
            //session.Roles = new List<string>();
            //session.Permissions = new List<string>();
            //session.Roles.Add("Admin);
            //session.Permissions.Add("Admin");

            return true;
        }
        else
            return false;
    }
}

这篇关于ServiceStack API和ASP MVC认证两种方式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆