加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – ServiceStack API和ASP MVC身份验证有两种方式

发布时间:2020-12-15 05:41:13 所属栏目:百科 来源:网络整理
导读:我在解决通过ServiceStack服务html页面和Web服务的ASP MVC应用程序的体系结构时遇到了麻烦. 应用程序存在于基本URL中,例如“http://myapplication.com”,SS存在于“http://myapplication.com/api”中,因为它是配置两者的最简单方法. 总的来说一切正常,但是当
我在解决通过ServiceStack服务html页面和Web服务的ASP MVC应用程序的体系结构时遇到了麻烦.

应用程序存在于基本URL中,例如“http://myapplication.com”,SS存在于“http://myapplication.com/api”中,因为它是配置两者的最简单方法.

总的来说一切正常,但是当我到达授权和身份验证的一部分时,我就被困住了.

首先,我需要应用程序处理cookie,因为ASP通常会执行FormsAuthentication,并且当使用属性“Authorize”时,用户将通过登录屏幕并使用操作和控制器.这是典型的ASP,所以我没有问题,比如“http://myapplication.com/PurchaseOrders”.

另一方面,我的应用程序的客户端将从javascript使用我的Web服务API.在某些情况下,还会使用ServiceStack的“Authenticate”属性标记这些Web服务.例如,“http://myapplication.com/api/purchaseorders/25”必须验证用户是否可以查看该特定采购订单,否则发送401 Unauthorized,以便javascript可以处理这些情况并显示错误消息.

最后但并非最不重要的是,另一组用户将使用任何外部应用程序(可能是Java或.NET)通过令牌使用我的API.因此,我需要解决两种类型的身份验证,一种使用用户名和密码,另一种使用令牌并使其持久化,因此一旦第一次进行身份验证,下一次调用就可以更快地从API中解决.

这是我到目前为止的代码,我已经非常简单地说明了这个例子.

[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();
    }

至于身份验证提供程序,我正在使用此类

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的配置功能我正在设置我的自定义身份验证类以将其用作默认值.我想我应该创建另一个类并在此处添加它来处理令牌场景.

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

到目前为止,ServiceStack正在按预期工作.我可以通过用户名和密码向/ auth /凭证提交一个帖子并存储这些信息,所以下次调用服务时请求已经被授权,到目前为止很棒!

我需要知道的问题是如何调用(并且可能在SS中的某个位置)从我的帐户控制器登录的用户.如果您看到第一个代码块我试图调用Web服务(看起来我做错了)并且它可以工作,但是对任何Web服务的下一次调用看起来都是未经身份验证的.

请不要指向ServiceStack教程,过去两天我一直在那里,但仍然无法理解.

非常感谢提前.

解决方法

这是我通常使用的:

您可以使用以下代码替换“登录”操作方法:

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,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);
    }

……和插件:

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

…. Auth提供者类:

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

public class CustomBasicAuthProvider : BasicAuthProvider
{
    public override bool TryAuthenticate(IServiceBase authService,password);
    }
}

…最后,日志实用程序类

internal static class UserLogUtil
{
    public static bool LogUser(IServiceBase authService,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;
    }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读