gpt4 book ai didi

authorization - 如何为asp.net mvc 4 web api进行基于角色的授权

转载 作者:行者123 更新时间:2023-12-04 02:44:02 27 4
gpt4 key购买 nike

我正在尝试制作一个安全的 asp.net web api。为此,我遵循了以下链接

MessageHandler for token

所以现在每个 api 请求都需要一个 token ,我在请求 header 中提供了一个 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 请求,检查 header 中的 token 。但是我如何完成授权,我的意思是我怎么能不允许这个 token 不能访问同一个 Controller 中的某些操作。我只需要一个想法。希望我解释得足够好。

编辑:
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 向 Controller 上方的“api” Controller 发出请求(稍后我将其更改为 HttpClient)。在上面 ** ** 之间的代码中,我得到 404 page not found for myWebRequest.GetResponse()

下面是我的 api Controller
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;
}
}
}

现在在委托(delegate)处理程序中,我有以下代码
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 Controller 中删除 Authorize 属性,则不会出现 404 错误,然后我就可以访问它。

更新(我也相信解决方案):

这就是问题得到解决的方式

我已经更改了 建议的 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,感谢 达林 感谢他的大力支持(他也很快)。

谢谢

最佳答案

您在 Global.asax 中注册处理程序:

GlobalConfiguration
.Configuration
.MessageHandlers
.Add(new TokenValidationHandler());

然后用 [Authorize] 装饰需要授权的 Controller / Action 属性:
public class MyController : ApiController
{
[Authorize]
public string Get(string id)
{
...
}
}

对于基于角色的授权,您可以查看以下示例: https://stackoverflow.com/a/11536349/29407

它使用 SSL 上的基本身份验证,并依赖于内置的成员资格和角色提供程序。

更新:

