安全な asp.net Web API を作成しようとしています。そのために、私は以下のリンクをたどりました
したがって、すべてのAPIリクエストには、たとえば以下のようにリクエストヘッダーで提供するトークンが必要です
public class TestController : Controller
{
public string GetProducts()
{
Uri myUri = new Uri("http://localhost:420420/api/products");
WebRequest myWebRequest = WebRequest.Create(myUri);
myWebRequest.Method = "GET";
myWebRequest.ContentType = "application/json";
myWebRequest.Headers.Add("Authorization-Token", RSAClass.accessToken);
using (WebResponse response = myWebRequest.GetResponse())
{
using (var responseStream = response.GetResponseStream())
{
var reader = new StreamReader(responseStream);
return reader.ReadToEnd();
}
}
}
}
そのため、すべての API リクエストを作成し、ヘッダーでトークンを確認できるようになりました。しかし、どうすれば承認を達成できますか。つまり、このトークンが同じコントローラー内のいくつかのアクションにアクセスできないようにする方法を意味します。アイデアが必要なだけです。十分に説明したいと思います。
編集:
public class TestController : Controller
{
public string GetProducts()
{
Uri myUri = new Uri("http://localhost:420420/api/products");
WebRequest myWebRequest = WebRequest.Create(myUri);
myWebRequest.Method = "GET";
myWebRequest.ContentType = "application/json";
myWebRequest.Headers.Add("Authorization-Token", RSAClass.accessToken);
**using (WebResponse response = myWebRequest.GetResponse())
{
using (var responseStream = response.GetResponseStream())
{
var reader = new StreamReader(responseStream);
return reader.ReadToEnd();
}
}**
}
上記のコントローラー内で、webrequest を使用して「api」コントローラーにリクエストを送信しています (後で HttpClient に変更します)。上記の ** ** の間のコードで、myWebRequest.GetResponse()の 404 ページが見つかりません。
以下は私のAPIコントローラーです
public class ProductsController : ApiController
{
TestModelContainer testModel = new TestModelContainer();
[Authorize(Roles="Users")]
public IEnumerable<Products> GetProducts()
{
IEnumerable<Products> products = (from prods in testModel.Products
select prods);
return products;
}
}
}
委任ハンドラーには、次のコードがあります
public class TokenValidationHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
CancellationToken cancellationToken)
{
TestModelContainer testModel = new TestModelContainer();
var token = "";
try
{
if (request.Headers.Contains("Authorization-Token"))
{
token = request.Headers.GetValues("Authorization-Token").FirstOrDefault();
if (String.IsNullOrEmpty(token))
{
return Task<HttpResponseMessage>.Factory.StartNew(() =>
{
return new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content = new StringContent("Missing Authorization-Token")
};
});
}
}
else
{
return Task<HttpResponseMessage>.Factory.StartNew(() =>
{
return new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content = new StringContent("You need to include Authorization-Token " +
"header in your request")
};
});
}
var decryptedToken = RSAClass.Decrypt(token);
var foundUser = (from user in testModel.Users
where user.Name == decryptedToken
select user).Any();
if (!foundUser)
return Task<HttpResponseMessage>.Factory.StartNew(() =>
{
return new HttpResponseMessage(HttpStatusCode.Forbidden)
{
Content = new StringContent("Unauthorized User")
};
});
var identity = new GenericIdentity(decryptedToken);
string[] roles = new string[] { "Users", "Testers" };
var principal = new GenericPrincipal(identity, roles);
Thread.CurrentPrincipal = principal;
}
catch (Exception ex)
{
return Task<HttpResponseMessage>.Factory.StartNew(() =>
{
return new HttpResponseMessage(HttpStatusCode.InternalServerError)
{
Content = new StringContent("Error encountered while attempting to process authorization token")
};
});
}
return base.SendAsync(request, cancellationToken);
}
APIコントローラーからAuthorize属性を削除すると、404エラーは発生せず、アクセスできるようになりました。
更新(私も解決策を信じています):
これが問題が解決した方法です
Darin Dimitrovが提案する以下のように TestController メソッドを変更しました
public class TestsController : Controller
{
public ActionResult GetProducts()
{
var productsUrl = Url.RouteUrl("DefaultApi", new { httproute = "", controller = "products" }, "http");
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization-Token", RSAClass.accessToken);
var products = client
.GetAsync(productsUrl)
.Result;
if (products.StatusCode == HttpStatusCode.Unauthorized)
{
return Content("Sorry you are not authorized to perform this operation");
}
var prods = products.Content
.ReadAsAsync<IEnumerable<Products>>()
.Result;
return Json(prods, JsonRequestBehavior.AllowGet);
}
}
問題は、API を呼び出す方法がわからなかったことです。Darin の素晴らしいサポートに感謝します(彼も非常に迅速でした)。
ありがとう