Cra*_*ooB 10 authorization asp.net-mvc-4 asp.net-web-api
我正在尝试制作一个安全的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的大力支持(他也很快).
谢谢
Dar*_*rov 27
您在Global.asax以下处注册处理程序:
GlobalConfiguration
    .Configuration
    .MessageHandlers
    .Add(new TokenValidationHandler());
然后装饰需要使用[Authorize]属性授权的控制器/操作:
public class MyController : ApiController
{
    [Authorize]
    public string Get(string id)
    {
        ...          
    }
}
对于基于角色的授权,您可以查看以下示例:https://stackoverflow.com/a/11536349/29407
它使用基于SSL的基本身份验证,并依赖于内置成员资格和角色提供程序.
更新:
根据无数的评论,我得到的印象是我的答案不够明确.让我详细说明一下.
定义模型:
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);
    }
}
定义测试控制器:
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
| 归档时间: | 
 | 
| 查看次数: | 29671 次 | 
| 最近记录: |