根据留下的众多评论,我的印象是我的答案不够清楚。让我详细说明。
  • 使用空模板
  • 创建一个新的 ASP.NET MVC 4 项目
  • 定义模型:
    public class Product
    {
    public int Id { get; set; }
    public string Name { get; set; }
    }
  • 定义一个 ApiController:
    public class ProductsController : ApiController
    {
    // GET /api/products => only users having the Users role can call this
    [Authorize(Roles = "Users")]
    public HttpResponseMessage Get()
    {
    var products = Enumerable.Range(1, 5).Select(x => new Product
    {
    Id = x,
    Name = "product " + x
    });
    return Request.CreateResponse(HttpStatusCode.OK, products);
    }

    // GET /api/products => only users having the Admin role can call this
    [Authorize(Roles = "Admin")]
    public void Post(Product product)
    {
    }
    }
  • 定义一个 RSAHelper :
    public class RSAClass
    {
    private static string _privateKey = "<RSAKeyValue><Modulus>poQS/c9tLkgg84xYZpnUBHP6fy24D6XmzhQ8yCOG317hfUNhRt6Z9N4oTn+QcOTh/DAnul4Q901GrHbPrMB8tl1LtbpKbvGftPhyR7OLQVnWC1Oz10t2tHEo7mqyPyAVuYsq8Q1E3YNTh2V6+PRvMiAWGUHGyyG7fKjt/R9W+RE=</Modulus><Exponent>AQAB</Exponent><P>4G09wYejA4iLakpAcjXbE/zV9tXTNsYqVIWeXF4hzwMmwmin7ru/WQzXu2DdapXXOJIKqrkfzXlcPwCsW5b9rQ==</P><Q>vfEq13Et+cP4eGgsR+crDQH0Mi+G6UW5ACfuDs/zam1o+CE70pLgeWawfqW4jRN30/VHDnTF9DZuotH6zihNdQ==</Q><DP>JoZaHYidERQ1am+IlJJuIwY57H9UHIjz50JwpsZ540FVO/YfLboI5M5xkfbUy2EhatKXBit1LB5zGVWSQL6wmQ==</DP><DQ>Gxk7KX2GN6oT2unR13hNlg9/TWGmd8VwvWr09bwJWFe/sBbduA8oY2mZKJhwGgB7CgxmVNOoIk1Zv3UBuUPauQ==</DQ><InverseQ>ZwJpSUZ09lCfiCF3ILB6F1q+6NC5hFH0O4924X9B4LZ8G4PRuudBMu1Yg0WNROUqVi3zfihKvzHnquHshSL56A==</InverseQ><D>pPQNRDVpeQGm8t1C7VDRwR+LNNV7krTMMbXGiJT5FOoPAmHvSZ9WcEZrM2gXFF8IpySlFm/86p84tbx0+jMs1niU52VsTscsamGbTzbsxeoHAt1fQUvzYveOGoRezotXblboVB2971r6avMHNtAk0FAdjvh4TjGZJCGTqNHD0mE=</D></RSAKeyValue>";
    private static string _publicKey = "<RSAKeyValue><Modulus>poQS/c9tLkgg84xYZpnUBHP6fy24D6XmzhQ8yCOG317hfUNhRt6Z9N4oTn+QcOTh/DAnul4Q901GrHbPrMB8tl1LtbpKbvGftPhyR7OLQVnWC1Oz10t2tHEo7mqyPyAVuYsq8Q1E3YNTh2V6+PRvMiAWGUHGyyG7fKjt/R9W+RE=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";
    private static UnicodeEncoding _encoder = new UnicodeEncoding();

    public static string Decrypt(string data)
    {
    try
    {
    var rsa = new RSACryptoServiceProvider();
    var dataArray = data.Split(new char[] { ',' });

    byte[] dataByte = new byte[dataArray.Length];
    for (int i = 0; i < dataArray.Length; i++)
    {
    dataByte[i] = Convert.ToByte(dataArray[i]);
    }

    rsa.FromXmlString(_privateKey);
    var decryptedByte = rsa.Decrypt(dataByte, false);
    return _encoder.GetString(decryptedByte);
    }
    catch (Exception)
    {
    throw new RSAException();
    }
    }

    public static string Encrypt(string data)
    {
    try
    {
    var rsa = new RSACryptoServiceProvider();
    rsa.FromXmlString(_publicKey);
    var dataToEncrypt = _encoder.GetBytes(data);
    var encryptedByteArray = rsa.Encrypt(dataToEncrypt, false).ToArray();
    var length = encryptedByteArray.Count();
    var item = 0;
    var sb = new StringBuilder();
    foreach (var x in encryptedByteArray)
    {
    item++;
    sb.Append(x);

    if (item < length)
    sb.Append(",");
    }

    return sb.ToString();

    }
    catch (Exception ex)
    {
    throw new RSAException();
    }
    }

    public class RSAException : Exception
    {
    public RSAException() : base("RSA Encryption Error") { }
    }
    }
  • 定义一个 TokenValidationHandler :
    public class TokenValidationHandler : DelegatingHandler
    {
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
    try
    {
    if (!request.Headers.Contains("Authorization-Token"))
    {
    return Task<HttpResponseMessage>.Factory.StartNew(() =>
    {
    return new HttpResponseMessage(HttpStatusCode.BadRequest)
    {
    Content = new StringContent("You need to include Authorization-Token header in your request")
    };
    });
    }

    var 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")
    };
    });
    }

    var decryptedToken = RSAClass.Decrypt(token);

    // TODO: do your query to find the user
    var user = decryptedToken;

    var identity = new GenericIdentity(decryptedToken);
    string[] roles = new[] { "Users", "Testers" };

    var principal = new GenericPrincipal(identity, roles);
    Thread.CurrentPrincipal = principal;
    }
    catch
    {
    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);
    }
    }
  • 定义一个测试 Controller :
    public class TestsController : Controller
    {
    public ActionResult GetProducts()
    {
    var productsUrl = Url.RouteUrl("DefaultApi", new { httproute = "", controller = "products" }, "http");
    using (var client = new HttpClient())
    {
    var token = RSAClass.Encrypt("john");
    client.DefaultRequestHeaders.Add("Authorization-Token", token);

    var products = client
    .GetAsync(productsUrl)
    .Result
    .Content
    .ReadAsAsync<IEnumerable<Product>>()
    .Result;

    return Json(products, JsonRequestBehavior.AllowGet);
    }
    }

    public ActionResult PostProduct()
    {
    var productsUrl = Url.RouteUrl("DefaultApi", new { httproute = "", controller = "products" }, "http");
    using (var client = new HttpClient())
    {
    var token = RSAClass.Encrypt("john");
    client.DefaultRequestHeaders.Add("Authorization-Token", token);

    var product = new Product
    {
    Id = 1,
    Name = "test product"
    };

    var result = client
    .PostAsync<Product>(productsUrl, product, new JsonMediaTypeFormatter())
    .Result;
    if (result.StatusCode == HttpStatusCode.Unauthorized)
    {
    return Content("Sorry you are not authorized to perform this operation");
    }

    return Json(true, JsonRequestBehavior.AllowGet);
    }
    }
    }
  • 测试:
    * /tests/getproducts => success
    * /tests/postproduct => 401
  • 关于authorization - 如何为asp.net mvc 4 web api进行基于角色的授权,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11986974/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com