我正在尝试创建一个安全的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请求进行检查,在头部检查token。但是如何进行授权,也就是说如何不允许该token访问同一控制器中的某些操作?我只需要一个思路。希望我解释得足够清楚。
编辑:
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”控制器发出请求,该控制器内使用 webrequest(稍后我将更改为 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控制器中删除授权属性,就不会出现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提供的大力支持(他也很快)。
谢谢
TokenValidationHandler
。本文介绍的仅将用户名存储在令牌中,没有角色。您可以查看以下答案,其中我使用基本身份验证方案说明了自定义委托处理程序,并依赖内置的成员身份和角色提供程序:https://dev59.com/dWgu5IYBdhLWcg3wJT9I#11536349 - Darin Dimitrov