适用于 Web 和移动设备的 ASP.NET Web API 社交身份验证

2024-05-26

我的问题有点复杂,所以请耐心等待我,因为我试图很好地阐明我正在努力解决的问题。

Goal

拥有一个 ASP.NET 网站,允许用户通过用户名/密码或也具有 API 的社交网站(Facebook、Twitter、Google 等)注册和登录。该 API 需要被锁定[Authorize]。 API 需要能够由可以通过用户名/密码或社交(Facebook、Twitter、Google 等)登录的移动客户端(Android、iOS 等)访问。

背景

因此,我创建的网站可以实现我的目标中的一两件事,但不能同时完成所有事情。网上有很多很好的例子,VS 项目中内置了一些例子,展示了如何让用户通过社交应用程序注册和登录,但它们仅适用于网站,不适用于移动设备。我做过一个网站,Android 应用程序使用用户名/密码通过该 API 进行身份验证,但不使用 OAuth 或社交凭证。

我开始使用这个page http://bitoftech.net/2014/08/11/asp-net-web-api-2-external-logins-social-logins-facebook-google-angularjs-app/作为参考,但我不知道如何接受它并使其适用于我的网站登录和我的移动应用程序登录。

This guy https://stackoverflow.com/questions/21065648/asp-net-web-api-2-how-to-login-with-external-authentication-services/21358918#21358918听起来很简单,但没有显示任何代码。

Question

是否有教程或 GitHub 示例可以帮助我实现目标?我基本上想要一个网站,人们可以在其中注册用户名/密码或使用他们的社交帐户,并让用户通过移动设备执行相同的操作(注册和登录)。移动设备基本上只使用 API 来推送/拉取数据,但我不确定如何将社交登录与我的 API 合并。我假设我需要使用 OAuth 并走这条路,但我找不到任何好的示例来展示如何在网络和移动设备上执行此操作。

或者也许正确的解决方案是让网页全部采用 cookie 身份验证,API 成为一个单独的“网站”,全部采用令牌身份验证,并且它们都绑定到同一个数据库?


我已经使用 ASP.NET Identity 在我自己的 ASP.NET MVC 应用程序中成功完成了这项任务,但随后遇到了您提到的问题:我也需要使用 Web API 来工作,以便我的移动应用程序可以进行本机交互。

我不熟悉您链接的文章,但在阅读完该文章后,我注意到许多工作和代码都是不必要的,并且使 ASP.NET Identity 中已存在的功能变得复杂。

以下是我的建议,我假设您使用的是 ASP.NET Identity V2,它相当于 MVC5 周围的软件包(而不是新的 MVC6 vNext)。这将允许您的网站和移动应用程序通过 API 通过本地登录名(用户名/密码)和外部 OAuth 提供商从您网站上的 MVC Web 视图以及通过移动应用程序的 Web API 调用进行身份验证:

步骤 1. 创建项目时,确保包含 MVC 和 Web API 所需的包。在 ASP.NET 项目选择对话框中,您可以选择复选框,确保 MVC 和 Web API 都被选中。如果您在创建项目时尚未执行此操作,我建议您创建一个新项目并迁移现有代码,而不是搜索并手动添加依赖项和模板代码。

步骤 2. 在 Startup.Auth.cs 文件中,您将需要代码来告诉 OWIN 使用 cookie 身份验证、允许外部登录 cookie 并支持 OAuth 不记名令牌(这是 Web API 调用的身份验证方式)。这些是我的工作项目代码库的相关摘录:

启动.Auth.cs

// Enable the application to use a cookie to store information for the signed in user
        // and to use a cookie to temporarily store information about a user logging in with a third party login provider
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/account/login"),
            Provider = new CookieAuthenticationProvider
            {
                // Enables the application to validate the security stamp when the user logs in.
                // This is a security feature which is used when you change a password or add an external login to your account.  
                OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                    validateInterval: TimeSpan.FromMinutes(30),
                    regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
            }
        });
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

