【问题标题】:Authorization of Web ApiWeb API 授权
【发布时间】:2014-01-04 17:28:08
【问题描述】:

我正在使用 Visual Studio 2013 mvc、webapi2 和 Odata 开发一个 RESTful WebApi,

可以从移动客户端访问。

我正在按照下面给出的教程进行操作

http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api

现在我在授权方面遇到了一些困难。我希望 api 得到保护,并希望检查请求是否来自正确的用户。

以下是我的客户端代码

<head>

    <script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>

    <script>

    $(document).ready(function() {

        $( "#post").click(function() {
        $.ajax({
                type: "GET",
                url: "http://localhost:21900/odata/Products(1)",
                success: function (data) {
                alert(data);
                },
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                alert(textStatus);
                }
            });
        });
    });
    </script>
</head>
<body>
    <input type="submit" id="post" value="Post"/>
</body>

和服务器端代码

public class ProductsController : ODataController
{
    private ProductServiceContext db = new ProductServiceContext();


    [Queryable]
    public SingleResult<Product> GetProduct([FromODataUri] int key)
    {
        return SingleResult.Create(db.Products.Where(product => product.ID == key));
    }
}

我已经尝试使用 [Authorize] 进行上述操作,但对我来说无法正常工作

任何帮助将不胜感激。

谢谢。

【问题讨论】:

  • [Authorize] 怎么不适合你?

标签: c# asp.net asp.net-mvc asp.net-web-api


【解决方案1】:

您必须创建新属性,如下所示:-

[AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
    public class AuthorizeAttribute : AuthorizationFilterAttribute
    {       
        public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext)
        {
            base.OnAuthorization(actionContext);            

            ////check authentication and return if not authorized
            if (actionContext != null)
            {
                if (!WebSecurity.IsAuthenticated)
                {
                    actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized) { RequestMessage = actionContext.ControllerContext.Request };
                     return;
                }             

            }
        }
    }

创建上述过滤器属性后,您可以将其添加到 webapiconfig.cs 文件中,如下所示,它将过滤您的所有请求。

config.Filters.Add(new AuthorizeAttribute());

你也可以为特定的方法或类添加它,如下所示

[AuthorizeAttribute]
public class TestController : ApiController

