Authorization of Web Api
本文关键字:Api Web of Authorization | 更新日期: 2024-10-20 10:15:21
我正在使用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));
}
}
我已经用[授权]尝试了上述操作,但对我来说无法正常工作
如有任何帮助,我们将不胜感激。
谢谢。
您必须创建如下新属性:-
[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;
}
}
}
}
创建上述filter属性后,您可以将其添加到webapiconfig.cs文件中,如下所示,这样它将过滤您的所有请求。
config.Filters.Add(new AuthorizeAttribute());
您也可以添加它用于特定的方法或类,如下面的
[AuthorizeAttribute]
public class TestController : ApiController
有许多方法可以保护Web Api应用程序的安全。基本身份验证、OAuth、HMAC、API密钥、自定义令牌。在这里可以找到一个好的入门程序,它还提供了一个下载的示例应用程序。
我还开发了一个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
阅读此处