无法在 Azure ASP.NET 后端对移动服务客户端进行身份验证



我有一个基于Visual Studio 2019模板的ASP.NET Web应用程序(.NET Framework),该应用程序具有使用单个用户帐户的自定义身份验证功能。

public void ConfigureAuth(IAppBuilder app)
{

// Configure the db context and user manager to use a single instance per request
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(10),
// In production mode set AllowInsecureHttp = false
AllowInsecureHttp = false
};
// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptions);
}

它适用于Postman。我能够获得标记为[授权]的令牌和访问控制器

我正在努力验证用于脱机同步的MobileServiceClient。客户端以这种方式初始化:

client = new MobileServiceClient(App.BackendUrl, new NativeMessageHandler());      
public async Task LoginAsync(string username, string password)
{
try
{
var token = await GetAuthenticationToken(username, password);
MobileServiceUser user = new MobileServiceUser(token.userName);
user.MobileServiceAuthenticationToken = token.Access_Token;
client.CurrentUser = user;
}
catch (InvalidGrantException) 
{
throw; 
}
catch (MobileServiceInvalidOperationException ex) 
{ 
throw; 
}
catch (Exception ex)
{
Crashes.TrackError(ex);
Debug.WriteLine(ex);
throw;
}
}
private async Task<AuthenticationToken> GetAuthenticationToken(string username, string password)
{
var keyValues = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("username", username),
new KeyValuePair<string, string>("password", password),
new KeyValuePair<string, string>("grant_type", "password")
};
HttpContent httpContent = new FormUrlEncodedContent(keyValues);
httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
try
{
var response = await client.InvokeApiAsync("/token",
httpContent,
HttpMethod.Post,
null,
null);
return JsonConvert.DeserializeObject<AuthenticationToken>(await response.Content.ReadAsStringAsync());
}
catch (MobileServiceInvalidOperationException exception)
{
if (string.Equals(exception.Message, "invalid_grant"))
throw new InvalidGrantException("invalid credentials",  exception);
else
throw;
}
} 

这里有一些测试代码:

public async Task InitializeAsync()
{
if (client?.SyncContext?.IsInitialized ?? false)
return;
// Create a reference to the local sqlite store
const string path = "syncstore.db";
var store = new MobileServiceSQLiteStore(path);
// Define the database schema
store.DefineTable<Brand>(); brandTable = new AzureCloudTable<Brand>(client, null);
// Actually create the store and update the schema
try
{
await client.SyncContext.InitializeAsync(store);
}
catch (Exception ex)
{
Crashes.TrackError(ex);
Debug.WriteLine(ex);
}
}
async Task Test(string username, string password)
{
await LoginAsync("Simulator8", " ");
await InitializeAsync();
//Test pull
try
{
await brandTable.PullAsync();
}
catch (Exception ex)
{
}
}

测试抛出异常:

