具有 ASP.NET 身份的 Azure 移动应用程序

Azure Mobile App with ASP.NET Identity

我的情况是:我已经实现了具有身份和 Register/Login 操作的 ASP.NET WebAPI 应用程序。这是我的 ApiAccountController:

    [Authorize]
    [RoutePrefix("api/Account")]
    public class ApiAccountController : ApiController
    {
        private const string LocalLoginProvider = "Local";
        private ApplicationUserManager _userManager;

        public ApiAccountController()
        {
        }

        public ApiAccountController(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; }

        // POST api/Account/Register
        [AllowAnonymous]
        [Route("Register")]
        public async Task<IHttpActionResult> Register(RegisterViewModel model)
        {
            if (!ModelState.IsValid) return BadRequest(ModelState);
            var user = new ApplicationUser
            {
                Name = model.Nome,
                UserName = model.Email,
                Email = model.Email,
                CidadeId = model.CidadeId
            };
            var result = await UserManager.CreateAsync(user, model.Password);
            //return !result.Succeeded ? GetErrorResult(result) : Ok();
            if (result.Succeeded)
            {
                var code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
                var callbackUrl = new Uri(Url.Link("ConfirmEmailRoute", new { userId = user.Id, code }));
                await
                    UserManager.SendEmailAsync(user.Id, "Confirme Sua Conta",
                        "Para confirmar sua conta, clique <a href=\"" + callbackUrl + "\">Aqui!</a>");
                // Uri locationHeader = new Uri(Url.Link("GetUserById", new { id = user.Id }));
                return Ok();
            }
            return GetErrorResult(result);
        }

        [HttpGet]
        [AllowAnonymous]
        [Route("ConfirmEmail", Name = "ConfirmEmailRoute")]
        public async Task<IHttpActionResult> ConfirmEmail(Guid userId, string code)
        {
            if (string.IsNullOrEmpty(userId.ToString()) || string.IsNullOrWhiteSpace(code))
            {
                ModelState.AddModelError("", "Códigos necessários");
                return BadRequest(ModelState);
            }

            var result = await UserManager.ConfirmEmailAsync(userId, code);

            if (result.Succeeded)
                return Ok("Conta confirmada! Obrigado pela preferência, agora você pode utilizar nosso novo app");
            return GetErrorResult(result);
        }

        [HttpPost]
        [AllowAnonymous]
        [Route("Login")]
        public async Task<IHttpActionResult> Login(LoginUserViewModel model)
        {
            var request = HttpContext.Current.Request;
            var tokenServiceUrl = request.Url.GetLeftPart(UriPartial.Authority) + request.ApplicationPath + "/Token";
            using (var client = new HttpClient())
            {
                var requestParams = new List<KeyValuePair<string, string>>
                {
                    new KeyValuePair<string, string>("grant_type", "password"),
                    new KeyValuePair<string, string>("username", model.Username),
                    new KeyValuePair<string, string>("password", model.Password)
                };
                var requestParamsFormUrlEncoded = new FormUrlEncodedContent(requestParams);
                var tokenServiceResponse = await client.PostAsync(tokenServiceUrl, requestParamsFormUrlEncoded);
                var responseString = await tokenServiceResponse.Content.ReadAsStringAsync();
                if (tokenServiceResponse.StatusCode != HttpStatusCode.OK) return BadRequest();
                using (var tx = new TransactionScope(TransactionScopeOption.Required,
                    new TransactionOptions { IsolationLevel = IsolationLevel.ReadCommitted },
                    TransactionScopeAsyncFlowOption.Enabled))
                {
                    try
                    {
                        var user = UserManager.FindByName(model.Username);
                        if (user == null) return NotFound();
                        if (!user.EmailConfirmed) return BadRequest();
                        var json = JsonConvert.DeserializeObject<Dictionary<string, string>>(responseString);
                        user.AccessToken = json["access_token"];
                        UserManager.Update(user);
                        tx.Complete();
                        var vm = user.Adapt<UserLoggedViewModel>();
                        return Ok(vm);
                    }
                    catch
                    {
                        tx.Dispose();
                        throw;
                    }
                }
            }
        }


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

// Some actions was removed
        #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 (var error in result.Errors)
                        ModelState.AddModelError("", error);

                if (ModelState.IsValid)
                    return BadRequest();

                return BadRequest(ModelState);
            }

            return null;
        }

        #endregion
    }

