我有一个 Azure 移动服务,用于进行身份验证。我有一个自定义身份验证提供程序,一旦经过验证,它会返回以下信息:
JwtSecurityToken token = AppServiceLoginHandler.CreateToken(claims, signingKey, audience, issuer, null);
return Ok(new LoginResult()
{
AuthenticationToken = token.RawData,
User = signinedInUser,
StatusCode = System.Net.HttpStatusCode.OK
});
请注意,Timespan
设置为 null
,因此 token 不会过期。
然后,我向 AMS 发出后续请求,该 AMS 具有受 Authorize()
属性保护的 Controller 。然而,在我的任何断点被命中之前,这些都失败了,并出现 401 Unauthorized
响应。
我可以从 Azure 日志中看到发生这种情况的位置:
2017-10-05T12:18:54 PID[5524] Information Request, Method=POST, Url=https://mywebsite.azurewebsites.net/api/userinfo/update, Message='https://mywebsite.azurewebsites.net/api/userinfo/update'
2017-10-05T12:18:54 PID[5524] Information Message='UserInfo', Operation=DefaultHttpControllerSelector.SelectController
2017-10-05T12:18:54 PID[5524] Information Message='MyAMS.Controllers.UserInfoController', Operation=DefaultHttpControllerActivator.Create
2017-10-05T12:18:54 PID[5524] Information Message='MyAMS.Controllers.UserInfoController', Operation=HttpControllerDescriptor.CreateController
2017-10-05T12:18:54 PID[5524] Information Message='Selected action 'Update(User cpUser)'', Operation=ApiControllerActionSelector.SelectAction
2017-10-05T12:18:54 PID[5524] Information Message='Will use same 'JsonMediaTypeFormatter' formatter', Operation=JsonMediaTypeFormatter.GetPerRequestFormatterInstance
2017-10-05T12:18:54 PID[5524] Information Message='Selected formatter='JsonMediaTypeFormatter', content-type='application/json; charset=utf-8'', Operation=DefaultContentNegotiator.Negotiate
2017-10-05T12:18:54 PID[5524] Information Operation=AuthorizeAttribute.OnAuthorizationAsync, Status=401 (Unauthorized)
2017-10-05T12:18:54 PID[5524] Information Operation=UserInfoController.ExecuteAsync, Status=401 (Unauthorized)
2017-10-05T12:18:54 PID[5524] Information Response, Status=401 (Unauthorized), Method=POST, Url=https://mywebsite.azurewebsites.net/api/userinfo/update, Message='Content-type='application/json; charset=utf-8', content-length=unknown'
您可以看到 Authorize 属性正在设置 401 响应:
2017-10-05T12:18:54 PID[5524] Information Operation=AuthorizeAttribute.OnAuthorizationAsync, Status=401 (Unauthorized)
在客户端上,我填充了用户 ID 和身份验证 token :
this.client = new MobileServiceClient("https://mywebsite.azurewebsites.net");
var user = UserProfileService.GetCurrentSignedInUser();
client.CurrentUser = new MobileServiceUser(user.UserId.ToString())
{
MobileServiceAuthenticationToken = user.AuthToken
};
单步执行代码,我已确认 UserID 与用户的 ID 匹配,并且 AuthToken 与我的登录方法中返回的 AutToken 相同。
我还需要设置/执行其他操作才能启用对 Azure 移动服务的经过身份验证的请求吗?
谢谢
编辑 此后,我禁用了 Azure 中的所有其他身份验证提供程序,但这并没有解决问题。 我还在本地调试了代码,并且仅在部署到 Azure 时才在我的本地主机上运行时不会出现此问题。
最佳答案
根据您的代码,您正在为您的 Azure 移动应用程序使用自定义身份验证。正如阿德里安·霍尔 (Adrian Hall) 的书所述 Custom Authentication :
You must turn on Authentication / Authorization in your App Service. Set the Action to take when request is not authenticated to Allow Request (no action) and do not configure any of the supported authentication providers.
此外,我建议您只使用 postman 或 fiddler 来模拟针对 api 端点的请求,您需要添加一个新的 X-ZUMO-AUTH
header 并将值设置为 AuthToken
可以缩小这个问题的范围。另外,您可以在本地检查此问题,然后使用 token 模拟请求,看看您的代码是否可以在您这边工作,或者这是 azure 方面的问题。对于您的客户端,您可以使用 client.LoginAsync("custom", JObject.FromObject(user))
进行日志记录,而无需自行设置 CurrentUser
。更多详情,您可以按照adrian Hall的书来查看这个问题。
更新:
根据您的评论,我在我这边进行了测试。我在本地端和 azure 端都使用了 UseAppServiceAuthentication
中间件,并读取了 SigningKey
、ValidAudience
、ValidIssuer
从我的 Startup.MobileApp.cs
下的 web.config 中,如下所示:
//if (string.IsNullOrEmpty(settings.HostName))
{
app.UseAppServiceAuthentication(new AppServiceAuthenticationOptions
{
// This middleware is intended to be used locally for debugging. By default, HostName will
// only have a value when running in an App Service application.
SigningKey = ConfigurationManager.AppSettings["SigningKey"],
ValidAudiences = new[] { ConfigurationManager.AppSettings["ValidAudience"] },
ValidIssuers = new[] { ConfigurationManager.AppSettings["ValidIssuer"] },
TokenHandler = config.GetAppServiceTokenHandler()
});
}
注意:我在 azure 上启用了身份验证/授权。对于我的 CustomAuthController.cs,我使用 web.config 中的设置调用了 AppServiceLoginHandler.CreateToken 作为初始化的 UseAppServiceAuthentication 中间件。经过设置,它可以在我这边和 azure 那边按预期工作。
然后,我在部署到 Azure 端时禁用 UseAppServiceAuthentication
中间件。正如您提到的,我遇到了 401,我认为 token 验证可能会失败。我重新检查了Custom Authentication并发现您需要从 CustomAuthController.cs
下的环境变量初始化 SigningKey
、ValidAudience
、ValidIssuer
作为如下:
signingKey = Environment.GetEnvironmentVariable("WEBSITE_AUTH_SIGNING_KEY");
var website = Environment.GetEnvironmentVariable("WEBSITE_HOSTNAME");
audience = $"https://{website}/";
issuer = $"https://{website}/";
使用jwt.io为了解码 token ,iss
和 aud
已更改,但我发现它仍然会返回 401。我注意到我们都将生存期设置为 null
当调用AppServiceLoginHandler.CreateToken
时。我尝试用一个值(例如 TimeSpan.FromDays(30))来指定它,然后它可以在 azure 方面工作。
综上所述,此问题可能是由于调用AppServiceLoginHandler.CreateToken
时的lifetime
参数值导致的,您需要设置一个特定的值,而不是null
在 azure 的一侧。此外,您可以添加您的问题 here寻求专业解释。
此外,您的移动后端将使用 AppServiceTokenHandler.cs为了处理安全 token ,您可以在使用 UseAppServiceAuthentication
中间件时覆盖它并指定 TokenHandler
参数,然后您可以调试 token 验证处理。
关于azure - 向 Azure 移动服务发出请求时出现 401 未经授权,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46586383/