向 Azure 移动服务发出请求时出现 401 Unauthorized
401 Unauthorized when making request to Azure Mobile Service
我有一个用于身份验证的 Azure 移动服务。我有一个自定义身份验证提供程序,一旦验证,returns 将提供以下信息:
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
,因此令牌不会过期。
然后我向我的 AMS 发出后续请求,该 AMS 的控制器受 Authorize()
属性保护。但是,在我的任何断点被击中之前,这些都失败了 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 和授权令牌:
this.client = new MobileServiceClient("https://mywebsite.azurewebsites.net");
var user = UserProfileService.GetCurrentSignedInUser();
client.CurrentUser = new MobileServiceUser(user.UserId.ToString())
{
MobileServiceAuthenticationToken = user.AuthToken
};
通过代码,我已确认 UserID 与用户的匹配,并且 AuthToken 与我的登录方法中返回的 AutToken 相同。
我还需要 set/do 来启用对 Azure 移动服务的经过身份验证的请求吗?
谢谢
编辑
我已经禁用了 Azure 中的所有其他身份验证提供程序,但这并没有解决问题。
我还在本地调试了代码,问题没有出现在我的本地主机上 运行,只有当部署到 Azure 时才会出现。
根据您的代码,您正在为您的 Azure 移动应用程序使用自定义身份验证。正如阿德里安·霍尔关于 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
缩小这个问题。此外,您可以在本地检查此问题,然后使用令牌模拟请求以查看您的代码是否可以在您这边工作,或者这是天蓝色方面的问题。对于您的客户端,您可以使用 client.LoginAsync("custom", JObject.FromObject(user))
进行日志记录,而无需自己设置 CurrentUser
。更多详细信息,您可以按照 adrian hall 的书查看此问题。
更新:
根据大家的意见,我自己测试了一下。我在本地端和 Azure 端都使用了 UseAppServiceAuthentication
中间件,并在 [=20= 下从我的 web.config 中读取了 SigningKey
、ValidAudience
、ValidIssuer
]如下:
//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,我认为令牌验证可能会失败。我重新检查了 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
变了,但我发现还是return401。我注意到我们都设置了调用 AppServiceLoginHandler.CreateToken
时生命周期为 null
。我试图用一个值来指定它(例如 TimeSpan.FromDays(30)),然后它在天蓝色的一面工作。
综上所述,这个问题可能是调用AppServiceLoginHandler.CreateToken
时的lifetime
参数值引起的,你需要设置一个特定的值而不是Azure端的null
。此外,您可以添加您的问题here以获得专业解释。
此外,您的移动后端将使用 AppServiceTokenHandler.cs 来处理安全令牌,您可以覆盖它并在使用 UseAppServiceAuthentication
中间件时指定 TokenHandler
参数,然后您可以调试令牌验证处理。
我有一个用于身份验证的 Azure 移动服务。我有一个自定义身份验证提供程序,一旦验证,returns 将提供以下信息:
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
,因此令牌不会过期。
然后我向我的 AMS 发出后续请求,该 AMS 的控制器受 Authorize()
属性保护。但是,在我的任何断点被击中之前,这些都失败了 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 和授权令牌:
this.client = new MobileServiceClient("https://mywebsite.azurewebsites.net");
var user = UserProfileService.GetCurrentSignedInUser();
client.CurrentUser = new MobileServiceUser(user.UserId.ToString())
{
MobileServiceAuthenticationToken = user.AuthToken
};
通过代码,我已确认 UserID 与用户的匹配,并且 AuthToken 与我的登录方法中返回的 AutToken 相同。
我还需要 set/do 来启用对 Azure 移动服务的经过身份验证的请求吗?
谢谢
编辑 我已经禁用了 Azure 中的所有其他身份验证提供程序,但这并没有解决问题。 我还在本地调试了代码,问题没有出现在我的本地主机上 运行,只有当部署到 Azure 时才会出现。
根据您的代码,您正在为您的 Azure 移动应用程序使用自定义身份验证。正如阿德里安·霍尔关于 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
缩小这个问题。此外,您可以在本地检查此问题,然后使用令牌模拟请求以查看您的代码是否可以在您这边工作,或者这是天蓝色方面的问题。对于您的客户端,您可以使用 client.LoginAsync("custom", JObject.FromObject(user))
进行日志记录,而无需自己设置 CurrentUser
。更多详细信息,您可以按照 adrian hall 的书查看此问题。
更新:
根据大家的意见,我自己测试了一下。我在本地端和 Azure 端都使用了 UseAppServiceAuthentication
中间件,并在 [=20= 下从我的 web.config 中读取了 SigningKey
、ValidAudience
、ValidIssuer
]如下:
//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,我认为令牌验证可能会失败。我重新检查了 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
变了,但我发现还是return401。我注意到我们都设置了调用 AppServiceLoginHandler.CreateToken
时生命周期为 null
。我试图用一个值来指定它(例如 TimeSpan.FromDays(30)),然后它在天蓝色的一面工作。
综上所述,这个问题可能是调用AppServiceLoginHandler.CreateToken
时的lifetime
参数值引起的,你需要设置一个特定的值而不是Azure端的null
。此外,您可以添加您的问题here以获得专业解释。
此外,您的移动后端将使用 AppServiceTokenHandler.cs 来处理安全令牌,您可以覆盖它并在使用 UseAppServiceAuthentication
中间件时指定 TokenHandler
参数,然后您可以调试令牌验证处理。