【讨论】:

    【解决方案2】:

    有很多方法可以保护您的 Web Api 应用程序。基本身份验证、OAuth、HMAC、API 密钥、自定义令牌。可以在here 找到一个很好的启动器,它还提供了一个示例应用程序供下载。

    【讨论】:

      【解决方案3】:

      我还开发了一个 web api,用户可以通过手机连接到它。 对于Authentication,我在.net 中使用RSA。手机中的客户端,首先发送用户名和密码,然后我创建一个令牌并将其发送给客户端。在下一个请求中,客户端必须将此令牌附加到请求标头中,我获取此令牌并从中提取用户名和密码。

      RSA 加密:

      public class ApiRSA
          {
              private static string privateKey = // Generate a private key
      
              private static string publicKey = // Generate a public key
      
              public static string Decrypt(string data)
              {
                  var rsa = new RSACryptoServiceProvider();
      
                  byte[] dataByte = Convert.FromBase64String(data);
      
                  rsa.FromXmlString(privateKey);
                  var decryptedByte = rsa.Decrypt(dataByte, false);
      
                  return Encoding.Unicode.GetString(decryptedByte);
              }
      
              public static string Encrypt(string data)
              {
                  var rsa = new RSACryptoServiceProvider();
      
                  var dataByte = Encoding.Unicode.GetBytes(data);
      
                  rsa.FromXmlString(publicKey);
                  var encryptedByte = rsa.Encrypt(dataByte, false);
      
                  return Convert.ToBase64String(encryptedByte);
              }
      
              public static void GeneraterPrivatePublicKey(out string privateKey, out string publicKey)
              {
                  var csp = new RSACryptoServiceProvider(1024);
      
                  var privKey = csp.ExportParameters(true);
                  var pubKey = csp.ExportParameters(false);
      
                  {
                      var sw = new System.IO.StringWriter();
                      var xs = new System.Xml.Serialization.XmlSerializer(typeof(RSAParameters));
                      xs.Serialize(sw, privKey);
                      privateKey = sw.ToString();
                  }
      
                  {
                      var sw = new System.IO.StringWriter();
                      var xs = new System.Xml.Serialization.XmlSerializer(typeof(RSAParameters));
                      xs.Serialize(sw, pubKey);
                      publicKey = sw.ToString();
                  }
              }
          }
      

      这个类会将用户名和密码加密成一个字符串(令牌)。在登录方法中,您检查用户名和密码并根据用户名和密码生成令牌并返回此令牌。 在任何进一步的请求中,客户端必须将此令牌附加到请求标头中。

      为了检查更多请求,您可以使用自定义身份验证属性:

      public interface IApiAuthenticationProvider
          {
              bool IsValid(string username, string password);
          }
      
      public static class ApiAuthenticationEncrypter
      {
          public static string Encrypt(string username, string password)
          {
              return ApiRSA.Encrypt(/*join username and password*/);
          }
      
          public static void Decrypt(string token, out string username, out string password)
          {
              var usernameAndPass = ApiRSA.Decrypt(token).Split(/*split username and password*/);
              username = usernameAndPass[0];
              password = usernameAndPass[1];
          }
      }
      
      public class ApiAuthenticationAttribute : ActionFilterAttribute
          {
              private IApiAuthenticationProvider AuthenticationProvider { get; set; }
      
              public ApiAuthenticationAttribute(Type apiAuthenticationType)
              {
                  Debug.Assert(typeof(IApiAuthenticationProvider).IsAssignableFrom(apiAuthenticationType));
                  AuthenticationProvider = (IApiAuthenticationProvider) Activator.CreateInstance(apiAuthenticationType);
              }
      
              public override void OnActionExecuting(HttpActionContext actionContext)
              {
                  Debug.Assert(AuthenticationProvider != null);
      
                  Object httpContextBase;
                  bool isValid = actionContext.Request.Properties.TryGetValue("MS_HttpContext", out httpContextBase);
                  bool isLocal = isValid && ((HttpContextBase)httpContextBase).Request.IsLocal;
      
                  if (isLocal)
                  {
                      base.OnActionExecuting(actionContext);
                      return;
                  }
      
      
                  //// == Only Https request ==
                  //if (!String.Equals(actionContext.Request.RequestUri.Scheme, "https", StringComparison.OrdinalIgnoreCase))
                  //{
                  //    actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.BadRequest)
                  //    {
                  //        Content = new StringContent("HTTPS Required")
                  //    };
                  //    return;
                  //}
      
                  // == Try to get Token ==
                  string token;
                  try
                  {
                      token = actionContext.Request.Headers.GetValues("AuthenticationToken").First();
                  }
                  catch (Exception)
                  {
                      actionContext.Response = new HttpResponseMessage(HttpStatusCode.BadRequest)
                      {
                          Content = new StringContent("AuthenticationToken not found"),
                      };
                      return;
                  }
      
                  // == Validate using validator provider ==
                  try
                  {
                      string username;
                      string password;
                      ApiAuthenticationEncrypter.Decrypt(token, out username, out password);
      
                      if (AuthenticationProvider.IsValid(username, password))
                          base.OnActionExecuting(actionContext);
                      else
                          throw new Exception();
                  }
                  catch (Exception)
                  {
                      actionContext.Response = new HttpResponseMessage(HttpStatusCode.Forbidden)
                      {
                          Content = new StringContent("Invalid UserName or Password")
                      };
                      return;
                  }
              }
          }
      

      并通过IApiAuthenticationProvider的具体类型使用此属性:

      [ApiAuthentication(typeof (Concrete Type of IApiAuthenticationProvider))]
      public class SomeController: ApiController
      

      阅读Here

      【讨论】:

        猜你喜欢
        • 2018-05-21
        • 2018-08-12
        • 2014-05-24
        • 2014-06-17
        • 2017-08-22
        • 1970-01-01
        • 2020-04-11
        • 2023-03-12
        • 1970-01-01
        相关资源
        最近更新 更多