简体   繁体   English

Windows窗体的MVC WebAPI身份验证

[英]MVC WebAPI authentication from Windows Forms

I am attempting to make a Windows Forms application that plugs into some services exposed by ASP.NET MVC WebAPI, but am having a great deal of trouble with the authentication/login part. 我试图制作一个Windows窗体应用程序,插入ASP.NET MVC WebAPI公开的一些服务,但是在验证/登录部分遇到了很多麻烦。

I cannot seem to find an example that just demonstrates how to do this from Windows Forms, everything I find seems to be very convoluted and includes a lot of very deep plumbing, or seems targeted to other ASP.NET websites, and not windows forms. 我似乎无法找到一个只是演示如何从Windows窗体执行此操作的示例,我发现的所有内容似乎都非常复杂,并且包含很多非常深的管道,或者似乎针对其他ASP.NET网站,而不是Windows窗体。

Is there something I am missing? 有什么我想念的吗? Is this just not possible? 这不可能吗? Or is it just not intended? 或者它只是不打算? I've looked at things like this .NET WebApi Authentication that claim to do it, but I don't see how to use cookies from a Windows Forms standpoint. 我已经看过像.NET WebApi身份验证那样声称要这样做的东西,但我没有看到如何使用Windows窗体的角度来构建 cookie。 I've also gone over http://blogs.msdn.com/b/webdev/archive/2012/08/26/asp-net-web-api-and-httpclient-samples.aspx and still have had very little luck. 我也经历了http://blogs.msdn.com/b/webdev/archive/2012/08/26/asp-net-web-api-and-httpclient-samples.aspx并且仍然运气不佳。

Just create authentication token on server-side and store it in your database or even in cache. 只需在服务器端创建身份验证令牌,并将其存储在数据库甚至缓存中。 Then send this token with requests from your win forms application. 然后使用来自win表单应用程序的请求发送此令牌。 WebApi should check this token all the time. WebApi应始终检查此令牌。 It's good enough and you have full control over your auth process. 它足够好,您可以完全控制您的身份验证过程。

Let me share, how it works for me: 让我分享一下,它对我有用:

Object with Auth details: 具有Auth详细信息的对象:

public class TokenIdentity
{
    public int UserID { get; set; }

    public string AuthToken { get; set; }

    public ISocialUser SocialUser { get; set; }
}

Web API Auth Controller: Web API Auth控制器:

  public class AuthController : ApiController
    {
        public TokenIdentity Post(
            SocialNetwork socialNetwork,
            string socialUserID,
            [FromUri]string socialAuthToken,
            [FromUri]string deviceRegistrationID = null,
            [FromUri]DeviceType? deviceType = null)
        {
            var socialManager = new SocialManager();

            var user = socialManager.GetSocialUser(socialNetwork, socialUserID, socialAuthToken);

            var tokenIdentity = new AuthCacheManager()
                .Authenticate(
                    user,
                    deviceType,
                    deviceRegistrationID);

            return tokenIdentity;
        }
    }

Auth Cache Manager: Auth缓存管理器:

public class AuthCacheManager : AuthManager
    {
        public override TokenIdentity CurrentUser
        {
            get
            {
                var authToken = HttpContext.Current.Request.Headers["AuthToken"];
                if (authToken == null) return null;

                if (HttpRuntime.Cache[authToken] != null)
                {
                    return (TokenIdentity) HttpRuntime.Cache.Get(authToken);
                }

                return base.CurrentUser;
            }
        }

        public int? CurrentUserID
        {
            get
            {
                if (CurrentUser != null)
                {
                    return CurrentUser.UserID;
                }
                return null;
            }
        }

        public override TokenIdentity Authenticate(
            ISocialUser socialUser, 
            DeviceType? deviceType = null, 
            string deviceRegistrationID = null)
        {
            if (socialUser == null) throw new ArgumentNullException("socialUser");
            var identity = base.Authenticate(socialUser, deviceType, deviceRegistrationID);

            HttpRuntime.Cache.Add(
                identity.AuthToken,
                identity,
                null,
                DateTime.Now.AddDays(7),
                Cache.NoSlidingExpiration,
                CacheItemPriority.Default,
                null);

            return identity;
        }
    }

Auth Manager: 认证经理:

 public abstract class AuthManager
    {
        public virtual TokenIdentity CurrentUser
        {
            get
            {
                var authToken = HttpContext.Current.Request.Headers["AuthToken"];
                if (authToken == null) return null;

                using (var usersRepo = new UsersRepository())
                {
                    var user = usersRepo.GetUserByToken(authToken);

                    if (user == null) return null;

                    return new TokenIdentity
                    {
                        AuthToken = user.AuthToken,
                        SocialUser = user,
                        UserID = user.ID
                    };
                }
            }
        }

        public virtual TokenIdentity Authenticate(
            ISocialUser socialUser, 
            DeviceType? deviceType = null, 
            string deviceRegistrationID = null)
        {
            using (var usersRepo = new UsersRepository())
            {
                var user = usersRepo.GetUserBySocialID(socialUser.SocialUserID, socialUser.SocialNetwork);

                user = (user ?? new User()).CopyFrom(socialUser);

                user.AuthToken = System.Guid.NewGuid().ToString();

                if (user.ID == default(int))
                {
                    usersRepo.Add(user);
                }

                usersRepo.SaveChanges();

                return new TokenIdentity
                {
                    AuthToken = user.AuthToken,
                    SocialUser = user,
                    UserID = user.ID
                };
            }
        }
    }

Global Action Filter: 全局动作过滤器:

public class TokenAuthenticationAttribute : System.Web.Http.Filters.ActionFilterAttribute
{
    public override void OnActionExecuting(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
        if (actionContext.Request.RequestUri.AbsolutePath.Contains("api/auth"))
        {
            return;
        }

        var authManager = new AuthCacheManager();

        var user = authManager.CurrentUser;

        if (user == null)
        {
            throw new HttpResponseException(HttpStatusCode.Unauthorized);
        }

        //Updates the authentication
        authManager.Authenticate(user.SocialUser);
    }
}

Global.asax registration: Global.asax注册:

GlobalConfiguration.Configuration.Filters.Add(new AuthFilterAttribute());

The idea is that AuthCacheManager extends AuthManager and decorates it's methods and properties. 我们的想法是AuthCacheManager扩展AuthManager并修饰它的方法和属性。 If there is nothing inside cache then go check database. 如果缓存中没有任何内容,那么去检查数据库。

You could use token based authentication. 您可以使用基于令牌的身份验证 Here's a great article illustrating how you could write a custom action filter that uses RSA public/private cryptography. 这是一篇很棒的文章,说明如何编写使用RSA公共/私有加密的自定义操作过滤器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM