2013-12-17 194 views
3

我正在開發使用Visual Studio 2013 MVC,webapi2和OData的REST風格的WebAPI的,授權網絡API

這可以從移動客戶端進行訪問。

我遵循以下

​​3210

給現在我面臨着一個授權一些困難的tuitorial。我希望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)); 
    } 
} 

我試着[授權]以上,但不是爲我正常工作

任何幫助將不勝感激。

謝謝。

+0

'[Authorize]'不適合你嗎? – Tobberoth

回答

0

我也在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

4

你有創建如下新屬性: -

[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()); 

,你還可以添加它perticular方法或類似以下

[AuthorizeAttribute] 
public class TestController : ApiController 
1

有保護Web API應用程序的方法很多。基本身份驗證,OAuth,HMAC,API密鑰,自定義令牌。一個好的首發可以找到here其中還提供了一個示例應用程序下載。