// Configure the application for OAuth based flow
        PublicClientId = "self";
        OAuthOptions = new OAuthAuthorizationServerOptions
        {
            TokenEndpointPath = new PathString("/token"),
            Provider = new ApplicationOAuthProvider(PublicClientId),
            AuthorizeEndpointPath = new PathString("/api/account/externallogin"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
            //AllowInsecureHttp = false
        };

        // Enable the application to use bearer tokens to authenticate users
        app.UseOAuthBearerTokens(OAuthOptions);

 app.UseTwitterAuthentication(
            consumerKey: "Twitter API Key",
            consumerSecret: "Twitter API Secret");

        app.UseFacebookAuthentication(
            appId: "Facebook AppId",
            appSecret: "Facebook AppSecret");

在上面的代码中,我目前支持 Twitter 和 Facebook 作为外部身份验证提供商;但是,您可以使用 app.UserXYZProvider 调用和其他库添加其他外部提供程序,它们将与我在此处提供的代码即插即用。

步骤 3. 在 WebApiConfig.cs 文件中,您必须配置 HttpConfiguration 以禁止默认主机身份验证并支持 OAuth 持有者令牌。解释一下,这告诉您的应用程序区分 MVC 和 Web API 之间的身份验证类型,这样您就可以使用网站的典型 cookie 流程,同时您的应用程序将从 Web API 接受 OAuth 形式的承载令牌,而不会抱怨或其他问题。

WebApiConfig.cs

// Web API configuration and services
        // Configure Web API to use only bearer token authentication.
        config.SuppressDefaultHostAuthentication();
        config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));

步骤 4. 您需要一个用于 MVC 和 Web API 的 AccountController(或同等用途的控制器)。在我的项目中,我有两个 AccountController 文件,一个 MVC 控制器继承自 Controller 基类,另一个 AccountController 继承自位于 Controllers.API 命名空间中的 ApiController,以保持整洁。我正在使用 Web API 和 MVC 项目中的标准模板 AccountController 代码。以下是帐户控制器的 API 版本:

AccountController.cs(Controllers.API 命名空间)

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
using System.Web.Http.ModelBinding;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OAuth;

using Disco.Models.API;
using Disco.Providers;
using Disco.Results;

using Schloss.AspNet.Identity.Neo4j;
using Disco.Results.API;

namespace Disco.Controllers.API
{
    [Authorize]
    [RoutePrefix("api/account")]
    public class AccountController : ApiController
    {
        private const string LocalLoginProvider = "Local";
        private ApplicationUserManager _userManager;

        public AccountController()
        {            
        }

        public AccountController(ApplicationUserManager userManager,
            ISecureDataFormat<AuthenticationTicket> accessTokenFormat)
        {
            UserManager = userManager;
            AccessTokenFormat = accessTokenFormat;
        }

        public ApplicationUserManager UserManager
        {
            get
            {
                return _userManager ?? Request.GetOwinContext().GetUserManager<ApplicationUserManager>();
            }
            private set
            {
                _userManager = value;
            }
        }

        public ISecureDataFormat<AuthenticationTicket> AccessTokenFormat { get; private set; }

        // GET account/UserInfo
        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("userinfo")]
        public UserInfoViewModel GetUserInfo()
        {
            ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity);

