我在AWS中托管了一个有效的Web API 2移动服务,我想转移到AMS。它适用于Postman和移动设备上。
我关注了几个博客/帖子,花了几个小时重写和重新排序WebApiConfig.Register。然后我创建了一个新的AMS项目并复制了我的所有控制器等,我得到了相同的结果。我回顾了很多类似的问题,但我的脑子已经过了20多行代码。
它通过Postman在本地工作,但在我发布之后我得到了
HTTP 401 - {"消息":"此请求已拒绝授权。"}
以下是AWS正在运行的startup.cs - 我没有调用WebApiConfig.Register
namespace Savviety.Data.Service
{ 公共部分类启动 { public void Configuration(IAppBuilder app) {
var config = new HttpConfiguration();
ConfigureOAuth(app);
// remove in production
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
app.UseWebApi(config);
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
var path = AppDomain.CurrentDomain.BaseDirectory + @"\log4net.config";
var fileInfo = new FileInfo(path);
XmlConfigurator.ConfigureAndWatch(fileInfo);
if (fileInfo.Exists)
{
log4net.Config.XmlConfigurator.ConfigureAndWatch(fileInfo);
}
else
{
throw new FileNotFoundException("Could not find log4net.config");
}
}
public void ConfigureOAuth(IAppBuilder app)
{
var oAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new SimpleAuthorizationServerProvider()
};
// Token Generation
app.UseOAuthAuthorizationServer(oAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
}
}
在AMS版本中,我从Global.asax中的Application.Onstart调用WebApiConfig.Register方法
public static void Register( )
{
.
var options = new ConfigOptions();
var config = ServiceConfig.Initialize(new ConfigBuilder(options));
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
// Make sure this is after ServiceConfig.Initialize
// Otherwise ServiceConfig.Initialize will overwrite your changes
Microsoft.WindowsAzure.Mobile.Service.Config.StartupOwinAppBuilder.Initialize(appBuilder =>
{
ConfigureOAuth(appBuilder);
appBuilder.UseWebApi(config);
var path = AppDomain.CurrentDomain.BaseDirectory + @"\log4net.config";
var fileInfo = new FileInfo(path);
});
//var cors = new EnableCorsAttribute("*", "*", "*");
//config.EnableCors(cors);
// Web API routes
// config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
我还用[AuthorizeLevel(AuthorizationLevel.User)]替换了[Authorize]并删除了startup.cs类。
在Postman中,它在本地工作,但在我发布后却没有。它会生成令牌,但身份验证失败。
TIA
加里
答案 0 :(得分:1)
AuthorizeLevel
属性查找由移动服务发布的令牌。由于您实际上并未在上面发出此类令牌,因此会失败。
事情可能在本地工作,因为默认配置会接受所有本地呼叫。如上所述here,您将需要进入WebApiConfig.cs的Register()方法并添加以下内容:
config.SetIsHosted(true);
这会导致调用开始在本地失败。
要解决核心问题,可以将自己的OWIN提供商连接到移动服务管道。您将需要创建一个LoginProvider
的子类,它基本上在其ConfigureMiddleware()内部执行您的ConfigureAuth()调用。请参阅this blog post中设置LinkedIn中间件的示例。
答案 1 :(得分:0)
好的,主要问题是Azure不支持自定义OWIN身份验证,或者我找不到如何在任何地方实现它。我必须使用其他系统提供的用户和密码列表,因此必须自定义。
解决方案是自定义LoginController和LoginProvider相关代码如下。
MyLoginProvider是LoginProvider的子类,并调用CreateLoginResult基本方法。
我必须将我的javascript auth拦截器修改为config.headers["X-ZUMO-AUTH"] = $localStorage.token;
而不是OAuth bearer token header。
我无法在请求中获取声明标识中的电子邮件或显示名称,但我使用了一种解决方法。当我搞清楚时,我会在这里发布,但现在它并没有阻止我。
public HttpResponseMessage Post(LoginRequest loginRequest)
{
var mongoDbManager = MongoDbManager.GetInstance();
var userCollection = mongoDbManager.GetCollection<UserDocument>(CollectionNames.User);
var q0 = Query<UserDocument>.EQ(i => i.ClientId, loginRequest.ClientId);
var q1 = Query<UserDocument>.EQ(i => i.UserEmailAddress, loginRequest.UserName);
var q2 = Query<UserDocument>.EQ(i => i.UserPassword, loginRequest.Password);
var query = Query.And(q0, q1, q2);
var result = userCollection.FindOne(query);
if (result == null)
{
return this.Request.CreateResponse(HttpStatusCode.Unauthorized, "Invalid username or password");
}
else
{
var claimsIdentity = new ClaimsIdentity();
claimsIdentity.AddClaim(new Claim(ClaimTypes.NameIdentifier, result.UserId));
claimsIdentity.AddClaim(new Claim(ClaimTypes.Email, result.UserEmailAddress));
claimsIdentity.AddClaim(new Claim("DisplayName", result.DisplayName));
var loginResult = new SavvietyLoginProvider(handler).CreateLoginResult(claimsIdentity, Services.Settings.MasterKey);
return this.Request.CreateResponse(HttpStatusCode.OK, loginResult);
}
}
}