- Tôi muốn có dự án MVC về dự án WebAPI
www.example1.com
- trên
api.example2.com
Tôi muốn hạn chế quyền truy cập vào WebAPI. Tôi đã cố gắng triển khai Mã thông báo chống giả mạo:Làm cách nào để triển khai Mã thông báo chống giả mạo giữa giao diện người dùng MVC và Web Api trên các miền khác nhau?
Khi tôi tạo yêu cầu GET cho WebApi bằng mã thông báo Chống giả mạo thì tôi nhận được ngoại lệ vì yêu cầu không chứa mã thông báo này.
Trong phương pháp có tên ValidateRequestHeader
là biến cookie = null
.
Tôi làm cách nào để khắc phục mã sau? Đây có phải là giải pháp đúng không?
dự án MVC (front-end) - cho sự phát triển là localhost:33635
:
Index.cshtml
<div class="container">
<div class="row">
<div class="col-md-12">
<input id="get-request-button" type="button" class="btn btn-info" value="Create request to API Server" />
<br />
<div id="result"></div>
</div>
</div>
</div>
@section scripts
{
<script type="text/javascript">
@functions{
public string TokenHeaderValue()
{
string cookieToken, formToken;
AntiForgery.GetTokens(null, out cookieToken, out formToken);
return cookieToken + ":" + formToken;
}
}
$(function() {
$("#get-request-button").click(function() {
$.ajax("http://localhost:33887/api/values", {
type: "GET",
contentType: "application/json",
data: {},
dataType: "json",
headers: {
'RequestVerificationToken': '@TokenHeaderValue()'
}
}).done(function (data) {
$("#result").html(data);
});
return false;
});
});
</script>
}
dự án WebAPI - phát triển là localhost:33887
:
WebApiConfig.cs
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
config.EnableCors(new EnableCorsAttribute("http://localhost:33635", "*", "*"));
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
ValidateHttpAntiForgeryTokenAttribute.cs:
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public sealed class ValidateHttpAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter
{
public Task<HttpResponseMessage> ExecuteAuthorizationFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation)
{
var request = actionContext.Request;
try
{
if (IsAjaxRequest(request))
{
ValidateRequestHeader(request);
}
else
{
AntiForgery.Validate();
}
}
catch (Exception)
{
actionContext.Response = new HttpResponseMessage
{
StatusCode = HttpStatusCode.Forbidden,
RequestMessage = actionContext.ControllerContext.Request
};
return FromResult(actionContext.Response);
}
return continuation();
}
private Task<HttpResponseMessage> FromResult(HttpResponseMessage result)
{
var source = new TaskCompletionSource<HttpResponseMessage>();
source.SetResult(result);
return source.Task;
}
private bool IsAjaxRequest(HttpRequestMessage request)
{
IEnumerable<string> xRequestedWithHeaders;
if (!request.Headers.TryGetValues("X-Requested-With", out xRequestedWithHeaders)) return false;
var headerValue = xRequestedWithHeaders.FirstOrDefault();
return !String.IsNullOrEmpty(headerValue) && String.Equals(headerValue, "XMLHttpRequest", StringComparison.OrdinalIgnoreCase);
}
private void ValidateRequestHeader(HttpRequestMessage request)
{
var headers = request.Headers;
var cookie = headers
.GetCookies()
.Select(c => c[AntiForgeryConfig.CookieName])
.FirstOrDefault();
IEnumerable<string> xXsrfHeaders;
if (headers.TryGetValues("RequestVerificationToken", out xXsrfHeaders))
{
var rvt = xXsrfHeaders.FirstOrDefault();
if (cookie == null)
{
throw new InvalidOperationException($"Missing {AntiForgeryConfig.CookieName} cookie");
}
AntiForgery.Validate(cookie.Value, rvt);
}
else
{
var headerBuilder = new StringBuilder();
headerBuilder.AppendLine("Missing X-XSRF-Token HTTP header:");
foreach (var header in headers)
{
headerBuilder.AppendFormat("- [{0}] = {1}", header.Key, header.Value);
headerBuilder.AppendLine();
}
throw new InvalidOperationException(headerBuilder.ToString());
}
}
}
ValuesController:
public class ValuesController : ApiController
{
// GET: api/Values
[ValidateHttpAntiForgeryToken]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET: api/Values/5
public string Get(int id)
{
return "value";
}
// POST: api/Values
public void Post([FromBody]string value)
{
}
// PUT: api/Values/5
public void Put(int id, [FromBody]string value)
{
}
// DELETE: api/Values/5
public void Delete(int id)
{
}
}
@teovankot Tôi muốn giải quyết việc chia sẻ AntiForgeryToken giữa hai máy chủ. Liên kết của bạn được giải quyết chỉ Mã thông báo chống giả mạo trên một máy chủ. – Jenan
Xin lỗi đó là điều xấu của tôi –