这是我的Start.Auth配置

public partial class Startup
{
    public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }

    public static string PublicClientId { get; private set; }

    // For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
    public void ConfigureAuth(IAppBuilder app)
    {
        // Configure the db context, user manager and signin manager to use a single instance per request
        app.CreatePerOwinContext(ApplicationDbContext.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
        app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

        // 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
        // Configure the sign in cookie
        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, Guid>(
                        TimeSpan.FromMinutes(30),
                        (manager, user) =>
                            user.GenerateUserIdentityAsync(manager, DefaultAuthenticationTypes.ApplicationCookie),
                        id => Guid.Parse(id.GetUserId()))
            }
        });

        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

        // Enables the application to temporarily store user information when they are verifying the second factor in the two-factor authentication process.
        app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));

        // Enables the application to remember the second login verification factor such as phone or email.
        // Once you check this option, your second step of verification during the login process will be remembered on the device where you logged in from.
        // This is similar to the RememberMe option when you log in.
        app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);

        app.CreatePerOwinContext(ApplicationDbContext.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);

        // 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());
        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(7),
            RefreshTokenProvider = new RefreshTokenProvider(),
            // In production mode set AllowInsecureHttp = false
            AllowInsecureHttp = true
        };

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

        //var options = new AppServiceAuthenticationOptions()
        //{
        //    SigningKey = ConfigurationManager.AppSettings["SigningKey"],
        //    ValidAudiences = new[] {ConfigurationManager.AppSettings["ValidAudience"]},
        //    ValidIssuers = new[] {ConfigurationManager.AppSettings["ValidIssuer"]},
        //    TokenHandler = WebApiConfig.Configuration.GetAppServiceTokenHandler()
        //};

        //app.UseAppServiceAuthentication(options);

    }
}

WebAPIConfig

  public static class WebApiConfig
{
    //public static HttpConfiguration Configuration { get; private set; }
    public static void Register(HttpConfiguration config)
    {
        //Configuration = config;
        // Web API configuration and services
        // Configure Web API to use only bearer token authentication.
        config.SuppressDefaultHostAuthentication();
        config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
        config.EnableCors(new EnableCorsAttribute("*", "*", "*"));
        config.Formatters.Remove(config.Formatters.XmlFormatter);
        config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
        config.Formatters.JsonFormatter.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;

        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            "DefaultApi",
            "api/{controller}/{id}",
            new {id = RouteParameter.Optional}
        );

        var container = LightInjectContainer.Register();
        container.RegisterApiControllers();
        container.EnableWebApi(config);

        MapsterConfig.RegisterMappings();

       // Database.SetInitializer<SolumDbContext>(null);

       // new MobileAppConfiguration()
       //     .UseDefaultConfiguration()
       //     .ApplyTo(config);

    }
}

这是完全可用的,我将它与我的移动应用程序一起使用。但是,我想将 azure 离线同步与每用户数据同步结合使用。阅读 Google 上的一些文章,没有人确切说明如何在移动应用程序上使用身份。所有文章都说要阅读有关如何配置自定义登录提供程序的 Microsoft 文档,但它们都没有解释如何准确配置。我已经在这里阅读了一些帖子。有些人和我有同样的问题,但没有人有解决方案,一个如何使用这个的真实例子,或者我没有找到这个。

明确地说,我想将我的身份配置与 Azure 移动应用程序一起使用,并使用 azure 离线同步功能同步每个用户的数据。

有人可以帮我解决这个问题吗?

真的很感谢!

你需要阅读我的书的第 2 章 - http://aka.ms/zumobook