            return new UserInfoViewModel
            {
                Email = User.Identity.GetUserName(),
                HasRegistered = externalLogin == null,
                LoginProvider = externalLogin != null ? externalLogin.LoginProvider : null
            };
        }

        // POST account/Logout
        [Route("logout")]
        public IHttpActionResult Logout()
        {
            Authentication.SignOut(CookieAuthenticationDefaults.AuthenticationType);
            return Ok();
        }

        // GET account/ManageInfo?returnUrl=%2F&generateState=true
        [Route("manageinfo")]
        public async Task<ManageInfoViewModel> GetManageInfo(string returnUrl, bool generateState = false)
        {
            IdentityUser user = await UserManager.FindByIdAsync(User.Identity.GetUserId());

            if (user == null)
            {
                return null;
            }

            List<UserLoginInfoViewModel> logins = new List<UserLoginInfoViewModel>();

            foreach (UserLoginInfo linkedAccount in await UserManager.GetLoginsAsync(User.Identity.GetUserId()))
            {
                logins.Add(new UserLoginInfoViewModel
                {
                    LoginProvider = linkedAccount.LoginProvider,
                    ProviderKey = linkedAccount.ProviderKey
                });
            }

            if (user.PasswordHash != null)
            {
                logins.Add(new UserLoginInfoViewModel
                {
                    LoginProvider = LocalLoginProvider,
                    ProviderKey = user.UserName,
                });
            }

            return new ManageInfoViewModel
            {
                LocalLoginProvider = LocalLoginProvider,
                Email = user.UserName,
                Logins = logins,
                ExternalLoginProviders = GetExternalLogins(returnUrl, generateState)
            };
        }

        // POST account/ChangePassword
        [Route("changepassword")]
        public async Task<IHttpActionResult> ChangePassword(ChangePasswordBindingModel model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            IdentityResult result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword,
                model.NewPassword);

            if (!result.Succeeded)
            {
                return GetErrorResult(result);
            }

            return Ok();
        }

        // POST account/SetPassword
        [Route("setpassword")]
        public async Task<IHttpActionResult> SetPassword(SetPasswordBindingModel model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            IdentityResult result = await UserManager.AddPasswordAsync(User.Identity.GetUserId(), model.NewPassword);

            if (!result.Succeeded)
            {
                return GetErrorResult(result);
            }

            return Ok();
        }

        // POST account/AddExternalLogin
        [Route("addexternallogin")]
        public async Task<IHttpActionResult> AddExternalLogin(AddExternalLoginBindingModel model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);

            AuthenticationTicket ticket = AccessTokenFormat.Unprotect(model.ExternalAccessToken);

            if (ticket == null || ticket.Identity == null || (ticket.Properties != null
                && ticket.Properties.ExpiresUtc.HasValue
                && ticket.Properties.ExpiresUtc.Value < DateTimeOffset.UtcNow))
            {
                return BadRequest("External login failure.");
            }

            ExternalLoginData externalData = ExternalLoginData.FromIdentity(ticket.Identity);

            if (externalData == null)
            {
                return BadRequest("The external login is already associated with an account.");
            }

            IdentityResult result = await UserManager.AddLoginAsync(User.Identity.GetUserId(),
                new UserLoginInfo(externalData.LoginProvider, externalData.ProviderKey));

            if (!result.Succeeded)
            {
                return GetErrorResult(result);
            }

            return Ok();
        }

        // POST account/RemoveLogin
        [Route("removelogin")]
        public async Task<IHttpActionResult> RemoveLogin(RemoveLoginBindingModel model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            IdentityResult result;

            if (model.LoginProvider == LocalLoginProvider)
            {
                result = await UserManager.RemovePasswordAsync(User.Identity.GetUserId());
            }
            else
            {
                result = await UserManager.RemoveLoginAsync(User.Identity.GetUserId(),
                    new UserLoginInfo(model.LoginProvider, model.ProviderKey));
            }

            if (!result.Succeeded)
            {
                return GetErrorResult(result);
            }

            return Ok();
        }

        // GET account/ExternalLogin
        [OverrideAuthentication]
        [HostAuthentication(DefaultAuthenticationTypes.ExternalCookie)]
        [AllowAnonymous]
        [Route("externallogin", Name = "ExternalLoginAPI")]
        public async Task<IHttpActionResult> GetExternalLogin(string provider, string error = null)
        {
            if (error != null)
            {
                return Redirect(Url.Content("~/") + "#error=" + Uri.EscapeDataString(error));
            }

            if (!User.Identity.IsAuthenticated)
            {
                return new ChallengeResult(provider, this);
            }

            ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity);

            if (externalLogin == null)
            {
                return InternalServerError();
            }

            if (externalLogin.LoginProvider != provider)
            {
                Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);
                return new ChallengeResult(provider, this);
            }

            ApplicationUser user = await UserManager.FindAsync(new UserLoginInfo(externalLogin.LoginProvider,
                externalLogin.ProviderKey));

            bool hasRegistered = user != null;

            if (hasRegistered)
            {
                Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);

                 ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(UserManager,
                    OAuthDefaults.AuthenticationType);
                ClaimsIdentity cookieIdentity = await user.GenerateUserIdentityAsync(UserManager,
                    CookieAuthenticationDefaults.AuthenticationType);

                AuthenticationProperties properties = ApplicationOAuthProvider.CreateProperties(user.UserName);
                Authentication.SignIn(properties, oAuthIdentity, cookieIdentity);
            }
            else
            {
                IEnumerable<Claim> claims = externalLogin.GetClaims();
                ClaimsIdentity identity = new ClaimsIdentity(claims, OAuthDefaults.AuthenticationType);
                Authentication.SignIn(identity);
            }

            return Ok();
        }

        // GET account/ExternalLogins?returnUrl=%2F&generateState=true
        [AllowAnonymous]
        [Route("externallogins")]
        public IEnumerable<ExternalLoginViewModel> GetExternalLogins(string returnUrl, bool generateState = false)
        {
            IEnumerable<AuthenticationDescription> descriptions = Authentication.GetExternalAuthenticationTypes();
            List<ExternalLoginViewModel> logins = new List<ExternalLoginViewModel>();

            string state;

            if (generateState)
            {
                const int strengthInBits = 256;
                state = RandomOAuthStateGenerator.Generate(strengthInBits);
            }
            else
            {
                state = null;
            }

            foreach (AuthenticationDescription description in descriptions)
            {
                ExternalLoginViewModel login = new ExternalLoginViewModel
                {
                    Name = description.Caption,
                    Url = Url.Route("ExternalLogin", new
                    {
                        provider = description.AuthenticationType,
                        response_type = "token",
                        client_id = Startup.PublicClientId,
                        redirect_uri = new Uri(Request.RequestUri, returnUrl).AbsoluteUri,
                        state = state
                    }),
                    State = state
                };
                logins.Add(login);
            }

            return logins;
        }

        // POST account/Register
        [AllowAnonymous]
        [Route("register")]
        public async Task<IHttpActionResult> Register(RegisterBindingModel model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var user = new ApplicationUser() { UserName = model.Email, Email = model.Email };

            IdentityResult result = await UserManager.CreateAsync(user, model.Password);

            if (!result.Succeeded)
            {
                return GetErrorResult(result);
            }

            return Ok();
        }

        // POST account/RegisterExternal
        [OverrideAuthentication]
        [HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
        [Route("registerexternal")]
        public async Task<IHttpActionResult> RegisterExternal(RegisterExternalBindingModel model)
        {
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }

            var info = await Authentication.GetExternalLoginInfoAsync();
            if (info == null)
            {
                return InternalServerError();
            }

            var user = new ApplicationUser() { UserName = model.Email, Email = model.Email };

            IdentityResult result = await UserManager.CreateAsync(user);
            if (!result.Succeeded)
            {
                return GetErrorResult(result);
            }

            result = await UserManager.AddLoginAsync(user.Id, info.Login);
            if (!result.Succeeded)
            {
                return GetErrorResult(result); 
            }
            return Ok();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing && _userManager != null)
            {
                _userManager.Dispose();
                _userManager = null;
            }

            base.Dispose(disposing);
        }

        #region Helpers

        private IAuthenticationManager Authentication
        {
            get { return Request.GetOwinContext().Authentication; }
        }

        private IHttpActionResult GetErrorResult(IdentityResult result)
        {
            if (result == null)
            {
                return InternalServerError();
            }

            if (!result.Succeeded)
            {
                if (result.Errors != null)
                {
                    foreach (string error in result.Errors)
                    {
                        ModelState.AddModelError("", error);
                    }
                }

                if (ModelState.IsValid)
                {
                    // No ModelState errors are available to send, so just return an empty BadRequest.
                    return BadRequest();
                }

                return BadRequest(ModelState);
            }

            return null;
        }

        private class ExternalLoginData
        {
            public string LoginProvider { get; set; }
            public string ProviderKey { get; set; }
            public string UserName { get; set; }

            public IList<Claim> GetClaims()
            {
                IList<Claim> claims = new List<Claim>();
                claims.Add(new Claim(ClaimTypes.NameIdentifier, ProviderKey, null, LoginProvider));

                if (UserName != null)
                {
                    claims.Add(new Claim(ClaimTypes.Name, UserName, null, LoginProvider));
                }

                return claims;
            }

            public static ExternalLoginData FromIdentity(ClaimsIdentity identity)
            {
                if (identity == null)
                {
                    return null;
                }

                Claim providerKeyClaim = identity.FindFirst(ClaimTypes.NameIdentifier);

                if (providerKeyClaim == null || String.IsNullOrEmpty(providerKeyClaim.Issuer)
                    || String.IsNullOrEmpty(providerKeyClaim.Value))
                {
                    return null;
                }

                if (providerKeyClaim.Issuer == ClaimsIdentity.DefaultIssuer)
                {
                    return null;
                }

                return new ExternalLoginData
                {
                    LoginProvider = providerKeyClaim.Issuer,
                    ProviderKey = providerKeyClaim.Value,
                    UserName = identity.FindFirstValue(ClaimTypes.Name)
                };
            }
        }

        private static class RandomOAuthStateGenerator
        {
            private static RandomNumberGenerator _random = new RNGCryptoServiceProvider();

            public static string Generate(int strengthInBits)
            {
                const int bitsPerByte = 8;

                if (strengthInBits % bitsPerByte != 0)
                {
                    throw new ArgumentException("strengthInBits must be evenly divisible by 8.", "strengthInBits");
                }

                int strengthInBytes = strengthInBits / bitsPerByte;

                byte[] data = new byte[strengthInBytes];
                _random.GetBytes(data);
                return HttpServerUtility.UrlTokenEncode(data);
            }
        }

        #endregion
    }
}

