Angularjs CORS飞行前请求响应Azure托管Web API中的302重定向
场景: Request OPTIONS /api/items HTTP/1.1 Host: webapi.azurewebsites.net Connection: keep-alive Access-Control-Request-Method: GET Access-Control-Request-Headers: accept, authorization Origin: https://mvcapp.azurewebsites.net User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.99 Safari/537.36 Accept: */* Referer: https://mvcapp.azurewebsites.net/ Response HTTP/1.1 302 Found Content-Length: 504 Location: https://login.windows.net/{authority-guid}/oauth2/authorize?response_type=id_token&redirect_uri=https%3A%2F%2F....etc..etc.%2F&client_id={api-guid}&scope=openid+profile+email&response_mode=form_post&state=...etc... Server: Microsoft-IIS/8.0 X-Powered-By: ASP.NET Set-Cookie: ARRAffinity=4f51...snip....redact....db6d;Path=/;Domain=webapi.azurewebsites.net 我有两个ASP.NET web应用程序分别托管在Windows Azure上,并且都与同一Azure Active Directory租户关联:Angularjs CORS飞行前请求响应Azure托管Web API中的302重定向,angularjs,azure,asp.net-web-api,cors,adal,Angularjs,Azure,Asp.net Web Api,Cors,Adal,场景: Request OPTIONS /api/items HTTP/1.1 Host: webapi.azurewebsites.net Connection: keep-alive Access-Control-Request-Method: GET Access-Control-Request-Headers: accept, authorization Origin: https://mvcapp.azurewebsites.net User-Agent: Mozilla/5.0 (W
angular.module("myApp", ["ngRoute", "AdalAngular"])
.config(["$routeProvider", "$locationProvider", "$httpProvider", "adalAuthenticationServiceProvider",
function ($routeProvider, $locationProvider, $httpProvider, adalProvider) {
$routeProvider.when("/", { // other routes omitted for brevity
templateUrl: "/content/views/home.html",
requireADLogin: true // restrict to validated users in the Azure AD tenant
});
// CORS support (I've tried with and without this line)
$httpProvider.defaults.withCredentials = true;
adalProvider.init({
tenant: "contoso.onmicrosoft.com",
clientId: "11111111-aaaa-2222-bbbb-3333cccc4444", // Azure id of the web app
endpoints: {
// URL and Azure id of the web api
"https://webapi.azurewebsites.net/": "99999999-zzzz-8888-yyyy-7777xxxx6666"
}
}, $httpProvider);
}
]);
public void ConfigureAuth(IAppBuilder app)
{
// I've tried with and without the below line and also by passing
// in a more restrictive and explicit custom CorsOptions object
app.UseCors(CorsOptions.AllowAll);
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
TokenValidationParameters = new TokenValidationParameters
{
// Azure id of the Web API, also tried the client app id
ValidAudience = "99999999-zzzz-8888-yyyy-7777xxxx6666"
},
Tenant = "contoso.onmicrosoft.com"
}
);
// I've tried with and without this
app.UseWebApi(GlobalConfiguration.Configuration);
}
public static void Register(HttpConfiguration config)
{
// I've tried with and without this and also using both this
// and the OWIN CORS setup above. Decorating the ApiControllers
// or specific Action methods with a similar EnableCors attribute
// also doesn't work.
var cors = new EnableCorsAttribute("https://mvcapp.azurewebsites.net", "*", "*")
{
cors.SupportsCredentials = true // tried with and without
};
config.EnableCors(cors);
// Route registration and other initialization code removed
}
WebApiConfig初始化
angular.module("myApp", ["ngRoute", "AdalAngular"])
.config(["$routeProvider", "$locationProvider", "$httpProvider", "adalAuthenticationServiceProvider",
function ($routeProvider, $locationProvider, $httpProvider, adalProvider) {
$routeProvider.when("/", { // other routes omitted for brevity
templateUrl: "/content/views/home.html",
requireADLogin: true // restrict to validated users in the Azure AD tenant
});
// CORS support (I've tried with and without this line)
$httpProvider.defaults.withCredentials = true;
adalProvider.init({
tenant: "contoso.onmicrosoft.com",
clientId: "11111111-aaaa-2222-bbbb-3333cccc4444", // Azure id of the web app
endpoints: {
// URL and Azure id of the web api
"https://webapi.azurewebsites.net/": "99999999-zzzz-8888-yyyy-7777xxxx6666"
}
}, $httpProvider);
}
]);
public void ConfigureAuth(IAppBuilder app)
{
// I've tried with and without the below line and also by passing
// in a more restrictive and explicit custom CorsOptions object
app.UseCors(CorsOptions.AllowAll);
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
TokenValidationParameters = new TokenValidationParameters
{
// Azure id of the Web API, also tried the client app id
ValidAudience = "99999999-zzzz-8888-yyyy-7777xxxx6666"
},
Tenant = "contoso.onmicrosoft.com"
}
);
// I've tried with and without this
app.UseWebApi(GlobalConfiguration.Configuration);
}
public static void Register(HttpConfiguration config)
{
// I've tried with and without this and also using both this
// and the OWIN CORS setup above. Decorating the ApiControllers
// or specific Action methods with a similar EnableCors attribute
// also doesn't work.
var cors = new EnableCorsAttribute("https://mvcapp.azurewebsites.net", "*", "*")
{
cors.SupportsCredentials = true // tried with and without
};
config.EnableCors(cors);
// Route registration and other initialization code removed
}
API选项谓词处理程序注册
<system.webServer>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="OPTIONSHandler" path="*" verb="OPTIONS" modules="IsapiModule" scriptProcessor="C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
我也遇到了类似的问题,无法找到合适的解决方案。只有Owin cors足以安装。请先检查Owin.cors的软件包
<package id="Microsoft.Owin" version="3.0.0" targetFramework="net45" />
<package id="Microsoft.Owin.Cors" version="2.1.0" targetFramework="net45" />
控制器不需要CORS相关属性
[Authorize]
public class ContactsController : ApiController
{
// GET api/<controller>
public IEnumerable<string> Get()
{
return new string[] { "person1", "person2" };
}
// GET api/<controller>/5
public string Get(int id)
{
return "person" + id;
}
}]))
飞行前响应示例:
Remote Address:127.0.0.1:8888
Request URL:http://localhost:39725/api/contacts
Request Method:OPTIONS
Status Code:200 OK
Request Headersview source
Accept:*/*
Accept-Encoding:gzip, deflate, sdch
Accept-Language:en-US,en;q=0.8
Access-Control-Request-Headers:accept, authorization
Access-Control-Request-Method:GET
Host:localhost:39725
Origin:http://localhost:49726
Proxy-Connection:keep-alive
Referer:http://localhost:49726/myspa.html
User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.99 Safari/537.36
Response Headersview source
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:authorization
Access-Control-Allow-Origin:http://localhost:49726
Content-Length:0
Date:Fri, 23 Jan 2015 01:10:54 GMT
Server:Microsoft-IIS/8.0
X-Powered-By:ASP.NET
已解决(某种程度上)
这似乎是由部署问题造成的,特别是我最初将应用程序发布到Azure的方式。这两个应用程序最初都是使用Windows身份验证编写的,并部署到标准(即非Azure)web服务器。使用这些技术,这些应用程序工作正常
根据新的业务需求,我一直在努力将它们迁移到Azure。我遵循的过程是:
按照最初编写的方式,从Visual Studio 2013发布向导将这两个应用程序直接部署/发布到Azure。当然,正如预期的那样,这是坏的,因为他们无法从Azure中与本地Active Directory通信
根据问题末尾所有链接的详细信息,逐步更新代码以删除Windows Auth并替换为Azure AD Auth
手动将应用程序与Azure AD租户关联,以便使用Azure AD门户进行身份验证
在某个时候,我注意到VS发布向导的“设置”选项卡上的“启用组织身份验证”选项,并开始使用它将应用程序与租户关联。因为我已经手动关联了它们,VisualStudio最终为每个应用程序创建了另一个Azure广告应用程序,结果产生了两个
最后,我们做到了:
Request
OPTIONS /api/items HTTP/1.1
Host: webapi.azurewebsites.net
Connection: keep-alive
Access-Control-Request-Method: GET
Access-Control-Request-Headers: accept, authorization
Origin: https://mvcapp.azurewebsites.net
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.99 Safari/537.36
Accept: */*
Referer: https://mvcapp.azurewebsites.net/
Response
HTTP/1.1 302 Found
Content-Length: 504
Location: https://login.windows.net/{authority-guid}/oauth2/authorize?response_type=id_token&redirect_uri=https%3A%2F%2F....etc..etc.%2F&client_id={api-guid}&scope=openid+profile+email&response_mode=form_post&state=...etc...
Server: Microsoft-IIS/8.0
X-Powered-By: ASP.NET
Set-Cookie: ARRAffinity=4f51...snip....redact....db6d;Path=/;Domain=webapi.azurewebsites.net
已删除使用门户的两个应用程序的所有Azure记录,包括Azure网站本身和Azure广告网站/关联李>
已将两个应用中的所有代码更改还原回其原始状态
在应用程序中重新实现Azure AD auth(OWIN、adal.js等)
重新发布了两个应用程序,让VS向导处理所有Azure关联
使用新创建的客户端ID更新了Web.config文件和adal.js初始化李>
再次出版
现在选项飞行前请求不再是302重定向
相反,它们现在是405方法不允许的,非常类似于。某种程度上说是进步
即使它仍然无法端到端工作,我还是会留下这个答案(而不是删除这个问题),以防它可能会帮助其他体验Azure 302重定向CORS预飞的人。感谢您的回复。您有一个早期版本的Microsoft.Owin.Cors NuGet包(我使用的是3.0.0),并且在Owin和adal.js初始化中使用租户ID而不是租户名称。除此之外,基本上是一样的。希望与希望相反,我换到了先前的包,并尝试使用租户ID。不幸的是,没有骰子。您能否发布工作示例中执行的选项飞行前请求的请求和响应标题?我很想看看它们之间有什么不同,如果有的话。我为选项请求添加了一个例子。您是否收到302的错误?这可能与应用程序的权限设置有关。我还更新了工作示例。感谢您发布标题。有趣。而且,是的,我在这两个应用程序中都配置了Azure AD访问权限。我已经更新了问题,并将该部分添加到“我尝试了什么”部分。您的飞行前响应正在尝试重定向到登录。我认为owin中间件不接受令牌并重定向到登录。您可以使用my cors示例并更改Web.config以尝试您的设置。我在上面提供了github回购链接。观众将是您在angular framework的web应用程序中瞄准的资源。看起来Owin并没有在预飞行中获得令牌。发布的选项请求头都不显示带有承载令牌的授权头,Chrome开发工具也不显示发送的任何请求cookie。我还查看了和的相关源代码。在飞行前的请求中,似乎只检查源代码、方法和头文件。您解决过这个问题吗?我被困在302上,想尽一切办法绕过它。我已经删除了所有内容,并开始了多次。如果您能提供任何帮助,我们将不胜感激。@Isaclevin,302已按上述方式解决。随后的405也在不久后解决了,但我真的不记得它的解决方案是什么。有机会吗