Tôi đã dành tuần trước tạo API cho ứng dụng MVC hiện có và hiện đang cố gắng bảo mật API cùng với việc làm lại bảo mật bên MVC khi cần .Yêu cầu POST MVC mất tiêu đề Cấp phép - cách sử dụng Mã thông báo API khi đã truy xuất
Hiện tại, ứng dụng MVC được thiết lập để sử dụng cookie ứng dụng qua OWIN/OAuth/Identity. Tôi đã cố gắng kết hợp mã thông báo Bearer rằng API Web được thiết lập để tạo ra bất cứ khi nào thực hiện cuộc gọi đến các phương thức API bị hạn chế, nhưng đã có rất ít thành công cho đến nay - yêu cầu GET hoạt động tốt, nhưng yêu cầu POST sẽ mất tiêu đề Cấp phép khi nhận được API.
Tôi đã tạo Ứng dụng khách SDK đang được ứng dụng MVC sử dụng để thực hiện cuộc gọi tới API và đã thử tổng cộng ba phương pháp đặt tiêu đề Cấp quyền cho bất kỳ lệnh gọi nào đến API, tất cả dường như chỉ làm việc tốt cho các yêu cầu GET, nhưng thất bại hoàn toàn cho bất kỳ yêu cầu POST tôi cần phải thực hiện ...
tôi có thể thiết lập các tiêu đề yêu cầu trong bộ điều khiển MVC:
HttpContext.Request.Headers. Thêm ("Ủy quyền", "Bộ đệm" + phản hồi.AccessToken);
(nơi response.AccessToken là dấu hiệu lấy ra trước đó từ API)
tôi có thể thiết lập các tiêu đề yêu cầu thông qua một phương pháp khuyến nông trên Client SDK:
_apiclient.SetBearerAuthentication (token.AccessToken)
hoặc tôi có thể đặt tiêu đề Yêu cầu bằng tay trên Client SDK:
_apiClient.Authentication = new AuthenticationHeaderValue ("Bearer, accessToken);
(Trường hợp accessToken là mã thông báo được truy xuất trước đó, được chuyển đến phương thức Khách hàng được gọi).
Tôi có rất ít việc tiếp tục từ điểm này đến những gì đang gây ra sự cố. Điều duy nhất tôi có thể thu được từ trước đến nay là ASP.NET làm cho tất cả các yêu cầu POST gửi yêu cầu đầu tiên với một tiêu đề Mong đợi cho một phản hồi HTTP 100-Continue, sau đó nó sẽ hoàn thành yêu cầu POST thực tế. Tuy nhiên, có vẻ như khi yêu cầu thứ hai này, tiêu đề Cấp quyền không còn hiện diện và do đó thuộc tính Ủy quyền của API sẽ gây ra phản hồi 401-Không được phép thay vì thực sự chạy phương thức API.
Vì vậy, làm cách nào để lấy mã thông báo Bearer mà tôi có thể truy xuất từ API và sử dụng nó trên các yêu cầu tiếp theo, bao gồm các yêu cầu POST khác nhau mà tôi cần thực hiện?
Ngoài ra, cách tốt nhất để lưu mã thông báo này vào chính ứng dụng MVC là gì? Tôi muốn tránh phải vượt qua chuỗi để mọi phương pháp trong ứng dụng có thể cần nó, nhưng tôi cũng đã được đọc mà lưu trữ nó trong một cookie là một ý tưởng rất xấu vì lý do an ninh.
Một vài điểm thêm rằng sẽ được quan tâm ngay lập tức sau khi tôi có được thông qua vấn đề này:
Có sử dụng OAuth Bearer Tokens có nghĩa là tôi không còn có thể sử dụng ApplicationCookies cho ứng dụng MVC?Và/hoặc nó sẽ làm cho mã sau vô ích trong suốt ứng dụng?
User.Identity.GetUserId()
Hiện nay tôi đang buộc vào cho ý kiến ra API của tôi [Duyệt] thuộc tính để tiếp tục với công việc của tôi, mà rõ ràng là không lý tưởng nhưng nó cho phép tôi tạm thời tiếp tục.
file Startup:
MVC:
public class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
}
private void ConfigureAuth(IAppBuilder app)
{
app.CreatePerOwinContext(ADUIdentityDbContext.Create);
app.CreatePerOwinContext<ADUUserManager>(ADUUserManager.Create);
app.UseOAuthBearerTokens(new OAuthAuthorizationServerOptions
{
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
//This should be set to FALSE before we move to production.
AllowInsecureHttp = true,
ApplicationCanDisplayErrors = true,
TokenEndpointPath = new PathString("/api/token"),
});
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ExternalBearer,
CookieName = "ADU",
ExpireTimeSpan = TimeSpan.FromHours(2),
LoginPath = new PathString("/Account/Login"),
SlidingExpiration = true,
});
}
}
API
public class Startup
{
public void Configuration(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();
config.DependencyResolver = new NinjectResolver(new Ninject.Web.Common.Bootstrapper().Kernel);
WebApiConfig.Register(config);
ConfigureOAuth(app);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
}
public void ConfigureOAuth(IAppBuilder app)
{
app.CreatePerOwinContext(ADUIdentityDbContext.Create);
app.CreatePerOwinContext<ADUUserManager>(ADUUserManager.Create);
OAuthAuthorizationServerOptions oAuthServerOptions = new OAuthAuthorizationServerOptions()
{
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/api/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new SimpleAuthorizationServerProvider(),
};
//token generation
app.UseOAuthAuthorizationServer(oAuthServerOptions);
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
}
public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
private IUserBusinessLogic _userBusinessLogic;
/// <summary>
/// Creates the objects necessary to initialize the user business logic field and initializes it, as this cannot be done by dependency injection in this case.
/// </summary>
public void CreateBusinessLogic()
{
IUserRepository userRepo = new UserRepository();
IGeneratedExamRepository examRepo = new GeneratedExamRepository();
IGeneratedExamBusinessLogic examBLL = new GeneratedExamBusinessLogic(examRepo);
_userBusinessLogic = new UserBusinessLogic(userRepo, examBLL);
}
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) { context.Validated(); }
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
//create a claim for the user
ClaimsIdentity identity = new ClaimsIdentity(context.Options.AuthenticationType);
identity.AddClaim(new Claim("sub", user.Id));
context.Validated(identity);
}
}