步骤 5. 您还需要创建一个 ApplicationOAuthProvider,以便服务器可以生成并验证 OAuth 令牌。 WebAPI 示例项目中提供了这一点。这是我的文件版本:

ApplicationOAuthProvider.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OAuth;
using Butler.Models;

using Schloss.AspNet.Identity.Neo4j;

namespace Butler.Providers
{
    public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
    {
        private readonly string _publicClientId;

        public ApplicationOAuthProvider(string publicClientId)
        {
            if (publicClientId == null)
            {
                throw new ArgumentNullException("publicClientId");
            }

            _publicClientId = publicClientId;
        }

        public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
        {
            var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();

            ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password);

            if (user == null)
            {
                context.SetError("invalid_grant", "The user name or password is incorrect.");
                return;
            }

            ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager,
               OAuthDefaults.AuthenticationType);
            ClaimsIdentity cookiesIdentity = await user.GenerateUserIdentityAsync(userManager,
                CookieAuthenticationDefaults.AuthenticationType);

            AuthenticationProperties properties = CreateProperties(user.UserName);
            AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
            context.Validated(ticket);
            context.Request.Context.Authentication.SignIn(cookiesIdentity);
        }

        public override Task TokenEndpoint(OAuthTokenEndpointContext context)
        {
            foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
            {
                context.AdditionalResponseParameters.Add(property.Key, property.Value);
            }

            return Task.FromResult<object>(null);
        }

        public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
        {
            // Resource owner password credentials does not provide a client ID.
            if (context.ClientId == null)
            {
                context.Validated();
            }

            return Task.FromResult<object>(null);
        }

        public override Task ValidateClientRedirectUri(OAuthValidateClientRedirectUriContext context)
        {
            if (context.ClientId == _publicClientId)
            {
                //Uri expectedRootUri = new Uri(context.Request.Uri, "/");

                //if (expectedRootUri.AbsoluteUri == context.RedirectUri)
                //{
                    context.Validated();
                //}
            }

            return Task.FromResult<object>(null);
        }

        public static AuthenticationProperties CreateProperties(string userName)
        {
            IDictionary<string, string> data = new Dictionary<string, string>
            {
                { "userName", userName }
            };
            return new AuthenticationProperties(data);
        }
    }
}