+ex{Microsoft.WindowsAzure.MobileServices.MobileServiceInvalidOperationException:无法完成请求。(未经授权)位于Microsoft.WindowsAzure.MobileServices.MobileServiceHttpClient.ThrowInvalidResponse(System.Net.Http.HttpRequestMessage请求,System.Net.HHttp.HttpResponseMessage响应)[00x001d2],位于:0位于Microsoft.WindowsAzure.MobileServices.MobileServiceHttpClient.SendRequestAsync(System.Net.Http.HttpClient客户端、System.Net.HHttp.HttpRequestMessage请求、System.Boolean ensureResponseContent、System.Threading.CancellationToken cancellionToken)[00x00121],位于:0位于Microsoft.WindowsAzure.MobileServices.MobileServiceHttpClient.RequestAsync(System.Boolean UseHandlers,System.Net.Http.HttpMethod方法,System.String uriPathAndQuery,Microsoft.WindowsAzure.MobileServices.MobileService用户,System.String内容,System.Boolean ensureResponseContent,System.Collections.Generic.IDictionary2[TKey,TValue] requestHeaders, System.Threading.CancellationToken cancellationToken) [0x000f0] in <d385e67aff524dc7bd2d27425b9e81ae>:0 at Microsoft.WindowsAzure.MobileServices.MobileServiceTable.ReadAsync (System.String uriString, Microsoft.WindowsAzure.MobileServices.MobileServiceFeatures features) [0x0009c] in <d385e67aff524dc7bd2d27425b9e81ae>:0 at Microsoft.WindowsAzure.MobileServices.MobileServiceTable.ReadAsync (System.String query, System.Collections.Generic.IDictionary2[TKey,TValue]参数,Microsoft.WindowsAzure.MobileServices.MobileServiceFeatures功能)[00x00136],位于:0位于Microsoft.WindowsAzure.MobileServices.Sync.PullAction.ProcessTableAsync()[00x00134],位于:0位于Microsoft.WindowsAzure.MobileServices.Sync.TableAction.ExecuteAsync()[00x00251],位于:0位于Microsoft.WindowsAzure.MobileServices.Sync.MobileServiceSyncContext.ExecuteSyncAction(Microsoft.WindowsAzure.MobileServices.Sync.SyncAction操作)[0x0090],位于:0位于Microsoft.WindowsAzure.MobileServices.Sync.MobileServiceSyncContext.PullAsync(System.String tableName,Microsoft.WindowsAzure.MobileServices.Sync.MabileServiceTableKind tableKind,System.String queryId,System.String查询,Microsoft.WindowsAzure.Mobile Services.MobileService RemoteTableOptions选项,System.Collections.Generic.IDictionary2[TKey,TValue] parameters, System.Collections.Generic.IEnumerable1[T]relatedTables,Microsoft.WindowsAzure.MobileServices.MobileServiceObjectReader读取器,System.Threading.CancellationToken cancellionToken,Microsoft.WindowsAzure.MobilesServices.Sync.PullOptions PullOptions)[00x00361]in:0

  1. 如果我尝试在令牌中接收的令牌。Postman中的Access_Token
  2. 如果我尝试在没有[授权]的情况下与控制器同步,它会起作用
  3. 这是来自Azure日志流的消息:

*2020-04-15 18:20:10 xxxBACKENDxxx POST/token X-ARR-LOG-ID=c0abefa4-8754-47e2-966d-add7716e6a95 443-000.000.000 ZUMO/4.1+(lang=托管;+os=iOS;+os_version=13.3;+arch=MacOSX;+version=4.1.2.0)-xxxBACKENDxxx.azurewebsites.net 200 0 1825 1377 6312

2020-04-15 18:20:10 xxxBACKENDxxx GET/tables/Brand$filter=(更新日期%20ge%20datetimeoffset'2020-04-06T21%3A05%3A17.7200000%2B00%3A00')&orderby=updatedAt&skip=0&top=50&amp__includeDeleted=true&X-ARR-LOG-ID=287a5464-caad-43be-a3c5-25245e0f9f49 443模拟器8 000.000.000 ZUMO/4.1+(lang=托管;+os=iOS;+os_version=13.3;+arch=MacOSX;+version=4.1.2.0)ARRAfinity=62f587f816224cc3b867889be38db42f5322e4bdb4b71703dac6a261166d1545;+。AspNet.Cookies=rpLpkcIS9jfvK1FyWL6q-2_5ImjYFR9yB1ZiIPd4iiTxHAGL5A0CFu4qihtFZmu-GKKQzVQ5hoxReQQVpS7w2a0jnjvvvFL4dpe_wS9_7nfTxMTBuDXiKDHGZBakbd28UR1CWvyq7iFDUI8AakKj1zrM2uYz93kpg1WMQCSx-Z3tREike74S3LqUOCnRuPjil-wMqOzTJKL9JLQZ750MbQbT_-DLmj31qMa55emfGg UcSEM7I5ksMD2IIMvEeAEqwsp-XKyhp17utOTy5OepSqO8lxrGLng96GY-shVFBP4gDt7YP2bNS3RCtXkCWSOve4g7ckWDud8SAOk1KRpkj4k-B9ZogpAqc9Zuz0idTBruY3HZ3sTHCw__atnd8DQVwNQtEu8kX1Cz2WFbkO35GHOULA7VKyGiJu-LOpf2-SZPoNl12lqH0jdvT1kI32WF2RDKbQ2W9eyWzURHOsUvekcg5EOZUDeehXYfbo0-xxxBACKENDxxx.azurewebsites.net 401 0 543 2837 46*

用户名正确。但如果我不从LoginAsync调用GetAuthenticationToken并手动将令牌传递给用户。MobileServiceAuthenticationToken,则结果为:

//var token = await GetAuthenticationToken(username, password);
MobileServiceUser user = new MobileServiceUser(username);
user.MobileServiceAuthenticationToken = "bearer _F-Bd8_74ZGV2gmKN4dkjPIRgZh7keYa-nIKpbjvSlfBV9wP2Reu9Z9Spy1eqK47LRdnXxKlMsZ5...
client.CurrentUser = user;

2020-04-15 18:15:34 xxxBACKENDxxx GET/tables/Brand$filter=(更新日期为%20ge%20datetimeoffset‘2020-04-06T21%3A05%3A17.7200000%2B00%3A00’)&orderby=updatedAt&skip=0&top=50&amp__includeDeleted=true&X-ARR-LOG-ID=c3bcf13e-b270-4d58-897f-58cfb9727e56 443-000.000。ZUMO/4.1+(lang=托管;+os=iOS;+os_version=13.3;+arch=MacOSX;+version=4.1.2.0)-xxxBACKENDxxx.azurewebsites.net 401 0 543 2249 4625

所以设置用户似乎没有任何效果。

有什么想法为什么我不能验证我的MobileServiceClient吗?

我在这里找到了答案https://devblogs.microsoft.com/xamarin/personalized-experiences-with-azure-mobile-apps-authentication/

有必要在标题"Authorization"中发送一个令牌。我已经创建了一个用于HttpMessageHandler 的类

public class AuthHandler : DelegatingHandler
{
public IMobileServiceClient Client { get; set; }
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (Client.CurrentUser != null)
request.Headers.Add("Authorization", "bearer " + Client.CurrentUser.MobileServiceAuthenticationToken);
return base.SendAsync(request, cancellationToken);
}
}

我用它来初始化客户端

var handlers = new AuthHandler();
client = new MobileServiceClient(App.BackendUrl, handlers);
handlers.Client = client;

最新更新