【问题标题】:MVC WebAPI authentication from Windows Forms来自 Windows 窗体的 MVC WebAPI 身份验证
【发布时间】:2023-04-10 17:39:01
【问题描述】:

我正在尝试制作一个 Windows 窗体应用程序,该应用程序可以插入一些由 ASP.NET MVC WebAPI 公开的服务,但在身份验证/登录部分遇到了很多麻烦。

我似乎找不到仅演示如何从 Windows 窗体执行此操作的示例,我发现的所有内容似乎都非常复杂,并且包含许多非常深入的管道,或者似乎针对其他 ASP.NET 网站,而不是窗体。

我有什么遗漏吗?这是不可能的吗?或者它只是不是故意的?我看过像.NET WebApi Authentication 这样声称可以做到的事情,但我不知道如何从 Windows 窗体的角度使用 cookie。我也去过http://blogs.msdn.com/b/webdev/archive/2012/08/26/asp-net-web-api-and-httpclient-samples.aspx,但运气仍然很差。

【问题讨论】:

    标签: c# winforms asp.net-web-api


    【解决方案1】:

    只需在服务器端创建身份验证令牌并将其存储在您的数据库甚至缓存中。然后将此令牌与来自您的 win forms 应用程序的请求一起发送。 WebApi 应该一直检查这个令牌。这已经足够好了,您可以完全控制您的身份验证过程。

    让我分享一下,它是如何为我工作的:

    带有身份验证详细信息的对象:

    public class TokenIdentity
    {
        public int UserID { get; set; }
    
        public string AuthToken { get; set; }
    
        public ISocialUser SocialUser { get; set; }
    }
    

    Web API 验证控制器:

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

    授权缓存管理器:

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

    授权管理器:

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

    全局操作过滤器:

    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 注册:

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

    这个想法是 AuthCacheManager 扩展 AuthManager 并装饰它的方法和属性。如果缓存中没有任何内容,请检查数据库。

    【讨论】:

    • 您有代码示例吗?达林的很有趣,但你可能有更好的。
    • @hawbsl 我已经更新了我的答案。希望您能在那里找到任何有趣的东西,并对您的应用有所了解。
    • +50 +10 我还没有尝试过,但它看起来是一个很好的路线图
    • 感谢@hawbsl,它是工作应用程序的一部分(如您所见)。很高兴为您提供帮助!
    【解决方案2】:

    您可以使用基于令牌的身份验证。这是 great article 说明如何编写使用 RSA 公用/私有加密的自定义操作过滤器。

    【讨论】:

    • 我有点困惑。我在 Windows 窗体中没有操作过滤器。
    • 我指的是登录身份验证,而不是真正的加密。
    • 是的,就是这样。请阅读我在答案中链接到的文章,并尝试使用其中说明的代码。
    • 这仍然没有多大意义。所有这些都假设您已经对用户进行了身份验证。这就是我遇到问题的部分。
    • 对,但我仍然不明白的是经过身份验证的用户会传递哪些数据。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-19
    • 2017-08-13
    • 2010-12-20
    • 1970-01-01
    • 2013-01-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多