还包括 ChallengeResult,您的应用程序的 Web API 部分将使用它来处理外部登录提供程序提供的质询,以对您的用户进行身份验证:

ChallengeResult.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;

namespace Butler.Results
{
    public class ChallengeResult : IHttpActionResult
    {
        public ChallengeResult(string loginProvider, ApiController controller)
        {
            LoginProvider = loginProvider;
            Request = controller.Request;
        }

        public string LoginProvider { get; set; }
        public HttpRequestMessage Request { get; set; }

        public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        {
            Request.GetOwinContext().Authentication.Challenge(LoginProvider);

            HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
            response.RequestMessage = Request;
            return Task.FromResult(response);
        }
    }
}

使用这组代码,您将能够在 AccountController 的 API 版本上使用 HTTP GET 和 HTTP POST 路由来注册用户、使用用户名和密码登录以接收 Bearer 令牌、添加/删除外部登录、管理外部登录,最重要的是,对于您的问题,通过传入外部登录令牌进行身份验证,以换取您应用程序的 OAuth 不记名令牌。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

适用于 Web 和移动设备的 ASP.NET Web API 社交身份验证 的相关文章

随机推荐

  • Spark 中的 RDD 和 Dataframe 有什么区别? [复制]

    这个问题在这里已经有答案了 嗨 我对 apache Spark 比较陌生 我想了解 RDD 数据帧和数据集之间的区别 例如 我正在从 s3 存储桶中提取数据 df spark read parquet s3 output unattribu
  • preg_match():编译失败:字符类中偏移量的范围无效

    预先感谢您花时间帮助解决此问题 preg match 编译失败 session php 第 278 行偏移量 20 处的字符类范围无效 经过几个月的工作 在我们的服务器上进行 PHP 升级后 它突然停止工作了 这是代码 else Spruc
  • 通过 VBA MS_Access 将 MS Access 表导出为 dBase 5

    如何通过 VBA 将单个表导出为 dBase 5 文件 目前我正在使用这个VBA代码 DoCmd TransferDatabase acExport dBase IV DB Total acTable DB Total C Data Fal
  • 使用 ruby​​ Net::SSH 通过 sudo 读取远程文件

    我必须读取我有权 sudo 读取的远程文件的内容 猫 少或尾巴 我将在 Ruby 中执行此操作 因此我认为应该使用 Net SSH 来执行此操作 该文件是一个日志文件 因此可能会很大 这是我现在正在尝试的代码 require rubygem
  • Alfresco 更新文件 - 错误帖子

    我正在尝试更新 Alfresco 中的文件 我编写了以下代码 var csrf header Alfresco util CSRFPolicy getHeader var csrf token Alfresco util CSRFPolic
  • 在 UIView 中的贝塞尔曲线路径内像草图颜色一样绘制/绘制

    我正在 UIView 上的 UIBezierPath 的帮助下绘制形状图层 CAShapeLayer pathLayer CAShapeLayer layer pathLayer frame CGRectMake view frame or
  • 为什么非交互式批处理脚本认为我按下了 Control-C?

    因此 当输出日志中突然出现以下内容时 我的批处理脚本运行得很好 21 27 13 99 c apps w7lab scripting gt some command Error 3221225786 CTerminate batch job
  • 在子网站中使用邮政和 Hangfire

    我一直在尝试在我的 MVC5 站点上使用 Postal 当我将我的网页托管为子网站时 即http localhost 子站点 http localhost Subsite我收到错误 虚拟路径 映射到另一个应用程序 这是不允许的 我已经将其调
  • 将字符串值赋给指针

    char tempMonth char month 4 month 0 j month 1 a month 2 n month 3 0 如何将月份分配给 tempMonth 谢谢 最后如何打印出来 thanks In C month mon
  • 如果该值未在语句中的其他任何地方使用,为什么要使用 ++i 而不是 i++?

    我很清楚在 C 中 int someValue i array i otherValue 相比之下有不同的效果 int someValue i array i otherValue 但每隔一段时间我就会看到 for 循环中带有前缀增量的语句
  • wglCreateContextAttribsARB 函数崩溃

    我尝试写下代码 我有InitializeOGL 的代码 bool Ogl InitializeOGL bool vSync cout lt lt Init OpenGL lt
  • 按时间范围聚合

    我有一个数据集 其中包含日期 yyyy mm dd 和时间 h m s 以及温度 float 作为单独的列 我想通过平均函数聚合每天的温度值 问题是 我不知道如何查询时间属性来表示例如聚合 h m 0 5 s and h m 5 10 s
  • 作为计划任务运行 C# 应用程序

    我有一个 C 应用程序 设计为与 Windows 窗体一起运行 但现在需要作为计划任务运行 我对此遇到了问题 我认为这是因为它需要 无头 因为它不应该有用户环境的概念 该程序已编写为无人值守运行 因为它有一个 AUTO 参数 然后该参数将从
  • FullCalendar 重复事件创建重复项

    我正在为我的新网站实现一个日历 我从后端应用程序检索事件并使用 fullcalendar 在模式中显示结果 我还使用 fullcalendar 的重复功能 https fullcalendar io docs recurring event
  • 特定代码行的类似装饰器的语法

    链接主题 但不重复 装饰器对代码的特定行而不是整个方法进行计时 https stackoverflow com questions 30433910 decorator to time specific lines of the code
  • Bootstrap 4、导航栏固定顶部和其他粘顶元素

    这里是再现 https jsbin com lawafu edit html 输出 https jsbin com lawafu edit html output 这是一个错误吗 一个失误 一个问题 一个无法实现的想法 Before scr
  • 如何用该单词的单一版本替换重复单词

    我正在尝试使用 C 处理似乎使用语音转文本的文字记录 我遇到的一个主要问题是重复单词和 或短语 我很想使用正则表达式来替换它们 这里有些例子 我我我真的很想去 但是我不去 去不了 我真的很想使用正则表达式替换 所以它会变成这样 我真的很想去
  • XGBoost 产生预测结果和概率

    我可能正在文档中查看它 但我想知道 XGBoost 是否有办法生成结果的预测和概率 就我而言 我正在尝试预测多类分类器 如果我能返回Medium 88 那就太好了 分类器 中 预测概率 88 参数 params max depth 3 ob
  • C++ 类的互斥成员导致编译错误

    我不确定为什么当我向 myClass 添加互斥体成员时会发生这种情况 在本例中为 mu Error C2661 std tuple lt void thiscall MyNameSpace myClass void MyNameSpace
  • 适用于 Web 和移动设备的 ASP.NET Web API 社交身份验证

    我的问题有点复杂 所以请耐心等待我 因为我试图很好地阐明我正在努力解决的问题 Goal 拥有一个 ASP NET 网站 允许用户通过用户名 密码或也具有 API 的社交网站 Facebook Twitter Google 等 注册和登录 该